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

Commit f6b23574 authored by chelseahao's avatar chelseahao Committed by Chelsea Hao
Browse files

[Audiosharing] Add tests.

Test: atest -c com.android.settings.connecteddevice.audiosharing.audiostreams
Bug: 308368124
Change-Id: I6322ccbb5deffe2bc169a898ef0208e135caa819
parent 8a8c89a4
Loading
Loading
Loading
Loading
+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);
+3 −1
Original line number Diff line number Diff line
@@ -139,8 +139,10 @@ public class AudioStreamsHelper {
                .toList();
    }

    /** Retrieves LocalBluetoothLeBroadcastAssistant. */
    @VisibleForTesting
    @Nullable
    LocalBluetoothLeBroadcastAssistant getLeBroadcastAssistant() {
    public LocalBluetoothLeBroadcastAssistant getLeBroadcastAssistant() {
        return mLeBroadcastAssistant;
    }

+327 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.audiostreams;

import static com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsDashboardFragment.KEY_BROADCAST_METADATA;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;

import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.content.Intent;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider;

import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.VolumeControlProfile;
import com.android.settingslib.flags.Flags;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.androidx.fragment.FragmentController;

import java.util.ArrayList;
import java.util.List;

@RunWith(RobolectricTestRunner.class)
@Config(
        shadows = {
            ShadowBluetoothAdapter.class,
            ShadowBluetoothUtils.class,
        })
public class AudioStreamConfirmDialogTest {
    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    private static final String VALID_METADATA =
            "BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
                    + "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
    private static final String DEVICE_NAME = "device_name";
    private final Context mContext = ApplicationProvider.getApplicationContext();
    @Mock private LocalBluetoothManager mLocalBluetoothManager;
    @Mock private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
    @Mock private LocalBluetoothLeBroadcast mBroadcast;
    @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
    @Mock private VolumeControlProfile mVolumeControl;
    @Mock private BluetoothDevice mBluetoothDevice;
    private AudioStreamConfirmDialog mDialogFragment;

    @Before
    public void setUp() {
        ShadowBluetoothAdapter shadowBluetoothAdapter =
                Shadow.extract(BluetoothAdapter.getDefaultAdapter());
        shadowBluetoothAdapter.setEnabled(true);
        shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
                BluetoothStatusCodes.FEATURE_SUPPORTED);
        shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
                BluetoothStatusCodes.FEATURE_SUPPORTED);

        ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
        when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile())
                .thenReturn(mAssistant);
        when(mLocalBluetoothProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl);
        when(mBroadcast.isProfileReady()).thenReturn(true);
        when(mAssistant.isProfileReady()).thenReturn(true);
        when(mVolumeControl.isProfileReady()).thenReturn(true);

        mDialogFragment = new AudioStreamConfirmDialog();
    }

    @After
    public void tearDown() {
        ShadowBluetoothUtils.reset();
        mDialogFragment.dismiss();
    }

    @Test
    public void showDialog_unsupported() {
        mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
        FragmentController.setupFragment(
                mDialogFragment,
                FragmentActivity.class,
                /* containerViewId= */ 0,
                /* bundle= */ null);
        shadowMainLooper().idle();

        assertThat(mDialogFragment.getMetricsCategory())
                .isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_FEATURE_UNSUPPORTED);

        var dialog = mDialogFragment.getDialog();
        assertThat(dialog).isNotNull();
        assertThat(dialog.isShowing()).isTrue();
        TextView title = dialog.findViewById(R.id.dialog_title);
        assertThat(title).isNotNull();
        assertThat(title.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
        TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
        assertThat(subtitle1).isNotNull();
        assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
        TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
        assertThat(subtitle2).isNotNull();
        assertThat(subtitle2.getText())
                .isEqualTo(
                        mContext.getString(
                                R.string.audio_streams_dialog_unsupported_device_subtitle));
        View leftButton = dialog.findViewById(R.id.left_button);
        assertThat(leftButton).isNotNull();
        assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
        assertThat(leftButton.hasOnClickListeners()).isFalse();
        View rightButton = dialog.findViewById(R.id.right_button);
        assertThat(rightButton).isNotNull();
        assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(rightButton.hasOnClickListeners()).isTrue();
    }

    @Test
    public void showDialog_noLeDevice() {
        FragmentController.setupFragment(
                mDialogFragment,
                FragmentActivity.class,
                /* containerViewId= */ 0,
                /* bundle= */ null);
        shadowMainLooper().idle();

        assertThat(mDialogFragment.getMetricsCategory())
                .isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_NO_LE_DEVICE);

        var dialog = mDialogFragment.getDialog();
        assertThat(dialog).isNotNull();
        assertThat(dialog.isShowing()).isTrue();

        TextView title = dialog.findViewById(R.id.dialog_title);
        assertThat(title).isNotNull();
        assertThat(title.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_title));
        TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
        assertThat(subtitle1).isNotNull();
        assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
        TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
        assertThat(subtitle2).isNotNull();
        assertThat(subtitle2.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_subtitle));
        View leftButton = dialog.findViewById(R.id.left_button);
        assertThat(leftButton).isNotNull();
        assertThat(leftButton.getVisibility()).isEqualTo(View.VISIBLE);
        Button rightButton = dialog.findViewById(R.id.right_button);
        assertThat(rightButton).isNotNull();
        assertThat(rightButton.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_no_le_device_button));
        assertThat(rightButton.hasOnClickListeners()).isTrue();
    }

    @Test
    public void showDialog_noMetadata() {
        List<BluetoothDevice> devices = new ArrayList<>();
        devices.add(mBluetoothDevice);
        when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
        when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);

        FragmentController.setupFragment(
                mDialogFragment,
                FragmentActivity.class,
                /* containerViewId= */ 0,
                /* bundle= */ null);
        shadowMainLooper().idle();

        assertThat(mDialogFragment.getMetricsCategory())
                .isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_DATA_ERROR);

        var dialog = mDialogFragment.getDialog();
        assertThat(dialog).isNotNull();
        assertThat(dialog.isShowing()).isTrue();
        TextView title = dialog.findViewById(R.id.dialog_title);
        assertThat(title).isNotNull();
        assertThat(title.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
        TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
        assertThat(subtitle1).isNotNull();
        assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
        TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
        assertThat(subtitle2).isNotNull();
        assertThat(subtitle2.getText())
                .isEqualTo(
                        mContext.getString(R.string.audio_streams_dialog_cannot_play, DEVICE_NAME));
        View leftButton = dialog.findViewById(R.id.left_button);
        assertThat(leftButton).isNotNull();
        assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
        assertThat(leftButton.hasOnClickListeners()).isFalse();
        View rightButton = dialog.findViewById(R.id.right_button);
        assertThat(rightButton).isNotNull();
        assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(rightButton.hasOnClickListeners()).isTrue();
    }

    @Test
    public void showDialog_invalidMetadata() {
        List<BluetoothDevice> devices = new ArrayList<>();
        devices.add(mBluetoothDevice);
        when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
        when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);

        Intent intent = new Intent();
        intent.putExtra(KEY_BROADCAST_METADATA, "invalid");
        FragmentController.of(mDialogFragment, intent)
                .create(/* containerViewId= */ 0, /* bundle= */ null)
                .start()
                .resume()
                .visible()
                .get();
        shadowMainLooper().idle();

        assertThat(mDialogFragment.getMetricsCategory())
                .isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_DATA_ERROR);

        var dialog = mDialogFragment.getDialog();
        assertThat(dialog).isNotNull();
        assertThat(dialog.isShowing()).isTrue();
        TextView title = dialog.findViewById(R.id.dialog_title);
        assertThat(title).isNotNull();
        assertThat(title.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_cannot_listen));
        TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
        assertThat(subtitle1).isNotNull();
        assertThat(subtitle1.getVisibility()).isEqualTo(View.GONE);
        TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
        assertThat(subtitle2).isNotNull();
        assertThat(subtitle2.getText())
                .isEqualTo(
                        mContext.getString(R.string.audio_streams_dialog_cannot_play, DEVICE_NAME));
        View leftButton = dialog.findViewById(R.id.left_button);
        assertThat(leftButton).isNotNull();
        assertThat(leftButton.getVisibility()).isEqualTo(View.GONE);
        assertThat(leftButton.hasOnClickListeners()).isFalse();
        View rightButton = dialog.findViewById(R.id.right_button);
        assertThat(rightButton).isNotNull();
        assertThat(rightButton.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(rightButton.hasOnClickListeners()).isTrue();
    }

    @Test
    public void showDialog_confirmListen() {
        List<BluetoothDevice> devices = new ArrayList<>();
        devices.add(mBluetoothDevice);
        when(mAssistant.getDevicesMatchingConnectionStates(any())).thenReturn(devices);
        when(mBluetoothDevice.getAlias()).thenReturn(DEVICE_NAME);

        Intent intent = new Intent();
        intent.putExtra(KEY_BROADCAST_METADATA, VALID_METADATA);
        FragmentController.of(mDialogFragment, intent)
                .create(/* containerViewId= */ 0, /* bundle= */ null)
                .start()
                .resume()
                .visible()
                .get();
        shadowMainLooper().idle();

        assertThat(mDialogFragment.getMetricsCategory())
                .isEqualTo(SettingsEnums.DIALOG_AUDIO_STREAM_CONFIRM_LISTEN);

        var dialog = mDialogFragment.getDialog();
        assertThat(dialog).isNotNull();
        assertThat(dialog.isShowing()).isTrue();
        TextView title = dialog.findViewById(R.id.dialog_title);
        assertThat(title).isNotNull();
        assertThat(title.getText())
                .isEqualTo(
                        mContext.getString(R.string.audio_streams_dialog_listen_to_audio_stream));
        TextView subtitle1 = dialog.findViewById(R.id.dialog_subtitle);
        assertThat(subtitle1).isNotNull();
        assertThat(subtitle1.getVisibility()).isEqualTo(View.VISIBLE);
        TextView subtitle2 = dialog.findViewById(R.id.dialog_subtitle_2);
        assertThat(subtitle2).isNotNull();
        assertThat(subtitle2.getText())
                .isEqualTo(
                        mContext.getString(
                                R.string.audio_streams_dialog_control_volume, DEVICE_NAME));
        View leftButton = dialog.findViewById(R.id.left_button);
        assertThat(leftButton).isNotNull();
        assertThat(leftButton.getVisibility()).isEqualTo(View.VISIBLE);
        Button rightButton = dialog.findViewById(R.id.right_button);
        assertThat(rightButton).isNotNull();
        assertThat(rightButton.getText())
                .isEqualTo(mContext.getString(R.string.audio_streams_dialog_listen));
        assertThat(rightButton.hasOnClickListeners()).isTrue();
    }
}
+233 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading