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

Commit 24d84119 authored by Chelsea Hao's avatar Chelsea Hao Committed by Android (Google) Code Review
Browse files

Merge changes I6322ccbb,Idc96c23d into main

* changes:
  [Audiosharing] Add tests.
  [Audiosharing] Add logging 3.
parents 0cc20946 f6b23574
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.Context;

import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;

import com.android.settings.R;
import com.android.settingslib.utils.ThreadUtils;
@@ -78,12 +79,10 @@ class AddSourceWaitForResponseState extends AudioStreamStateHandler {
                            ThreadUtils.postOnMainThread(
                                    () -> {
                                        if (controller.getFragment() != null) {
                                            AudioStreamsDialogFragment.show(
                                            showBroadcastUnavailableNoRetryDialog(
                                                    controller.getFragment(),
                                                    getBroadcastUnavailableNoRetryDialog(
                                                    preference.getContext(),
                                                            AudioStreamsHelper.getBroadcastName(
                                                                    metadata)));
                                                    AudioStreamsHelper.getBroadcastName(metadata));
                                        }
                                    });
                        }
@@ -103,13 +102,21 @@ class AddSourceWaitForResponseState extends AudioStreamStateHandler {
        return AudioStreamsProgressCategoryController.AudioStreamState.ADD_SOURCE_WAIT_FOR_RESPONSE;
    }

    private AudioStreamsDialogFragment.DialogBuilder getBroadcastUnavailableNoRetryDialog(
            Context context, String broadcastName) {
        return new AudioStreamsDialogFragment.DialogBuilder(context)
                .setTitle(context.getString(R.string.audio_streams_dialog_stream_is_not_available))
    private void showBroadcastUnavailableNoRetryDialog(
            Fragment fragment, Context context, String broadcastName) {
        var broadcastUnavailableNoRetryDialog =
                new AudioStreamsDialogFragment.DialogBuilder(context)
                        .setTitle(
                                context.getString(
                                        R.string.audio_streams_dialog_stream_is_not_available))
                        .setSubTitle1(broadcastName)
                        .setSubTitle2(context.getString(R.string.audio_streams_is_not_playing))
                        .setRightButtonText(context.getString(R.string.audio_streams_dialog_close))
                        .setRightButtonOnClickListener(AlertDialog::dismiss);

        AudioStreamsDialogFragment.show(
                fragment,
                broadcastUnavailableNoRetryDialog,
                SettingsEnums.DIALOG_AUDIO_STREAM_MAIN_JOIN_FAILED_TIMEOUT);
    }
}
+101 −64
Original line number Diff line number Diff line
@@ -21,101 +21,84 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
import android.app.Activity;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;

import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;

import com.google.common.base.Strings;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;

public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {
    private static final String TAG = "AudioStreamConfirmDialog";
    private static final int DEFAULT_DEVICE_NAME = R.string.audio_streams_dialog_default_device;
    @Nullable private LocalBluetoothManager mLocalBluetoothManager;
    @Nullable private LocalBluetoothProfileManager mProfileManager;
    private Context mContext;
    @Nullable private Activity mActivity;
    @Nullable private String mBroadcastMetadataStr;
    @Nullable private BluetoothLeBroadcastMetadata mBroadcastMetadata;
    private boolean mIsRequestValid = false;
    @Nullable private BluetoothDevice mConnectedDevice;
    private int mAudioStreamConfirmDialogId = SettingsEnums.PAGE_UNKNOWN;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setShowsDialog(true);
    public void onAttach(Context context) {
        mContext = context;
        mActivity = getActivity();
        if (mActivity == null) {
            Log.w(TAG, "onCreate() mActivity is null!");
            Log.w(TAG, "onAttach() mActivity is null!");
            return;
        }
        mLocalBluetoothManager = Utils.getLocalBluetoothManager(mActivity);
        mProfileManager =
                mLocalBluetoothManager == null ? null : mLocalBluetoothManager.getProfileManager();
        mBroadcastMetadataStr = mActivity.getIntent().getStringExtra(KEY_BROADCAST_METADATA);
        if (Strings.isNullOrEmpty(mBroadcastMetadataStr)) {
            Log.w(TAG, "onCreate() mBroadcastMetadataStr is null or empty!");
            return;
        }
        mBroadcastMetadata =
                BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(
                        mBroadcastMetadataStr);
        if (mBroadcastMetadata == null) {
            Log.w(TAG, "onCreate() mBroadcastMetadata is null!");
        } else {
            mIsRequestValid = true;
        Intent intent = mActivity.getIntent();
        mBroadcastMetadata = getMetadata(intent);
        mConnectedDevice = getConnectedDevice();
        mAudioStreamConfirmDialogId =
                getDialogId(mBroadcastMetadata != null, mConnectedDevice != null);
        super.onAttach(context);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setShowsDialog(true);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        if (!AudioSharingUtils.isFeatureEnabled()) {
            return getUnsupporteDialog();
        }
        if (AudioSharingUtils.isAudioSharingProfileReady(mProfileManager)) {
            CachedBluetoothDevice connectedLeDevice =
                    AudioStreamsHelper.getCachedBluetoothDeviceInSharingOrLeConnected(
                                    mLocalBluetoothManager)
                            .orElse(null);
            if (connectedLeDevice == null) {
                return getNoLeDeviceDialog();
            }
            String deviceName = connectedLeDevice.getName();
            return mIsRequestValid ? getConfirmDialog(deviceName) : getErrorDialog(deviceName);
        }
        Log.d(TAG, "onCreateDialog() : profile not ready!");
        String defaultDeviceName =
                mActivity != null ? mActivity.getString(DEFAULT_DEVICE_NAME) : "";
        return mIsRequestValid
                ? getConfirmDialog(defaultDeviceName)
                : getErrorDialog(defaultDeviceName);
        return switch (mAudioStreamConfirmDialogId) {
            case SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_FEATURE_UNSUPPORTED ->
                    getUnsupportedDialog();
            case SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_NO_LE_DEVICE -> getNoLeDeviceDialog();
            case SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_LISTEN -> getConfirmDialog();
            default -> getErrorDialog();
        };
    }

    @Override
    public int getMetricsCategory() {
        // TODO(chelseahao): update metrics id
        return 0;
        return mAudioStreamConfirmDialogId;
    }

    private Dialog getConfirmDialog(String name) {
    private Dialog getConfirmDialog() {
        return new AudioStreamsDialogFragment.DialogBuilder(getActivity())
                .setTitle(getString(R.string.audio_streams_dialog_listen_to_audio_stream))
                .setSubTitle1(
                        mBroadcastMetadata != null
                                ? AudioStreamsHelper.getBroadcastName(mBroadcastMetadata)
                                : "")
                .setSubTitle2(getString(R.string.audio_streams_dialog_control_volume, name))
                .setSubTitle2(
                        getString(
                                R.string.audio_streams_dialog_control_volume,
                                getConnectedDeviceName()))
                .setLeftButtonText(getString(com.android.settings.R.string.cancel))
                .setLeftButtonOnClickListener(
                        unused -> {
@@ -127,6 +110,10 @@ public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {
                .setRightButtonText(getString(R.string.audio_streams_dialog_listen))
                .setRightButtonOnClickListener(
                        unused -> {
                            mMetricsFeatureProvider.action(
                                    getActivity(),
                                    SettingsEnums
                                            .ACTION_AUDIO_STREAM_CONFIRM_LAUNCH_MAIN_BUTTON_CLICK);
                            launchAudioStreamsActivity();
                            dismiss();
                            if (mActivity != null) {
@@ -136,7 +123,7 @@ public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {
                .build();
    }

    private Dialog getUnsupporteDialog() {
    private Dialog getUnsupportedDialog() {
        return new AudioStreamsDialogFragment.DialogBuilder(getActivity())
                .setTitle(getString(R.string.audio_streams_dialog_cannot_listen))
                .setSubTitle2(getString(R.string.audio_streams_dialog_unsupported_device_subtitle))
@@ -151,10 +138,13 @@ public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {
                .build();
    }

    private Dialog getErrorDialog(String name) {
    private Dialog getErrorDialog() {
        return new AudioStreamsDialogFragment.DialogBuilder(getActivity())
                .setTitle(getString(R.string.audio_streams_dialog_cannot_listen))
                .setSubTitle2(getString(R.string.audio_streams_dialog_cannot_play, name))
                .setSubTitle2(
                        getString(
                                R.string.audio_streams_dialog_cannot_play,
                                getConnectedDeviceName()))
                .setRightButtonText(getString(R.string.audio_streams_dialog_close))
                .setRightButtonOnClickListener(
                        unused -> {
@@ -181,11 +171,12 @@ public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {
                .setRightButtonText(getString(R.string.audio_streams_dialog_no_le_device_button))
                .setRightButtonOnClickListener(
                        dialog -> {
                            if (mActivity != null) {
                                mActivity.startActivity(
                                        new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)
                                                .setPackage(mActivity.getPackageName()));
                            }
                            new SubSettingLauncher(mContext)
                                    .setDestination(
                                            ConnectedDeviceDashboardFragment.class.getName())
                                    .setSourceMetricsCategory(
                                            SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_NO_LE_DEVICE)
                                    .launch();
                            dismiss();
                            if (mActivity != null) {
                                mActivity.finish();
@@ -196,14 +187,60 @@ public class AudioStreamConfirmDialog extends InstrumentedDialogFragment {

    private void launchAudioStreamsActivity() {
        Bundle bundle = new Bundle();
        bundle.putString(KEY_BROADCAST_METADATA, mBroadcastMetadataStr);
        bundle.putParcelable(KEY_BROADCAST_METADATA, mBroadcastMetadata);
        if (mActivity != null) {
            new SubSettingLauncher(getActivity())
                    .setTitleText(getString(R.string.audio_streams_activity_title))
                    .setDestination(AudioStreamsDashboardFragment.class.getName())
                    .setArguments(bundle)
                    .setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
                    .setSourceMetricsCategory(getMetricsCategory())
                    .launch();
        }
    }

    private @Nullable BluetoothLeBroadcastMetadata getMetadata(Intent intent) {
        String metadata = intent.getStringExtra(KEY_BROADCAST_METADATA);
        if (metadata == null || metadata.isEmpty()) {
            return null;
        }
        return BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(metadata);
    }

    private int getDialogId(boolean hasMetadata, boolean hasConnectedDevice) {
        if (!AudioSharingUtils.isFeatureEnabled()) {
            return SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_FEATURE_UNSUPPORTED;
        }
        if (!hasConnectedDevice) {
            return SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_NO_LE_DEVICE;
        }
        return hasMetadata
                ? SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_LISTEN
                : SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_DATA_ERROR;
    }

    @Nullable
    private BluetoothDevice getConnectedDevice() {
        var localBluetoothManager = Utils.getLocalBluetoothManager(getActivity());
        if (localBluetoothManager == null) {
            return null;
        }
        LocalBluetoothLeBroadcastAssistant assistant =
                localBluetoothManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
        if (assistant == null) {
            return null;
        }
        var devices =
                assistant.getDevicesMatchingConnectionStates(
                        new int[] {BluetoothProfile.STATE_CONNECTED});
        return devices.isEmpty() ? null : devices.get(0);
    }

    private String getConnectedDeviceName() {
        if (mConnectedDevice != null) {
            String alias = mConnectedDevice.getAlias();
            return TextUtils.isEmpty(alias) ? getString(DEFAULT_DEVICE_NAME) : alias;
        }
        Log.w(TAG, "getConnectedDeviceName : no connected device!");
        return getString(DEFAULT_DEVICE_NAME);
    }
}
+4 −3
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.util.Log;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
@@ -196,7 +197,7 @@ public class AudioStreamMediaService extends Service {
    // override this value. Otherwise, we raise the volume to 25 when the play button is clicked.
    private int mLatestPositiveVolume = 25;
    private boolean mIsMuted = false;
    @Nullable private MediaSession mLocalSession;
    @VisibleForTesting @Nullable MediaSession mLocalSession;

    @Override
    public void onCreate() {
@@ -228,7 +229,7 @@ public class AudioStreamMediaService extends Service {
            NotificationChannel notificationChannel =
                    new NotificationChannel(
                            CHANNEL_ID,
                            this.getString(com.android.settings.R.string.bluetooth),
                            getString(com.android.settings.R.string.bluetooth),
                            NotificationManager.IMPORTANCE_HIGH);
            mNotificationManager.createNotificationChannel(notificationChannel);
        }
@@ -403,7 +404,7 @@ public class AudioStreamMediaService extends Service {
                new Notification.Builder(this, CHANNEL_ID)
                        .setSmallIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing)
                        .setStyle(mediaStyle)
                        .setContentText(this.getString(BROADCAST_CONTENT_TEXT))
                        .setContentText(getString(BROADCAST_CONTENT_TEXT))
                        .setSilent(true);
        return notificationBuilder.build();
    }
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        if (!isAvailable()) return;
        super.onStart(owner);
        if (mLocalBtManager != null) {
            mLocalBtManager.getEventManager().registerCallback(mBluetoothCallback);
@@ -68,6 +69,7 @@ public class AudioStreamsCategoryController extends AudioSharingBasePreferenceCo

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        if (!isAvailable()) return;
        super.onStop(owner);
        if (mLocalBtManager != null) {
            mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback);
+8 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
@@ -43,15 +44,16 @@ import java.util.function.Consumer;
public class AudioStreamsDialogFragment extends InstrumentedDialogFragment {
    private static final String TAG = "AudioStreamsDialogFragment";
    private final DialogBuilder mDialogBuilder;
    private int mDialogId = SettingsEnums.PAGE_UNKNOWN;

    AudioStreamsDialogFragment(DialogBuilder dialogBuilder) {
    AudioStreamsDialogFragment(DialogBuilder dialogBuilder, int dialogId) {
        mDialogBuilder = dialogBuilder;
        mDialogId = dialogId;
    }

    @Override
    public int getMetricsCategory() {
        // TODO(chelseahao): update metrics id
        return 0;
        return mDialogId;
    }

    @Override
@@ -64,14 +66,15 @@ public class AudioStreamsDialogFragment extends InstrumentedDialogFragment {
     *
     * @param host The fragment to host the dialog.
     * @param dialogBuilder The builder for constructing the dialog.
     * @param dialogId The dialog settings enum for logging
     */
    public static void show(Fragment host, DialogBuilder dialogBuilder) {
    public static void show(Fragment host, DialogBuilder dialogBuilder, int dialogId) {
        if (!host.isAdded()) {
            Log.w(TAG, "The host fragment is not added to the activity!");
            return;
        }
        FragmentManager manager = host.getChildFragmentManager();
        (new AudioStreamsDialogFragment(dialogBuilder)).show(manager, TAG);
        (new AudioStreamsDialogFragment(dialogBuilder, dialogId)).show(manager, TAG);
    }

    static void dismissAll(Fragment host) {
Loading