Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4774b37 authored by yqian's avatar yqian
Browse files

Update the audio sharing QR code logic to enable OEMs providing customized QR code image

Test: atest AudioSharingFeatureProviderImplTest
Bug: b/397137711
Flag: EXEMPT no-op

Change-Id: I124d6ded50faf9fa0ca06bd5b34d72e9399f3e59
parent 87a9cdf1
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -40,7 +40,9 @@ import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothPairingDetail;
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
import com.android.settingslib.bluetooth.BluetoothUtils;

import com.google.common.collect.Iterables;
@@ -75,6 +77,9 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
    private static Pair<Integer, Object>[] sEventData = new Pair[0];
    @Nullable private static Fragment sHost;

    AudioSharingFeatureProvider audioSharingFeatureProvider =
            FeatureFactory.getFeatureFactory().getAudioSharingFeatureProvider();

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE;
@@ -158,6 +163,9 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
            Log.d(TAG, "Create dialog error: null deviceItems");
            return builder.build();
        }
        BluetoothLeBroadcastMetadata metadata = arguments.getParcelable(
                BUNDLE_KEY_BROADCAST_METADATA, BluetoothLeBroadcastMetadata.class);
        Drawable qrCodeDrawable = null;
        if (deviceItems.isEmpty()) {
            builder.setTitle(R.string.audio_sharing_share_dialog_title)
                    .setCustomPositiveButton(
@@ -181,9 +189,7 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
                                }
                                launcher.launch();
                            });
            BluetoothLeBroadcastMetadata metadata = arguments.getParcelable(
                    BUNDLE_KEY_BROADCAST_METADATA, BluetoothLeBroadcastMetadata.class);
            Drawable qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata,
            qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata,
                    getContext()).orElse(null);
            if (qrCodeDrawable != null) {
                String broadcastName =
@@ -195,8 +201,7 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
                        new String(metadata.getBroadcastCode(), StandardCharsets.UTF_8)) :
                        getString(R.string.audio_sharing_dialog_qr_code_content_no_password,
                                broadcastName);
                builder.setCustomImage(qrCodeDrawable)
                        .setCustomMessage(message)
                builder.setCustomMessage(message)
                        .setCustomMessage2(R.string.audio_sharing_dialog_pair_new_device_content)
                        .setCustomNegativeButton(R.string.audio_streams_dialog_close,
                                v -> onCancelClick());
@@ -251,7 +256,17 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
                    .setCustomNegativeButton(
                            com.android.settings.R.string.cancel, v -> onCancelClick());
        }
        return builder.build();
        Dialog dialog = builder.build();
        dialog.show();
        if (deviceItems.isEmpty() && qrCodeDrawable != null) {
            audioSharingFeatureProvider.setQrCode(
                    this,
                    dialog.getWindow().getDecorView(),
                    R.id.description_image,
                    qrCodeDrawable,
                    BluetoothLeBroadcastMetadataExt.INSTANCE.toQrCodeString(metadata));
        }
        return dialog;
    }

    private void onCancelClick() {
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.connecteddevice.audiosharing;

import android.annotation.IdRes;
import androidx.annotation.NonNull;
import android.graphics.drawable.Drawable;
import android.view.View;

import androidx.fragment.app.Fragment;

/** Feature provider for the audio sharing features. */
public interface AudioSharingFeatureProvider {
    /**
     * Sets the QR code for audio sharing dialogs
     *
     * @param fragment the fragment to be updated
     * @param qrcodeContainer the view to be updated
     * @param qrCodeImageViewId the view ID to search for
     * @param drawable the drawable asset of the QR code
     * @param qrCode the value of the qrCode
     */
    public void setQrCode(
            @NonNull Fragment fragment,
            @NonNull View qrcodeContainer,
            @IdRes int qrCodeImageViewId,
            @NonNull Drawable drawable,
            @NonNull String qrCode);
}
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.connecteddevice.audiosharing;

import android.annotation.IdRes;
import androidx.annotation.NonNull;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;

import androidx.fragment.app.Fragment;

/** Default implementation for {@link AudioSharingFeatureProvider} */
public class AudioSharingFeatureProviderImpl implements AudioSharingFeatureProvider {
    public void setQrCode(
            @NonNull Fragment fragment,
            @NonNull View qrcodeContainer,
            @IdRes int qrCodeImageViewId,
            @NonNull Drawable drawable,
            @NonNull String qrCode) {
        ImageView imageView = ((ImageView) qrcodeContainer.requireViewById(qrCodeImageViewId));
        imageView.setImageDrawable(drawable);
        imageView.setVisibility(View.VISIBLE);
    }
}
+51 −36
Original line number Diff line number Diff line
@@ -37,11 +37,13 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;

import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider;
import com.android.settings.core.InstrumentedFragment;
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.qrcode.QrCodeGenerator;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settings.overlay.FeatureFactory;

import com.google.zxing.WriterException;

@@ -52,6 +54,9 @@ import java.util.Optional;
public class AudioStreamsQrCodeFragment extends InstrumentedFragment {
    private static final String TAG = "AudioStreamsQrCodeFragment";

    AudioSharingFeatureProvider audioSharingFeatureProvider =
            FeatureFactory.getFeatureFactory().getAudioSharingFeatureProvider();

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.AUDIO_STREAM_QR_CODE;
@@ -68,22 +73,29 @@ public class AudioStreamsQrCodeFragment extends InstrumentedFragment {
        super.onViewCreated(view, savedInstanceState);
        // Collapse or expand the app bar based on orientation for better display the qr code image.
        AudioStreamsHelper.configureAppBarByOrientation(getActivity());
        var unused = ThreadUtils.postOnBackgroundThread(
        var unused =
                ThreadUtils.postOnBackgroundThread(
                        () -> {
                            BluetoothLeBroadcastMetadata broadcastMetadata = getBroadcastMetadata();
                            if (broadcastMetadata == null) {
                                return;
                            }
                    Drawable drawable = getQrCodeDrawable(broadcastMetadata, getActivity()).orElse(
                            null);
                            Drawable drawable =
                                    getQrCodeDrawable(broadcastMetadata, getActivity())
                                            .orElse(null);
                            if (drawable == null) {
                                return;
                            }

                            ThreadUtils.postOnMainThread(
                                    () -> {
                                ((ImageView) view.requireViewById(R.id.qrcode_view))
                                        .setImageDrawable(drawable);
                                        audioSharingFeatureProvider.setQrCode(
                                                this,
                                                view,
                                                R.id.qrcode_view,
                                                drawable,
                                                BluetoothLeBroadcastMetadataExt.INSTANCE
                                                        .toQrCodeString(broadcastMetadata));
                                        if (broadcastMetadata.getBroadcastCode() != null) {
                                            String password =
                                                    new String(
@@ -91,15 +103,18 @@ public class AudioStreamsQrCodeFragment extends InstrumentedFragment {
                                                            StandardCharsets.UTF_8);
                                            String passwordText =
                                                    getString(
                                                    R.string.audio_streams_qr_code_page_password,
                                                            R.string
                                                                    .audio_streams_qr_code_page_password,
                                                            password);
                                            ((TextView) view.requireViewById(R.id.password))
                                                    .setText(passwordText);
                                        }
                                TextView summaryView = view.requireViewById(android.R.id.summary);
                                        TextView summaryView =
                                                view.requireViewById(android.R.id.summary);
                                        String summary =
                                                getString(
                                                R.string.audio_streams_qr_code_page_description,
                                                        R.string
                                                                .audio_streams_qr_code_page_description,
                                                        broadcastMetadata.getBroadcastName());
                                        summaryView.setText(summary);
                                    });
+6 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.settings.biometrics.BiometricsFeatureProvider
import com.android.settings.biometrics.face.FaceFeatureProvider
import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider
import com.android.settings.bluetooth.BluetoothFeatureProvider
import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider
import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider
import com.android.settings.dashboard.DashboardFeatureProvider
@@ -179,6 +180,11 @@ abstract class FeatureFactory {
     */
    abstract val fastPairFeatureProvider: FastPairFeatureProvider

    /**
     * Gets implementation for audio sharing related feature.
     */
    abstract val audioSharingFeatureProvider: AudioSharingFeatureProvider

    /**
     * Gets implementation for Private Space account login feature.
     */
Loading