Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +114 −26 Original line number Diff line number Diff line Loading @@ -41,7 +41,9 @@ import android.widget.CompoundButton.OnCheckedChangeListener; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; Loading Loading @@ -69,7 +71,6 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; Loading Loading @@ -113,14 +114,21 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private final Executor mExecutor; private final MetricsFeatureProvider mMetricsFeatureProvider; private final OnAudioSharingStateChangedListener mListener; @VisibleForTesting IntentFilter mIntentFilter; private Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>(); @Nullable private AudioSharingDeviceItem mTargetActiveItem; private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>(); @VisibleForTesting IntentFilter mIntentFilter; private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private AtomicInteger mIntentHandleStage = new AtomicInteger(StartIntentHandleStage.TO_HANDLE.ordinal()); // The sinks in adding source process. We show the progress dialog based on this list. private CopyOnWriteArrayList<BluetoothDevice> mSinksInAdding = new CopyOnWriteArrayList<>(); // The primary/active sinks in adding source process. // To avoid users advance to share then pair flow before the primary/active sinks successfully // join the audio sharing, we will wait for the process complete for this list of sinks and then // popup audio sharing dialog with options to pair new device. private CopyOnWriteArrayList<BluetoothDevice> mSinksToWaitFor = new CopyOnWriteArrayList<>(); private AtomicBoolean mStoppingSharing = new AtomicBoolean(false); @VisibleForTesting BroadcastReceiver mReceiver = Loading Loading @@ -153,6 +161,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController public void onBroadcastStartFailed(int reason) { Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); updateSwitch(); showRetryDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_START_FAILED, Loading @@ -178,7 +187,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + reason + ", broadcastId = " + broadcastId); mStoppingSharing.compareAndSet(true, false); updateSwitch(); AudioSharingUtils.postOnMainThread(mContext, () -> dismissStaleDialogsOtherThanRetryDialog()); AudioSharingUtils.toastMessage( mContext, mContext.getString(R.string.audio_sharing_sharing_stopped_label)); Loading Loading @@ -219,7 +231,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController TAG, "Skip handleOnBroadcastReady: null assistant or " + "sink has active local source."); cleanUp(); cleanUpStatesForStartSharing(); return; } handleOnBroadcastReady(); Loading Loading @@ -264,17 +276,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + source + ", reason = " + reason); if (mSinksInAdding.contains(sink)) { stopAudioSharing(); showRetryDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED, SettingsEnums.AUDIO_SHARING_SETTINGS); AudioSharingUtils.toastMessage( mContext, String.format( Locale.US, "Fail to add source to %s reason %d", sink.getAddress(), reason)); } } @Override Loading @@ -298,6 +307,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController @NonNull BluetoothDevice sink, int sourceId, @NonNull BluetoothLeBroadcastReceiveState state) { if (mStoppingSharing.get()) { Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast"); return; } if (BluetoothUtils.isConnected(state)) { if (mSinksInAdding.contains(sink)) { mSinksInAdding.remove(sink); Loading @@ -305,6 +318,22 @@ public class AudioSharingSwitchBarController extends BasePreferenceController dismissLoadingStateDialogIfNeeded(); Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink + ", remaining sinks = " + mSinksInAdding); if (mSinksToWaitFor.contains(sink)) { mSinksToWaitFor.remove(sink); if (mSinksToWaitFor.isEmpty()) { // To avoid users advance to share then pair flow before the // primary/active sinks successfully join the audio sharing, // popup dialog till adding source complete for mSinksToWaitFor. Pair<Integer, Object>[] eventData = AudioSharingUtils.buildAudioSharingDialogEventData( SettingsEnums.AUDIO_SHARING_SETTINGS, SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE, /* userTriggered= */ false, /* deviceCountInSharing= */ 1, /* candidateDeviceCount= */ 0); showAudioSharingDialog(eventData); } } } } }; Loading Loading @@ -411,6 +440,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController return; } stopAudioSharing(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF); } } Loading Loading @@ -553,9 +584,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private void stopAudioSharing() { if (mBroadcast != null) { mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId()); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF); int broadcastId = mBroadcast.getLatestBroadcastId(); if (broadcastId != -1) { mBroadcast.stopBroadcast(broadcastId); mStoppingSharing.compareAndSet(false, true); mSinksInAdding.clear(); mSinksToWaitFor.clear(); } cleanUpStatesForStartSharing(); } } Loading Loading @@ -617,11 +653,22 @@ public class AudioSharingSwitchBarController extends BasePreferenceController /* userTriggered= */ false, /* deviceCountInSharing= */ targetActiveSinks.isEmpty() ? 0 : 1, /* candidateDeviceCount= */ mDeviceItemsForSharing.size()); // Auto add primary/active sinks w/o user interactions. if (!targetActiveSinks.isEmpty() && mTargetActiveItem != null) { Log.d(TAG, "handleOnBroadcastReady: automatically add source to active sinks."); addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName()); // To avoid users advance to share then pair flow before the primary/active sinks // successfully join the audio sharing, save the primary/active sinks in mSinksToWaitFor // and popup dialog till adding source complete for these sinks. if (mDeviceItemsForSharing.isEmpty()) { mSinksToWaitFor.clear(); mSinksToWaitFor.addAll(targetActiveSinks); } mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING); mTargetActiveItem = null; // When audio sharing page is brought up by intent with EXTRA_START_LE_AUDIO_SHARING // == true, plus there is one active lea headset and one connected lea headset, we // should auto add these sinks without user interactions. if (mIntentHandleStage.compareAndSet( StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(), StartIntentHandleStage.HANDLED.ordinal()) Loading @@ -631,31 +678,42 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault( target.getGroupId(), ImmutableList.of()); addSourceToTargetSinks(targetSinks, target.getName()); cleanUp(); cleanUpStatesForStartSharing(); // TODO: Add metric for auto add by intent return; } } // Still mark intent as handled if early returned due to preconditions not met mIntentHandleStage.compareAndSet( StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(), StartIntentHandleStage.HANDLED.ordinal()); if (mFragment == null) { Log.d(TAG, "handleOnBroadcastReady: dialog fail to show due to null fragment."); // Clean up states before early return. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); return; } showDialog(eventData); // To avoid users advance to share then pair flow before the primary/active sinks // successfully join the audio sharing, popup dialog till adding source complete for // mSinksToWaitFor. if (mSinksToWaitFor.isEmpty() && !mStoppingSharing.get()) { showAudioSharingDialog(eventData); } } private void showDialog(Pair<Integer, Object>[] eventData) { private void showAudioSharingDialog(Pair<Integer, Object>[] eventData) { if (!BluetoothUtils.isBroadcasting(mBtManager)) { Log.d(TAG, "Skip showAudioSharingDialog, broadcast is stopped"); return; } AudioSharingDialogFragment.DialogEventListener listener = new AudioSharingDialogFragment.DialogEventListener() { @Override public void onPositiveClick() { // Could go to other pages, dismiss the loading dialog. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); } @Override Loading @@ -663,14 +721,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault( item.getGroupId(), ImmutableList.of()); addSourceToTargetSinks(targetSinks, item.getName()); cleanUp(); cleanUpStatesForStartSharing(); } @Override public void onCancelClick() { // Could go to other pages, dismiss the loading dialog. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); } }; AudioSharingUtils.postOnMainThread( Loading @@ -684,6 +742,36 @@ public class AudioSharingSwitchBarController extends BasePreferenceController }); } private void showRetryDialog() { AudioSharingUtils.postOnMainThread(mContext, () -> { // Remove all opening dialogs before show retry dialog dismissStaleDialogsOtherThanRetryDialog(); AudioSharingRetryDialogFragment.show(mFragment); }); } @UiThread private void dismissStaleDialogsOtherThanRetryDialog() { List<Fragment> fragments = new ArrayList<Fragment>(); try { if (mFragment != null) { fragments = mFragment.getChildFragmentManager().getFragments(); } } catch (Exception e) { Log.e(TAG, "Fail to dismiss stale dialogs: " + e.getMessage()); } for (Fragment fragment : fragments) { if (fragment != null && fragment instanceof DialogFragment && !(fragment instanceof AudioSharingRetryDialogFragment) && ((DialogFragment) fragment).getDialog() != null) { Log.d(TAG, "Remove stale dialog = " + fragment.getTag()); ((DialogFragment) fragment).dismiss(); } } } private static final class MainSwitchAccessibilityDelegate extends View.AccessibilityDelegate { @Override public boolean onRequestSendAccessibilityEvent( Loading Loading @@ -742,10 +830,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks, @NonNull String sinkName) { mSinksInAdding.addAll(targetActiveSinks); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); // TODO: move to res once finalized String loadingMessage = "Sharing with " + sinkName + "..."; showLoadingStateDialog(loadingMessage); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); } private void showLoadingStateDialog(@NonNull String loadingMessage) { Loading @@ -760,7 +848,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController } } private void cleanUp() { private void cleanUpStatesForStartSharing() { mGroupedConnectedDevices.clear(); mDeviceItemsForSharing.clear(); } Loading tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java +116 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +114 −26 Original line number Diff line number Diff line Loading @@ -41,7 +41,9 @@ import android.widget.CompoundButton.OnCheckedChangeListener; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; Loading Loading @@ -69,7 +71,6 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; Loading Loading @@ -113,14 +114,21 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private final Executor mExecutor; private final MetricsFeatureProvider mMetricsFeatureProvider; private final OnAudioSharingStateChangedListener mListener; @VisibleForTesting IntentFilter mIntentFilter; private Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>(); @Nullable private AudioSharingDeviceItem mTargetActiveItem; private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>(); @VisibleForTesting IntentFilter mIntentFilter; private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private AtomicInteger mIntentHandleStage = new AtomicInteger(StartIntentHandleStage.TO_HANDLE.ordinal()); // The sinks in adding source process. We show the progress dialog based on this list. private CopyOnWriteArrayList<BluetoothDevice> mSinksInAdding = new CopyOnWriteArrayList<>(); // The primary/active sinks in adding source process. // To avoid users advance to share then pair flow before the primary/active sinks successfully // join the audio sharing, we will wait for the process complete for this list of sinks and then // popup audio sharing dialog with options to pair new device. private CopyOnWriteArrayList<BluetoothDevice> mSinksToWaitFor = new CopyOnWriteArrayList<>(); private AtomicBoolean mStoppingSharing = new AtomicBoolean(false); @VisibleForTesting BroadcastReceiver mReceiver = Loading Loading @@ -153,6 +161,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController public void onBroadcastStartFailed(int reason) { Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); updateSwitch(); showRetryDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_START_FAILED, Loading @@ -178,7 +187,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + reason + ", broadcastId = " + broadcastId); mStoppingSharing.compareAndSet(true, false); updateSwitch(); AudioSharingUtils.postOnMainThread(mContext, () -> dismissStaleDialogsOtherThanRetryDialog()); AudioSharingUtils.toastMessage( mContext, mContext.getString(R.string.audio_sharing_sharing_stopped_label)); Loading Loading @@ -219,7 +231,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController TAG, "Skip handleOnBroadcastReady: null assistant or " + "sink has active local source."); cleanUp(); cleanUpStatesForStartSharing(); return; } handleOnBroadcastReady(); Loading Loading @@ -264,17 +276,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + source + ", reason = " + reason); if (mSinksInAdding.contains(sink)) { stopAudioSharing(); showRetryDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED, SettingsEnums.AUDIO_SHARING_SETTINGS); AudioSharingUtils.toastMessage( mContext, String.format( Locale.US, "Fail to add source to %s reason %d", sink.getAddress(), reason)); } } @Override Loading @@ -298,6 +307,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController @NonNull BluetoothDevice sink, int sourceId, @NonNull BluetoothLeBroadcastReceiveState state) { if (mStoppingSharing.get()) { Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast"); return; } if (BluetoothUtils.isConnected(state)) { if (mSinksInAdding.contains(sink)) { mSinksInAdding.remove(sink); Loading @@ -305,6 +318,22 @@ public class AudioSharingSwitchBarController extends BasePreferenceController dismissLoadingStateDialogIfNeeded(); Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink + ", remaining sinks = " + mSinksInAdding); if (mSinksToWaitFor.contains(sink)) { mSinksToWaitFor.remove(sink); if (mSinksToWaitFor.isEmpty()) { // To avoid users advance to share then pair flow before the // primary/active sinks successfully join the audio sharing, // popup dialog till adding source complete for mSinksToWaitFor. Pair<Integer, Object>[] eventData = AudioSharingUtils.buildAudioSharingDialogEventData( SettingsEnums.AUDIO_SHARING_SETTINGS, SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE, /* userTriggered= */ false, /* deviceCountInSharing= */ 1, /* candidateDeviceCount= */ 0); showAudioSharingDialog(eventData); } } } } }; Loading Loading @@ -411,6 +440,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController return; } stopAudioSharing(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF); } } Loading Loading @@ -553,9 +584,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private void stopAudioSharing() { if (mBroadcast != null) { mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId()); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF); int broadcastId = mBroadcast.getLatestBroadcastId(); if (broadcastId != -1) { mBroadcast.stopBroadcast(broadcastId); mStoppingSharing.compareAndSet(false, true); mSinksInAdding.clear(); mSinksToWaitFor.clear(); } cleanUpStatesForStartSharing(); } } Loading Loading @@ -617,11 +653,22 @@ public class AudioSharingSwitchBarController extends BasePreferenceController /* userTriggered= */ false, /* deviceCountInSharing= */ targetActiveSinks.isEmpty() ? 0 : 1, /* candidateDeviceCount= */ mDeviceItemsForSharing.size()); // Auto add primary/active sinks w/o user interactions. if (!targetActiveSinks.isEmpty() && mTargetActiveItem != null) { Log.d(TAG, "handleOnBroadcastReady: automatically add source to active sinks."); addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName()); // To avoid users advance to share then pair flow before the primary/active sinks // successfully join the audio sharing, save the primary/active sinks in mSinksToWaitFor // and popup dialog till adding source complete for these sinks. if (mDeviceItemsForSharing.isEmpty()) { mSinksToWaitFor.clear(); mSinksToWaitFor.addAll(targetActiveSinks); } mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING); mTargetActiveItem = null; // When audio sharing page is brought up by intent with EXTRA_START_LE_AUDIO_SHARING // == true, plus there is one active lea headset and one connected lea headset, we // should auto add these sinks without user interactions. if (mIntentHandleStage.compareAndSet( StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(), StartIntentHandleStage.HANDLED.ordinal()) Loading @@ -631,31 +678,42 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault( target.getGroupId(), ImmutableList.of()); addSourceToTargetSinks(targetSinks, target.getName()); cleanUp(); cleanUpStatesForStartSharing(); // TODO: Add metric for auto add by intent return; } } // Still mark intent as handled if early returned due to preconditions not met mIntentHandleStage.compareAndSet( StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(), StartIntentHandleStage.HANDLED.ordinal()); if (mFragment == null) { Log.d(TAG, "handleOnBroadcastReady: dialog fail to show due to null fragment."); // Clean up states before early return. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); return; } showDialog(eventData); // To avoid users advance to share then pair flow before the primary/active sinks // successfully join the audio sharing, popup dialog till adding source complete for // mSinksToWaitFor. if (mSinksToWaitFor.isEmpty() && !mStoppingSharing.get()) { showAudioSharingDialog(eventData); } } private void showDialog(Pair<Integer, Object>[] eventData) { private void showAudioSharingDialog(Pair<Integer, Object>[] eventData) { if (!BluetoothUtils.isBroadcasting(mBtManager)) { Log.d(TAG, "Skip showAudioSharingDialog, broadcast is stopped"); return; } AudioSharingDialogFragment.DialogEventListener listener = new AudioSharingDialogFragment.DialogEventListener() { @Override public void onPositiveClick() { // Could go to other pages, dismiss the loading dialog. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); } @Override Loading @@ -663,14 +721,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault( item.getGroupId(), ImmutableList.of()); addSourceToTargetSinks(targetSinks, item.getName()); cleanUp(); cleanUpStatesForStartSharing(); } @Override public void onCancelClick() { // Could go to other pages, dismiss the loading dialog. dismissLoadingStateDialogIfNeeded(); cleanUp(); cleanUpStatesForStartSharing(); } }; AudioSharingUtils.postOnMainThread( Loading @@ -684,6 +742,36 @@ public class AudioSharingSwitchBarController extends BasePreferenceController }); } private void showRetryDialog() { AudioSharingUtils.postOnMainThread(mContext, () -> { // Remove all opening dialogs before show retry dialog dismissStaleDialogsOtherThanRetryDialog(); AudioSharingRetryDialogFragment.show(mFragment); }); } @UiThread private void dismissStaleDialogsOtherThanRetryDialog() { List<Fragment> fragments = new ArrayList<Fragment>(); try { if (mFragment != null) { fragments = mFragment.getChildFragmentManager().getFragments(); } } catch (Exception e) { Log.e(TAG, "Fail to dismiss stale dialogs: " + e.getMessage()); } for (Fragment fragment : fragments) { if (fragment != null && fragment instanceof DialogFragment && !(fragment instanceof AudioSharingRetryDialogFragment) && ((DialogFragment) fragment).getDialog() != null) { Log.d(TAG, "Remove stale dialog = " + fragment.getTag()); ((DialogFragment) fragment).dismiss(); } } } private static final class MainSwitchAccessibilityDelegate extends View.AccessibilityDelegate { @Override public boolean onRequestSendAccessibilityEvent( Loading Loading @@ -742,10 +830,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks, @NonNull String sinkName) { mSinksInAdding.addAll(targetActiveSinks); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); // TODO: move to res once finalized String loadingMessage = "Sharing with " + sinkName + "..."; showLoadingStateDialog(loadingMessage); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); } private void showLoadingStateDialog(@NonNull String loadingMessage) { Loading @@ -760,7 +848,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController } } private void cleanUp() { private void cleanUpStatesForStartSharing() { mGroupedConnectedDevices.clear(); mDeviceItemsForSharing.clear(); } Loading
tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java +116 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes