From 97f06864f89c7202528e5c7c7729595f29fe830a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Thu, 19 Sep 2024 13:51:19 +0200 Subject: [PATCH 01/16] Don't add the "Events" mode anymore, and delete it if disabled Fixes: 368227085 Test: atest ZenModeHelperTest Flag: android.app.modes_ui Change-Id: Idd5563505ca92463485b433e80f29bf3e0f98d39 --- .../notification/zen/ZenModeBackend.java | 2 +- .../notification/zen/ZenModeBackendTest.java | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/notification/zen/ZenModeBackend.java b/src/com/android/settings/notification/zen/ZenModeBackend.java index de641c5f38b..c85b06bef38 100644 --- a/src/com/android/settings/notification/zen/ZenModeBackend.java +++ b/src/com/android/settings/notification/zen/ZenModeBackend.java @@ -458,7 +458,7 @@ public class ZenModeBackend { } private static List getDefaultRuleIds() { - return ZenModeConfig.DEFAULT_RULE_IDS; + return ZenModeConfig.getDefaultRuleIds(); } NotificationManager.Policy toNotificationPolicy(ZenPolicy policy) { diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBackendTest.java index 32bf9af3010..63da3c41ea4 100644 --- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBackendTest.java +++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBackendTest.java @@ -23,14 +23,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.AutomaticZenRule; +import android.app.Flags; import android.app.NotificationManager; import android.app.NotificationManager.Policy; import android.content.Context; import android.database.Cursor; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.service.notification.ZenModeConfig; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -53,12 +57,15 @@ public class ZenModeBackendTest { private NotificationManager mNotificationManager; private static final String GENERIC_RULE_NAME = "test"; - private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID; + private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_OBSOLETE_RULE_ID; private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID; private Context mContext; private ZenModeBackend mBackend; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -161,6 +168,10 @@ public class ZenModeBackendTest { } @Test + // With MODES_UI the Events rule is not default and is sorted differently. Most likely this + // whole test class should be disabled since ZenModeBackend should never be used with + // MODES_UI. However the other tests pass, so... + @DisableFlags(Flags.FLAG_MODES_UI) public void updateState_checkRuleOrderingDescending_withDefaultRules() { final int NUM_RULES = 4; @@ -168,8 +179,8 @@ public class ZenModeBackendTest { true); Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR); - assertEquals(rules[0].getKey(), DEFAULT_ID_1); - assertEquals(rules[1].getKey(), DEFAULT_ID_2); + assertEquals(DEFAULT_ID_1, rules[0].getKey()); + assertEquals(DEFAULT_ID_2, rules[1].getKey()); // NON-DEFAULT RULES check ordering, most recent at the bottom/end for (int i = 0; i < NUM_RULES; i++) { assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey()); From 4edaf1b804b64c600a3411ebf309a1c9dac0ef71 Mon Sep 17 00:00:00 2001 From: yumeichen Date: Sun, 1 Sep 2024 17:16:19 +0000 Subject: [PATCH 02/16] Support customized summary in Channel Notification Want to show the vibration name if customised vibration in channel notification is enabled. Therefore, need the summary function could be overrided. Flag: com.android.server.notification.notification_vibration_in_sound_uri Test: manual test Bug: 351975435 Change-Id: I1fcd6deb3f176ef5943da59ae8861136d4a63f79 --- .../app/NotificationSoundPreference.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/notification/app/NotificationSoundPreference.java b/src/com/android/settings/notification/app/NotificationSoundPreference.java index b55f9bd7ce8..4084ffe685f 100644 --- a/src/com/android/settings/notification/app/NotificationSoundPreference.java +++ b/src/com/android/settings/notification/app/NotificationSoundPreference.java @@ -24,9 +24,8 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.AsyncTask; import android.util.AttributeSet; - import android.util.Log; -import com.android.settings.R; + import com.android.settings.RingtonePreference; public class NotificationSoundPreference extends RingtonePreference { @@ -49,6 +48,20 @@ public class NotificationSoundPreference extends RingtonePreference { updateRingtoneName(mRingtone); } + protected String generateRingtoneTitle(Uri uri) { + if (uri == null) { + return getContext().getString(com.android.internal.R.string.ringtone_silent); + } else if (RingtoneManager.isDefault(uri)) { + return getContext().getString(com.android.settings.R.string.notification_sound_default); + } else if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) { + return getContext().getString( + com.android.settings.R.string.notification_unknown_sound_title); + } else { + return Ringtone.getTitle(getContext(), uri, false /* followSettingsUri */, + true /* allowRemote */); + } + } + @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { @@ -69,16 +82,7 @@ public class NotificationSoundPreference extends RingtonePreference { AsyncTask ringtoneNameTask = new AsyncTask() { @Override protected CharSequence doInBackground(Object... params) { - if (uri == null) { - return getContext().getString(com.android.internal.R.string.ringtone_silent); - } else if (RingtoneManager.isDefault(uri)) { - return getContext().getString(R.string.notification_sound_default); - } else if(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) { - return getContext().getString(R.string.notification_unknown_sound_title); - } else { - return Ringtone.getTitle(getContext(), uri, false /* followSettingsUri */, - true /* allowRemote */); - } + return generateRingtoneTitle(uri); } @Override From 0af43e26099860f86fb4a76d30d18bbe559ae87d Mon Sep 17 00:00:00 2001 From: tomhsu Date: Fri, 20 Sep 2024 07:27:33 +0000 Subject: [PATCH 03/16] [Satellite] Hide BT switch in Settings search when started Satellite. Flag: EXEMPT bugfix fix: 360142029 Test: Manual test passed. Change-Id: Id1e52a80e86ce6bab1eab3708588208d7981b3aa --- .../bluetooth/BluetoothSliceBuilder.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java index fd8ef1fd82a..f4060d62dfd 100644 --- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java +++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.provider.SettingsSlicesContract; +import android.util.Log; import androidx.core.graphics.drawable.IconCompat; import androidx.slice.Slice; @@ -36,10 +37,16 @@ import androidx.slice.builders.SliceAction; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.connecteddevice.BluetoothDashboardFragment; +import com.android.settings.network.SatelliteRepository; import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBuilderUtils; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + /** * Utility class to build a Bluetooth Slice, and handle all associated actions. */ @@ -80,18 +87,34 @@ public class BluetoothSliceBuilder { final PendingIntent primaryAction = getPrimaryAction(context); final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon, ListBuilder.ICON_IMAGE, title); - final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, - null /* actionTitle */, isBluetoothEnabled); + RowBuilder rowBuilder = new RowBuilder(); + rowBuilder.setTitle(title); + rowBuilder.setPrimaryAction(primarySliceAction); + if (!isSatelliteOn(context)) { + final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, + null /* actionTitle */, isBluetoothEnabled); + rowBuilder.addEndItem(toggleSliceAction); + } return new ListBuilder(context, CustomSliceRegistry.BLUETOOTH_URI, ListBuilder.INFINITY) .setAccentColor(color) - .addRow(new RowBuilder() - .setTitle(title) - .addEndItem(toggleSliceAction) - .setPrimaryAction(primarySliceAction)) + .addRow(rowBuilder) .build(); } + private static boolean isSatelliteOn(Context context) { + boolean result = false; + SatelliteRepository satelliteRepository = new SatelliteRepository(context); + try { + result = satelliteRepository.requestIsSessionStarted( + Executors.newSingleThreadExecutor()).get(3000, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + Log.e(TAG, "Error to get satellite status : " + e); + } + + return result; + } + public static Intent getIntent(Context context) { final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString(); final Uri contentUri = new Uri.Builder().appendPath( From f528660602f155f432840a2504703af0f38c0539 Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Fri, 20 Sep 2024 13:15:17 -0700 Subject: [PATCH 04/16] OnDeviceRecognition shows only profile group Currently, if there are multiple users on the device, then the Settings for OnDeviceRecognition show a chooser for all users on the device, with only the users from the same profile group as the current user working. It shouldn't even show the users from other profile groups; we fix that here. Bug: 361095700 Test: on a device with multiple users and profiles, made sure that only users from the same profile group appeared Flag: EXEMPT bugfix Change-Id: I139e32a6a2cfede8d8a8abf573dcbaeede789f95 --- .../language/OnDeviceRecognitionPreferenceController.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java b/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java index cd9f266cf90..d0dec6430d7 100644 --- a/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java +++ b/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java @@ -20,7 +20,6 @@ import android.app.Dialog; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; @@ -80,10 +79,7 @@ public class OnDeviceRecognitionPreferenceController extends BasePreferenceContr } private void show(Preference preference) { - final List userHandles = new ArrayList<>(); - for (UserInfo userInfo : UserManager.get(mContext).getUsers()) { - userHandles.add(userInfo.getUserHandle()); - } + final List userHandles = UserManager.get(mContext).getEnabledProfiles(); // Only a single profile is installed. Proceed with its settings. if (userHandles.size() == 1) { From a604a6cee8f53ef022faddf4fe8ceef0db9d3eb5 Mon Sep 17 00:00:00 2001 From: arunvoddu Date: Fri, 20 Sep 2024 08:26:58 +0000 Subject: [PATCH 05/16] Changed the token from 'Add satellite messaging' to 'Learn More'. Flag: EXEMPT bugfix Bug: 367377460 Test: Verified the UI Manually Change-Id: Ieba6dc32dbedaea98fe39a8bb081f3562d8eeb6e --- res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index cd847f7400e..610574682e6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12142,8 +12142,8 @@ Satellite messaging is included with your account Satellite messaging isn\u2019t included with your account - - Add satellite messaging + + Learn More How it works From b6a64e99589aef913c569df4ae796f7ac5bea777 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Mon, 23 Sep 2024 11:00:33 +0800 Subject: [PATCH 06/16] Update color-check-baseline.xml `repo upload --verify` fails on HardCodedColor check and ag/29447250 did not fix the issue. Bug: 269100659 Flag: EXEMPT lint only Test: repo upload --verify Change-Id: Ie5462c0956a436f6dd0d5eb95c7b8ec0d3262321 --- color-check-baseline.xml | 897 +++++++-------------------------------- 1 file changed, 145 insertions(+), 752 deletions(-) diff --git a/color-check-baseline.xml b/color-check-baseline.xml index 75d4aba8304..15b497632f6 100644 --- a/color-check-baseline.xml +++ b/color-check-baseline.xml @@ -1,658 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + From 302b26ff74ff71b7bc1ee1210ba5a8d56f9ea5de Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Fri, 20 Sep 2024 17:11:47 +0800 Subject: [PATCH 07/16] [Audiosharing] Show retry dialog when error occurs in start sharing Errors including: 1. onBroadcastStartFailed 2. onSourceAddFailed Test: atest Flag: com.android.settingslib.flags.enable_le_audio_sharing Bug: 362858894 Change-Id: I0fe13bd675672c57219d0f6f3e735515a7ed7a06 --- .../AudioSharingSwitchBarController.java | 140 ++++++++++++++---- .../AudioSharingSwitchBarControllerTest.java | 132 +++++++++++++++-- 2 files changed, 230 insertions(+), 42 deletions(-) diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java index 395647ca84a..786d07741e2 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java @@ -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; @@ -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; @@ -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> mGroupedConnectedDevices = new HashMap<>(); @Nullable private AudioSharingDeviceItem mTargetActiveItem; private List 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 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 mSinksToWaitFor = new CopyOnWriteArrayList<>(); + private AtomicBoolean mStoppingSharing = new AtomicBoolean(false); @VisibleForTesting BroadcastReceiver mReceiver = @@ -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, @@ -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)); @@ -219,7 +231,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController TAG, "Skip handleOnBroadcastReady: null assistant or " + "sink has active local source."); - cleanUp(); + cleanUpStatesForStartSharing(); return; } handleOnBroadcastReady(); @@ -264,17 +276,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + source + ", reason = " + reason); - 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)); + if (mSinksInAdding.contains(sink)) { + stopAudioSharing(); + showRetryDialog(); + mMetricsFeatureProvider.action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED, + SettingsEnums.AUDIO_SHARING_SETTINGS); + } } @Override @@ -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); @@ -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[] eventData = + AudioSharingUtils.buildAudioSharingDialogEventData( + SettingsEnums.AUDIO_SHARING_SETTINGS, + SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE, + /* userTriggered= */ false, + /* deviceCountInSharing= */ 1, + /* candidateDeviceCount= */ 0); + showAudioSharingDialog(eventData); + } + } } } }; @@ -411,6 +440,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController return; } stopAudioSharing(); + mMetricsFeatureProvider.action( + mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF); } } @@ -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(); } } @@ -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()) @@ -631,31 +678,42 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List 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[] eventData) { + private void showAudioSharingDialog(Pair[] 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 @@ -663,14 +721,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController List 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( @@ -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 fragments = new ArrayList(); + 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( @@ -742,10 +830,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController private void addSourceToTargetSinks(List 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) { @@ -760,7 +848,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController } } - private void cleanUp() { + private void cleanUpStatesForStartSharing() { mGroupedConnectedDevices.clear(); mDeviceItemsForSharing.clear(); } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java index eb2083ebe7b..415762b1879 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java @@ -146,6 +146,7 @@ public class AudioSharingSwitchBarControllerTest { @Mock private LocalBluetoothLeBroadcastAssistant mAssistant; @Mock private VolumeControlProfile mVolumeControl; @Mock private BluetoothLeBroadcastMetadata mMetadata; + @Mock private BluetoothLeBroadcastReceiveState mState; @Mock private CompoundButton mBtnView; @Mock private CachedBluetoothDevice mCachedDevice1; @Mock private CachedBluetoothDevice mCachedDevice2; @@ -519,10 +520,9 @@ public class AudioSharingSwitchBarControllerTest { mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); when(mBtnView.isEnabled()).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1)); - BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); - when(state.getBroadcastId()).thenReturn(1); + when(mState.getBroadcastId()).thenReturn(1); when(mBroadcast.getLatestBroadcastId()).thenReturn(1); - when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(state)); + when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(mState)); when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); doNothing().when(mBroadcast).startPrivateBroadcast(); mController.onCheckedChanged(mBtnView, /* isChecked= */ true); @@ -549,14 +549,77 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void onPlaybackStarted_showJoinAudioSharingDialog() { + public void onPlaybackStarted_singleActiveDevice_showJoinAudioSharingDialog() { + FeatureFlagUtils.setEnabled( + mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); + when(mBtnView.isEnabled()).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2)); + when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of()); + doNothing().when(mBroadcast).startPrivateBroadcast(); + mController.onCheckedChanged(mBtnView, /* isChecked= */ true); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mBroadcast).startPrivateBroadcast(); + List childFragments = mParentFragment.getChildFragmentManager().getFragments(); + assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( + AudioSharingLoadingStateDialogFragment.class.getName()); + + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); + mController.mBroadcastCallback.onPlaybackStarted(0, 0); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mFeatureFactory.metricsFeatureProvider) + .action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING)); + + when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L)); + mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice2, /* sourceId= */ 1, + mState); + shadowOf(Looper.getMainLooper()).idle(); + + childFragments = mParentFragment.getChildFragmentManager().getFragments(); + assertThat(childFragments) + .comparingElementsUsing(CLAZZNAME_EQUALS) + .containsExactly(AudioSharingDialogFragment.class.getName()); + + Pair[] eventData = new Pair[0]; + for (Fragment fragment : childFragments) { + if (fragment instanceof AudioSharingDialogFragment) { + eventData = ((AudioSharingDialogFragment) fragment).getEventData(); + break; + } + } + assertThat(eventData) + .asList() + .containsExactly( + Pair.create( + AudioSharingUtils.MetricKey.METRIC_KEY_SOURCE_PAGE_ID.ordinal(), + SettingsEnums.AUDIO_SHARING_SETTINGS), + Pair.create( + AudioSharingUtils.MetricKey.METRIC_KEY_PAGE_ID.ordinal(), + SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE), + Pair.create( + AudioSharingUtils.MetricKey.METRIC_KEY_USER_TRIGGERED.ordinal(), 0), + Pair.create( + AudioSharingUtils.MetricKey.METRIC_KEY_DEVICE_COUNT_IN_SHARING + .ordinal(), + 1), + Pair.create( + AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT + .ordinal(), + 0)); + + childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); + } + + @Test + public void onPlaybackStarted_oneActiveOnConnected_showJoinAudioSharingDialog() { FeatureFlagUtils.setEnabled( mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); when(mBtnView.isEnabled()).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1)); when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of()); doNothing().when(mBroadcast).startPrivateBroadcast(); - when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); mController.onCheckedChanged(mBtnView, /* isChecked= */ true); shadowOf(Looper.getMainLooper()).idle(); @@ -570,6 +633,8 @@ public class AudioSharingSwitchBarControllerTest { String expectedMessage = "Starting audio stream..."; checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); mController.mBroadcastCallback.onPlaybackStarted(0, 0); shadowOf(Looper.getMainLooper()).idle(); @@ -616,18 +681,19 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void onPlaybackStarted_clickShareBtnOnDialog_addSource() { + public void onPlaybackStarted_oneActiveOnConnected_clickShareBtnOnDialog_addSource() { FeatureFlagUtils.setEnabled( mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); when(mBtnView.isEnabled()).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1)); when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of()); - when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); doNothing().when(mBroadcast).startPrivateBroadcast(); mController.onCheckedChanged(mBtnView, /* isChecked= */ true); shadowOf(Looper.getMainLooper()).idle(); verify(mBroadcast).startPrivateBroadcast(); + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); mController.mBroadcastCallback.onPlaybackStarted(0, 0); shadowOf(Looper.getMainLooper()).idle(); @@ -656,18 +722,19 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void onPlaybackStarted_clickCancelBtnOnDialog_doNothing() { + public void onPlaybackStarted_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() { FeatureFlagUtils.setEnabled( mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); when(mBtnView.isEnabled()).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1)); when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of()); - when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); doNothing().when(mBroadcast).startPrivateBroadcast(); mController.onCheckedChanged(mBtnView, /* isChecked= */ true); shadowOf(Looper.getMainLooper()).idle(); verify(mBroadcast).startPrivateBroadcast(); + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); mController.mBroadcastCallback.onPlaybackStarted(0, 0); shadowOf(Looper.getMainLooper()).idle(); @@ -754,14 +821,50 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void testAssistantCallbacks_onSourceAddFailed_logAction() { + public void testAssistantCallbacks_onSourceAddFailed_twoDevices_showRetryAndLogAction() { + FeatureFlagUtils.setEnabled( + mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); + when(mBtnView.isEnabled()).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1)); + when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of()); + doNothing().when(mBroadcast).startPrivateBroadcast(); + mController.onCheckedChanged(mBtnView, /* isChecked= */ true); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mBroadcast).startPrivateBroadcast(); + + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); + mController.mBroadcastCallback.onPlaybackStarted(0, 0); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false); + + AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); + assertThat(dialog).isNotNull(); + View btnView = dialog.findViewById(R.id.positive_btn); + assertThat(btnView).isNotNull(); + btnView.performClick(); + shadowMainLooper().idle(); + + verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false); + assertThat(dialog.isShowing()).isFalse(); + mController.mBroadcastAssistantCallback.onSourceAddFailed( mDevice1, mMetadata, /* reason= */ 1); + shadowMainLooper().idle(); + + // Loading state dialog shows sharing state for the user chosen sink. + List childFragments = mParentFragment.getChildFragmentManager().getFragments(); + assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( + AudioSharingRetryDialogFragment.class.getName()); verify(mFeatureFactory.metricsFeatureProvider) .action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED, SettingsEnums.AUDIO_SHARING_SETTINGS); + + childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); } @Test @@ -772,10 +875,9 @@ public class AudioSharingSwitchBarControllerTest { assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( AudioSharingLoadingStateDialogFragment.class.getName()); - BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); - when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L)); + when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L)); mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1, - state); + mState); shadowOf(Looper.getMainLooper()).idle(); childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).isEmpty(); @@ -783,11 +885,9 @@ public class AudioSharingSwitchBarControllerTest { @Test public void testAssistantCallbacks_doNothing() { - BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); - // Do nothing mController.mBroadcastAssistantCallback.onReceiveStateChanged( - mDevice1, /* sourceId= */ 1, state); + mDevice1, /* sourceId= */ 1, mState); mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1); mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1); mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1); From 73fb290969c5a04288ab75be0b0d33828f20664e Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Fri, 20 Sep 2024 15:27:57 +0800 Subject: [PATCH 08/16] Check DISALLOW_CONFIG_MOBILE_NETWORKS when search If disallowed, not show mobile related search results. Bug: 358238959 Flag: EXEMPT bug fix Test: manual - search Mobile Settings Test: atest MobileNetworkSettingsSearchIndexTest Change-Id: I79b984f41f09dd9612bcd0c9942089756d5d365d --- .../network/MobileNetworkListFragment.kt | 2 +- .../network/MobileNetworkSummaryController.kt | 2 +- ...opLevelNetworkEntryPreferenceController.kt | 2 +- .../MobileNetworkSettingsSearchIndex.kt | 10 +--- .../network/telephony/SimRepository.kt | 17 +++++- .../network/NetworkCellularGroupProvider.kt | 2 +- .../network/MobileNetworkListFragmentTest.kt | 4 +- ...velNetworkEntryPreferenceControllerTest.kt | 4 +- .../network/telephony/SimRepositoryTest.kt | 58 ++++++++++++++----- 9 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkListFragment.kt b/src/com/android/settings/network/MobileNetworkListFragment.kt index d110779b36d..3118088c6c3 100644 --- a/src/com/android/settings/network/MobileNetworkListFragment.kt +++ b/src/com/android/settings/network/MobileNetworkListFragment.kt @@ -89,7 +89,7 @@ class MobileNetworkListFragment : DashboardFragment() { private val simRepositoryFactory: (Context) -> SimRepository = ::SimRepository ) : BaseSearchIndexProvider(R.xml.network_provider_sims_list) { public override fun isPageSearchEnabled(context: Context): Boolean = - simRepositoryFactory(context).showMobileNetworkPage() + simRepositoryFactory(context).canEnterMobileNetworkPage() } } } diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.kt b/src/com/android/settings/network/MobileNetworkSummaryController.kt index 5980bbd7d05..8cf9bec283e 100644 --- a/src/com/android/settings/network/MobileNetworkSummaryController.kt +++ b/src/com/android/settings/network/MobileNetworkSummaryController.kt @@ -57,7 +57,7 @@ constructor( private var isAirplaneModeOn = false override fun getAvailabilityStatus() = - if (SimRepository(mContext).showMobileNetworkPage()) AVAILABLE + if (SimRepository(mContext).showMobileNetworkPageEntrance()) AVAILABLE else CONDITIONALLY_UNAVAILABLE override fun displayPreference(screen: PreferenceScreen) { diff --git a/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.kt b/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.kt index 1722f6ae6b9..11698a6699c 100644 --- a/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.kt +++ b/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.kt @@ -48,7 +48,7 @@ constructor( override fun getSummary(): CharSequence { val summaryResId = - if (simRepository.showMobileNetworkPage()) { + if (simRepository.showMobileNetworkPageEntrance()) { R.string.network_dashboard_summary_mobile } else { R.string.network_dashboard_summary_no_mobile diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt index 83e3a31ff3f..f850e1d9b4b 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt +++ b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt @@ -21,7 +21,6 @@ import android.provider.Settings import android.telephony.SubscriptionInfo import com.android.settings.R import com.android.settings.datausage.BillingCyclePreferenceController.Companion.BillingCycleSearchItem -import com.android.settings.network.SubscriptionUtil import com.android.settings.network.telephony.CarrierSettingsVersionPreferenceController.Companion.CarrierSettingsVersionSearchItem import com.android.settings.network.telephony.DataUsagePreferenceController.Companion.DataUsageSearchItem import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem @@ -36,7 +35,6 @@ import com.android.settings.spa.search.SpaSearchRepository.Companion.createSearc import com.android.settings.spa.search.SpaSearchRepository.Companion.searchIndexProviderOf import com.android.settingslib.search.SearchIndexableData import com.android.settingslib.search.SearchIndexableRaw -import com.android.settingslib.spaprivileged.framework.common.userManager import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean class MobileNetworkSettingsSearchIndex( @@ -109,12 +107,8 @@ class MobileNetworkSettingsSearchIndex( companion object { /** suppress full page if user is not admin */ @JvmStatic - fun isMobileNetworkSettingsSearchable(context: Context): Boolean { - val isAirplaneMode by context.settingsGlobalBoolean(Settings.Global.AIRPLANE_MODE_ON) - return SubscriptionUtil.isSimHardwareVisible(context) && - !isAirplaneMode && - context.userManager.isAdminUser - } + fun isMobileNetworkSettingsSearchable(context: Context): Boolean = + SimRepository(context).canEnterMobileNetworkPage() fun createSearchItems(context: Context): List = listOf( diff --git a/src/com/android/settings/network/telephony/SimRepository.kt b/src/com/android/settings/network/telephony/SimRepository.kt index ed3c8aa303c..baff5cbe2a3 100644 --- a/src/com/android/settings/network/telephony/SimRepository.kt +++ b/src/com/android/settings/network/telephony/SimRepository.kt @@ -18,13 +18,24 @@ package com.android.settings.network.telephony import android.content.Context import android.content.pm.PackageManager +import android.os.UserManager +import android.provider.Settings import com.android.settingslib.spaprivileged.framework.common.userManager +import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean -class SimRepository(context: Context) { +class SimRepository(private val context: Context) { private val packageManager = context.packageManager private val userManager = context.userManager - /** Gets whether we show mobile network settings page to the current user. */ - fun showMobileNetworkPage(): Boolean = + /** Gets whether show mobile network settings page entrance to the current user. */ + fun showMobileNetworkPageEntrance(): Boolean = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) && userManager.isAdminUser + + /** Gets whether current user can enter mobile network settings page. */ + fun canEnterMobileNetworkPage(): Boolean { + val isAirplaneMode by context.settingsGlobalBoolean(Settings.Global.AIRPLANE_MODE_ON) + return showMobileNetworkPageEntrance() && + !isAirplaneMode && + !userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) + } } diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt index d736fe5224a..f60ba81fc4c 100644 --- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt +++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt @@ -212,7 +212,7 @@ open class NetworkCellularGroupProvider : SettingsPageProvider, SearchablePage { const val fileName = "NetworkCellularGroupProvider" private fun isPageSearchable(context: Context) = - Flags.isDualSimOnboardingEnabled() && SimRepository(context).showMobileNetworkPage() + Flags.isDualSimOnboardingEnabled() && SimRepository(context).canEnterMobileNetworkPage() } } diff --git a/tests/spa_unit/src/com/android/settings/network/MobileNetworkListFragmentTest.kt b/tests/spa_unit/src/com/android/settings/network/MobileNetworkListFragmentTest.kt index 4bb5f2f803f..226f14f1dd2 100644 --- a/tests/spa_unit/src/com/android/settings/network/MobileNetworkListFragmentTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/MobileNetworkListFragmentTest.kt @@ -36,7 +36,7 @@ class MobileNetworkListFragmentTest { @Test fun isPageSearchEnabled_showMobileNetworkPage_returnTrue() { - mockSimRepository.stub { on { showMobileNetworkPage() } doReturn true } + mockSimRepository.stub { on { canEnterMobileNetworkPage() } doReturn true } val isEnabled = SearchIndexProvider { mockSimRepository }.isPageSearchEnabled(context) @@ -45,7 +45,7 @@ class MobileNetworkListFragmentTest { @Test fun isPageSearchEnabled_hideMobileNetworkPage_returnFalse() { - mockSimRepository.stub { on { showMobileNetworkPage() } doReturn false } + mockSimRepository.stub { on { canEnterMobileNetworkPage() } doReturn false } val isEnabled = SearchIndexProvider { mockSimRepository }.isPageSearchEnabled(context) diff --git a/tests/spa_unit/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.kt index 27c960282dc..78d2941ae89 100644 --- a/tests/spa_unit/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.kt @@ -71,7 +71,7 @@ class TopLevelNetworkEntryPreferenceControllerTest { @Test fun getSummary_hasMobile_shouldReturnMobileSummary() { - mockSimRepository.stub { on { showMobileNetworkPage() } doReturn true } + mockSimRepository.stub { on { showMobileNetworkPageEntrance() } doReturn true } val summary = controller.summary @@ -84,7 +84,7 @@ class TopLevelNetworkEntryPreferenceControllerTest { @Test fun getSummary_noMobile_shouldReturnNoMobileSummary() { - mockSimRepository.stub { on { showMobileNetworkPage() } doReturn false } + mockSimRepository.stub { on { showMobileNetworkPageEntrance() } doReturn false } val summary = controller.summary diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/SimRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/SimRepositoryTest.kt index bbcac086a10..e80cc2f8704 100644 --- a/tests/spa_unit/src/com/android/settings/network/telephony/SimRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/telephony/SimRepositoryTest.kt @@ -37,50 +37,76 @@ class SimRepositoryTest { private val mockPackageManager = mock() - private val context: Context = spy(ApplicationProvider.getApplicationContext()) { - on { userManager } doReturn mockUserManager - on { packageManager } doReturn mockPackageManager - } + private val context: Context = + spy(ApplicationProvider.getApplicationContext()) { + on { userManager } doReturn mockUserManager + on { packageManager } doReturn mockPackageManager + } private val repository = SimRepository(context) @Test - fun showMobileNetworkPage_adminUserAndHasTelephony_returnTrue() { - mockUserManager.stub { - on { isAdminUser } doReturn true - } + fun showMobileNetworkPageEntrance_adminUserAndHasTelephony_returnTrue() { + mockUserManager.stub { on { isAdminUser } doReturn true } mockPackageManager.stub { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true } - val showMobileNetworkPage = repository.showMobileNetworkPage() + val showMobileNetworkPage = repository.showMobileNetworkPageEntrance() assertThat(showMobileNetworkPage).isTrue() } @Test - fun showMobileNetworkPage_notAdminUser_returnFalse() { + fun showMobileNetworkPageEntrance_notAdminUser_returnFalse() { + mockUserManager.stub { on { isAdminUser } doReturn false } + mockPackageManager.stub { + on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true + } + + val showMobileNetworkPage = repository.showMobileNetworkPageEntrance() + + assertThat(showMobileNetworkPage).isFalse() + } + + @Test + fun showMobileNetworkPageEntrance_noTelephony_returnFalse() { + mockUserManager.stub { on { isAdminUser } doReturn true } + mockPackageManager.stub { + on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn false + } + + val showMobileNetworkPage = repository.showMobileNetworkPageEntrance() + + assertThat(showMobileNetworkPage).isFalse() + } + + @Test + fun canEnterMobileNetworkPage_allowConfigMobileNetwork_returnTrue() { mockUserManager.stub { - on { isAdminUser } doReturn false + on { isAdminUser } doReturn true + on { hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) } doReturn false } mockPackageManager.stub { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true } - val showMobileNetworkPage = repository.showMobileNetworkPage() + val showMobileNetworkPage = repository.canEnterMobileNetworkPage() - assertThat(showMobileNetworkPage).isFalse() + assertThat(showMobileNetworkPage).isTrue() } - @Test fun showMobileNetworkPage_noTelephony_returnFalse() { + @Test + fun canEnterMobileNetworkPage_disallowConfigMobileNetwork_returnFalse() { mockUserManager.stub { on { isAdminUser } doReturn true + on { hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) } doReturn true } mockPackageManager.stub { - on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn false + on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true } - val showMobileNetworkPage = repository.showMobileNetworkPage() + val showMobileNetworkPage = repository.canEnterMobileNetworkPage() assertThat(showMobileNetworkPage).isFalse() } From 4ded4ac03867a3dff9119279c1247afa2152fc23 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 23 Sep 2024 12:09:00 +0800 Subject: [PATCH 09/16] Check canEnterMobileNetworkPage When startSimOnboardingActivity, so we enforce the no_config_mobile_networks when insert psim. Fix: 366370519 Flag: EXEMPT bug fix Test: manual - set no_config_mobile_networks and insert psim Change-Id: I0d4e85262924cc55a035ebeb2038ae08c0052ef6 --- src/com/android/settings/network/SimOnboardingActivity.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt index 25afb661e8b..7fab9c9848e 100644 --- a/src/com/android/settings/network/SimOnboardingActivity.kt +++ b/src/com/android/settings/network/SimOnboardingActivity.kt @@ -53,8 +53,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.LifecycleRegistry import com.android.settings.R import com.android.settings.SidecarFragment +import com.android.settings.network.telephony.SimRepository import com.android.settings.network.telephony.SubscriptionActionDialogActivity -import com.android.settings.network.telephony.SubscriptionRepository import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity import com.android.settings.network.telephony.requireSubscriptionManager import com.android.settings.spa.SpaActivity.Companion.startSpaActivity @@ -578,6 +578,10 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { subId: Int, isNewTask: Boolean = false, ) { + if (!SimRepository(context).canEnterMobileNetworkPage()) { + Log.i(TAG, "Unable to start SimOnboardingActivity due to missing permissions") + return + } val intent = Intent(context, SimOnboardingActivity::class.java).apply { putExtra(SUB_ID, subId) if(isNewTask) { From 322e15335077b80756a37f27001c2a381e934505 Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Fri, 20 Sep 2024 20:16:51 +0800 Subject: [PATCH 10/16] Rename AudioSharingLoadingStateDialogFragment and layout Test: atest Flag: com.android.settingslib.flags.enable_le_audio_sharing Bug: 362858894 Change-Id: I05e29b248541511daca355f1bbe4a13b17b4d20d --- ....xml => dialog_audio_sharing_progress.xml} | 0 .../BluetoothDevicePairingDetailBase.java | 20 +++--- ...> AudioSharingProgressDialogFragment.java} | 15 ++-- .../AudioSharingSwitchBarController.java | 26 +++---- ...dioSharingProgressDialogFragmentTest.java} | 24 +++---- .../AudioSharingSwitchBarControllerTest.java | 68 +++++++++---------- 6 files changed, 76 insertions(+), 77 deletions(-) rename res/layout/{dialog_audio_sharing_loading_state.xml => dialog_audio_sharing_progress.xml} (100%) rename src/com/android/settings/connecteddevice/audiosharing/{AudioSharingLoadingStateDialogFragment.java => AudioSharingProgressDialogFragment.java} (91%) rename tests/robotests/src/com/android/settings/connecteddevice/audiosharing/{AudioSharingLoadingStateDialogFragmentTest.java => AudioSharingProgressDialogFragmentTest.java} (86%) diff --git a/res/layout/dialog_audio_sharing_loading_state.xml b/res/layout/dialog_audio_sharing_progress.xml similarity index 100% rename from res/layout/dialog_audio_sharing_loading_state.xml rename to res/layout/dialog_audio_sharing_progress.xml diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java index 86f090e8be5..f1e12a4a6fe 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java @@ -72,7 +72,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere private final Handler mHandler = new Handler(Looper.getMainLooper()); private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); @Nullable - private AlertDialog mLoadingDialog = null; + private AlertDialog mProgressDialog = null; @VisibleForTesting boolean mShouldTriggerAudioSharingShareThenPairFlow = false; private CopyOnWriteArrayList mDevicesWithMetadataChangedListener = @@ -89,7 +89,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere // In share then pair flow, we have to wait on this page till the device is connected. // The BluetoothDevicePreference summary will be blank for seconds between "Pairing..." and // "Connecting..." To help users better understand the process, we listen to metadata change - // as well and show a loading dialog with "Connecting to ...." once BluetoothDevice.getState() + // as well and show a progress dialog with "Connecting to ...." once BluetoothDevice.getState() // gets to BOND_BONDED. final BluetoothAdapter.OnMetadataChangedListener mMetadataListener = new BluetoothAdapter.OnMetadataChangedListener() { @@ -97,7 +97,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere public void onMetadataChanged(@NonNull BluetoothDevice device, int key, @Nullable byte[] value) { Log.d(getLogTag(), "onMetadataChanged device = " + device + ", key = " + key); - if (mShouldTriggerAudioSharingShareThenPairFlow && mLoadingDialog == null + if (mShouldTriggerAudioSharingShareThenPairFlow && mProgressDialog == null && device.getBondState() == BluetoothDevice.BOND_BONDED && mSelectedList.contains(device)) { triggerAudioSharingShareThenPairFlow(device); @@ -355,7 +355,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere return; } mJustBonded = device; - // Show connecting device loading state + // Show connecting device progress String aliasName = device.getAlias(); String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress() : aliasName; @@ -387,9 +387,9 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere // TODO: use DialogFragment private void showConnectingDialog(@NonNull String message) { postOnMainThread(() -> { - if (mLoadingDialog != null) { + if (mProgressDialog != null) { Log.d(getLogTag(), "showConnectingDialog, is already showing"); - TextView textView = mLoadingDialog.findViewById(R.id.message); + TextView textView = mProgressDialog.findViewById(R.id.message); if (textView != null && !message.equals(textView.getText().toString())) { Log.d(getLogTag(), "showConnectingDialog, update message"); // TODO: use string res once finalized @@ -401,7 +401,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = LayoutInflater.from(builder.getContext()); View customView = inflater.inflate( - R.layout.dialog_audio_sharing_loading_state, /* root= */ + R.layout.dialog_audio_sharing_progress, /* root= */ null); TextView textView = customView.findViewById(R.id.message); if (textView != null) { @@ -410,15 +410,15 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere } AlertDialog dialog = builder.setView(customView).setCancelable(false).create(); dialog.setCanceledOnTouchOutside(false); - mLoadingDialog = dialog; + mProgressDialog = dialog; dialog.show(); }); } private void dismissConnectingDialog() { postOnMainThread(() -> { - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); + if (mProgressDialog != null) { + mProgressDialog.dismiss(); } }); } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragment.java similarity index 91% rename from src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java rename to src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragment.java index 8706590c362..53bfcf8f17c 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragment.java @@ -40,8 +40,8 @@ import com.google.common.base.Strings; import java.util.concurrent.TimeUnit; -public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFragment { - private static final String TAG = "AudioSharingLoadingDlg"; +public class AudioSharingProgressDialogFragment extends InstrumentedDialogFragment { + private static final String TAG = "AudioSharingProgressDlg"; private static final String BUNDLE_KEY_MESSAGE = "bundle_key_message"; private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15); @@ -58,7 +58,7 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr } /** - * Display the {@link AudioSharingLoadingStateDialogFragment} dialog. + * Display the {@link AudioSharingProgressDialogFragment} dialog. * * @param host The Fragment this dialog will be hosted by. * @param message The content to be shown on the dialog. @@ -85,16 +85,15 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr return; } sMessage = message; - Log.d(TAG, "Show up the loading dialog."); + Log.d(TAG, "Show up the progress dialog."); Bundle args = new Bundle(); args.putString(BUNDLE_KEY_MESSAGE, message); - AudioSharingLoadingStateDialogFragment dialogFrag = - new AudioSharingLoadingStateDialogFragment(); + AudioSharingProgressDialogFragment dialogFrag = new AudioSharingProgressDialogFragment(); dialogFrag.setArguments(args); dialogFrag.show(manager, TAG); } - /** Dismiss the {@link AudioSharingLoadingStateDialogFragment} dialog. */ + /** Dismiss the {@link AudioSharingProgressDialogFragment} dialog. */ public static void dismiss(@Nullable Fragment host) { if (host == null || !BluetoothUtils.isAudioSharingEnabled()) return; final FragmentManager manager; @@ -119,7 +118,7 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr String message = args.getString(BUNDLE_KEY_MESSAGE, ""); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = LayoutInflater.from(builder.getContext()); - View customView = inflater.inflate(R.layout.dialog_audio_sharing_loading_state, /* root= */ + View customView = inflater.inflate(R.layout.dialog_audio_sharing_progress, /* root= */ null); TextView textView = customView.findViewById(R.id.message); if (!Strings.isNullOrEmpty(message)) textView.setText(message); diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java index 786d07741e2..68dba54de6b 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java @@ -315,7 +315,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController if (mSinksInAdding.contains(sink)) { mSinksInAdding.remove(sink); } - dismissLoadingStateDialogIfNeeded(); + dismissProgressDialogIfNeeded(); Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink + ", remaining sinks = " + mSinksInAdding); if (mSinksToWaitFor.contains(sink)) { @@ -573,7 +573,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController mSinksInAdding.clear(); // TODO: use string res once finalized. AudioSharingUtils.postOnMainThread(mContext, - () -> AudioSharingLoadingStateDialogFragment.show(mFragment, + () -> AudioSharingProgressDialogFragment.show(mFragment, "Starting audio stream...")); mMetricsFeatureProvider.action( mContext, @@ -690,7 +690,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController if (mFragment == null) { Log.d(TAG, "handleOnBroadcastReady: dialog fail to show due to null fragment."); // Clean up states before early return. - dismissLoadingStateDialogIfNeeded(); + dismissProgressDialogIfNeeded(); cleanUpStatesForStartSharing(); return; } @@ -711,8 +711,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController new AudioSharingDialogFragment.DialogEventListener() { @Override public void onPositiveClick() { - // Could go to other pages, dismiss the loading dialog. - dismissLoadingStateDialogIfNeeded(); + // Could go to other pages, dismiss the progress dialog. + dismissProgressDialogIfNeeded(); cleanUpStatesForStartSharing(); } @@ -726,8 +726,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController @Override public void onCancelClick() { - // Could go to other pages, dismiss the loading dialog. - dismissLoadingStateDialogIfNeeded(); + // Could go to other pages, dismiss the progress dialog. + dismissProgressDialogIfNeeded(); cleanUpStatesForStartSharing(); } }; @@ -831,20 +831,20 @@ public class AudioSharingSwitchBarController extends BasePreferenceController @NonNull String sinkName) { mSinksInAdding.addAll(targetActiveSinks); // TODO: move to res once finalized - String loadingMessage = "Sharing with " + sinkName + "..."; - showLoadingStateDialog(loadingMessage); + String progressMessage = "Sharing with " + sinkName + "..."; + showProgressDialog(progressMessage); AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager); } - private void showLoadingStateDialog(@NonNull String loadingMessage) { + private void showProgressDialog(@NonNull String progressMessage) { AudioSharingUtils.postOnMainThread(mContext, - () -> AudioSharingLoadingStateDialogFragment.show(mFragment, loadingMessage)); + () -> AudioSharingProgressDialogFragment.show(mFragment, progressMessage)); } - private void dismissLoadingStateDialogIfNeeded() { + private void dismissProgressDialogIfNeeded() { if (mSinksInAdding.isEmpty()) { AudioSharingUtils.postOnMainThread(mContext, - () -> AudioSharingLoadingStateDialogFragment.dismiss(mFragment)); + () -> AudioSharingProgressDialogFragment.dismiss(mFragment)); } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragmentTest.java similarity index 86% rename from tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java rename to tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragmentTest.java index ff15f5269d4..b08e5c5e96b 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingLoadingStateDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingProgressDialogFragmentTest.java @@ -52,7 +52,7 @@ import org.robolectric.shadows.androidx.fragment.FragmentController; ShadowAlertDialogCompat.class, ShadowBluetoothAdapter.class, }) -public class AudioSharingLoadingStateDialogFragmentTest { +public class AudioSharingProgressDialogFragmentTest { @Rule public final MockitoRule mocks = MockitoJUnit.rule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -60,7 +60,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { private static final String TEST_MESSAGE2 = "message2"; private Fragment mParent; - private AudioSharingLoadingStateDialogFragment mFragment; + private AudioSharingProgressDialogFragment mFragment; @Before public void setUp() { @@ -72,7 +72,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); - mFragment = new AudioSharingLoadingStateDialogFragment(); + mFragment = new AudioSharingProgressDialogFragment(); mParent = new Fragment(); FragmentController.setupFragment( mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null); @@ -93,7 +93,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void onCreateDialog_flagOff_dialogNotExist() { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNull(); @@ -102,7 +102,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void onCreateDialog_unattachedFragment_dialogNotExist() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(new Fragment(), TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(new Fragment(), TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNull(); @@ -111,7 +111,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void onCreateDialog_flagOn_showDialog() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); @@ -124,13 +124,13 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void dismissDialog_succeed() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); assertThat(dialog.isShowing()).isTrue(); - AudioSharingLoadingStateDialogFragment.dismiss(mParent); + AudioSharingProgressDialogFragment.dismiss(mParent); shadowMainLooper().idle(); assertThat(dialog.isShowing()).isFalse(); } @@ -138,13 +138,13 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void showDialog_sameMessage_keepExistingDialog() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); assertThat(dialog.isShowing()).isTrue(); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); assertThat(dialog.isShowing()).isTrue(); } @@ -152,7 +152,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { @Test public void showDialog_newMessage_keepAndUpdateDialog() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); @@ -161,7 +161,7 @@ public class AudioSharingLoadingStateDialogFragmentTest { assertThat(view).isNotNull(); assertThat(view.getText().toString()).isEqualTo(TEST_MESSAGE1); - AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE2); + AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE2); shadowMainLooper().idle(); assertThat(dialog.isShowing()).isTrue(); assertThat(view.getText().toString()).isEqualTo(TEST_MESSAGE2); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java index 415762b1879..8865e6f7234 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java @@ -500,7 +500,7 @@ public class AudioSharingSwitchBarControllerTest { verify(mBroadcast).startPrivateBroadcast(); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); - // No loading state dialog. + // No progress dialog. assertThat(childFragments).isEmpty(); mController.mBroadcastCallback.onPlaybackStarted(0, 0); @@ -531,7 +531,7 @@ public class AudioSharingSwitchBarControllerTest { verify(mBroadcast).startPrivateBroadcast(); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); + AudioSharingProgressDialogFragment.class.getName()); mController.mBroadcastCallback.onPlaybackStarted(0, 0); shadowOf(Looper.getMainLooper()).idle(); @@ -562,7 +562,7 @@ public class AudioSharingSwitchBarControllerTest { verify(mBroadcast).startPrivateBroadcast(); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); + AudioSharingProgressDialogFragment.class.getName()); when(mBroadcast.isEnabled(null)).thenReturn(true); when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); @@ -626,12 +626,12 @@ public class AudioSharingSwitchBarControllerTest { verify(mBroadcast).startPrivateBroadcast(); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); - AudioSharingLoadingStateDialogFragment loadingFragment = - (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments); + AudioSharingProgressDialogFragment.class.getName()); + AudioSharingProgressDialogFragment progressFragment = + (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); // TODO: use string res once finalized String expectedMessage = "Starting audio stream..."; - checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + checkProgressDialogMessage(progressFragment, expectedMessage); when(mBroadcast.isEnabled(null)).thenReturn(true); when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata); @@ -642,13 +642,13 @@ public class AudioSharingSwitchBarControllerTest { .action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING)); // TODO: use string res once finalized expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "..."; - checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + checkProgressDialogMessage(progressFragment, expectedMessage); childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments) .comparingElementsUsing(CLAZZNAME_EQUALS) .containsExactly(AudioSharingDialogFragment.class.getName(), - AudioSharingLoadingStateDialogFragment.class.getName()); + AudioSharingProgressDialogFragment.class.getName()); Pair[] eventData = new Pair[0]; for (Fragment fragment : childFragments) { @@ -708,15 +708,15 @@ public class AudioSharingSwitchBarControllerTest { verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false); assertThat(dialog.isShowing()).isFalse(); - // Loading state dialog shows sharing state for the user chosen sink. + // Progress dialog shows sharing progress for the user chosen sink. List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); - AudioSharingLoadingStateDialogFragment loadingFragment = - (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments); + AudioSharingProgressDialogFragment.class.getName()); + AudioSharingProgressDialogFragment progressFragment = + (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); // TODO: use string res once finalized String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "..."; - checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + checkProgressDialogMessage(progressFragment, expectedMessage); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); } @@ -749,15 +749,15 @@ public class AudioSharingSwitchBarControllerTest { verify(mAssistant, never()).addSource(mDevice1, mMetadata, /* isGroupOp= */ false); assertThat(dialog.isShowing()).isFalse(); - // Loading state dialog shows sharing state for the auto add active sink. + // Progress dialog shows sharing progress for the auto add active sink. List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); - AudioSharingLoadingStateDialogFragment loadingFragment = - (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments); + AudioSharingProgressDialogFragment.class.getName()); + AudioSharingProgressDialogFragment progressFragment = + (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); // TODO: use string res once finalized String expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "..."; - checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + checkProgressDialogMessage(progressFragment, expectedMessage); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); } @@ -854,7 +854,7 @@ public class AudioSharingSwitchBarControllerTest { mDevice1, mMetadata, /* reason= */ 1); shadowMainLooper().idle(); - // Loading state dialog shows sharing state for the user chosen sink. + // Progress dialog shows sharing progress for the user chosen sink. List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( AudioSharingRetryDialogFragment.class.getName()); @@ -868,12 +868,12 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void testAssistantCallbacks_onReceiveStateChanged_dismissLoadingDialog() { - AudioSharingLoadingStateDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1); + public void testAssistantCallbacks_onReceiveStateChanged_dismissProgressDialog() { + AudioSharingProgressDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1); shadowOf(Looper.getMainLooper()).idle(); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); + AudioSharingProgressDialogFragment.class.getName()); when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L)); mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1, @@ -1023,13 +1023,13 @@ public class AudioSharingSwitchBarControllerTest { List childFragments = parentFragment.getChildFragmentManager().getFragments(); // Skip audio sharing dialog. assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); - // The loading state dialog shows sharing state for the auto add second sink. - AudioSharingLoadingStateDialogFragment loadingFragment = - (AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments); + AudioSharingProgressDialogFragment.class.getName()); + // Progress dialog shows sharing progress for the auto add second sink. + AudioSharingProgressDialogFragment progressFragment = + (AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments); // TODO: use string res once finalized String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "..."; - checkLoadingStateDialogMessage(loadingFragment, expectedMessage); + checkProgressDialogMessage(progressFragment, expectedMessage); childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss()); } @@ -1044,7 +1044,7 @@ public class AudioSharingSwitchBarControllerTest { verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false); List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingLoadingStateDialogFragment.class.getName()); + AudioSharingProgressDialogFragment.class.getName()); } private Fragment setUpFragmentWithStartSharingIntent() { @@ -1064,12 +1064,12 @@ public class AudioSharingSwitchBarControllerTest { return fragment; } - private void checkLoadingStateDialogMessage( - @NonNull AudioSharingLoadingStateDialogFragment fragment, + private void checkProgressDialogMessage( + @NonNull AudioSharingProgressDialogFragment fragment, @NonNull String expectedMessage) { - TextView loadingMessage = fragment.getDialog() == null ? null + TextView progressMessage = fragment.getDialog() == null ? null : fragment.getDialog().findViewById(R.id.message); - assertThat(loadingMessage).isNotNull(); - assertThat(loadingMessage.getText().toString()).isEqualTo(expectedMessage); + assertThat(progressMessage).isNotNull(); + assertThat(progressMessage.getText().toString()).isEqualTo(expectedMessage); } } From 51fc7a8239e333b4c30ec930310acfa67187d659 Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Mon, 23 Sep 2024 16:20:48 +0800 Subject: [PATCH 11/16] Rename AudioSharingRetryDialogFragment Test: atest Flag: com.android.settingslib.flags.enable_le_audio_sharing Bug: 362858894 Change-Id: I157b036541e9a7b21205ee45437bfd4562c49118 --- ...va => AudioSharingErrorDialogFragment.java} | 10 +++++----- .../AudioSharingSwitchBarController.java | 18 +++++++++--------- ...> AudioSharingErrorDialogFragmentTest.java} | 14 +++++++------- .../AudioSharingSwitchBarControllerTest.java | 4 ++-- 4 files changed, 23 insertions(+), 23 deletions(-) rename src/com/android/settings/connecteddevice/audiosharing/{AudioSharingRetryDialogFragment.java => AudioSharingErrorDialogFragment.java} (89%) rename tests/robotests/src/com/android/settings/connecteddevice/audiosharing/{AudioSharingRetryDialogFragmentTest.java => AudioSharingErrorDialogFragmentTest.java} (91%) diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragment.java similarity index 89% rename from src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragment.java rename to src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragment.java index 822e0537149..95b9bc36b92 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragment.java @@ -29,8 +29,8 @@ import androidx.fragment.app.FragmentManager; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settingslib.bluetooth.BluetoothUtils; -public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment { - private static final String TAG = "AudioSharingRetryDialog"; +public class AudioSharingErrorDialogFragment extends InstrumentedDialogFragment { + private static final String TAG = "AudioSharingErrorDialog"; @Override public int getMetricsCategory() { @@ -39,7 +39,7 @@ public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment } /** - * Display the {@link AudioSharingRetryDialogFragment} dialog. + * Display the {@link AudioSharingErrorDialogFragment} dialog. * * @param host The Fragment this dialog will be hosted. */ @@ -57,8 +57,8 @@ public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment Log.d(TAG, "Dialog is showing, return."); return; } - Log.d(TAG, "Show up the retry dialog."); - AudioSharingRetryDialogFragment dialogFrag = new AudioSharingRetryDialogFragment(); + Log.d(TAG, "Show up the error dialog."); + AudioSharingErrorDialogFragment dialogFrag = new AudioSharingErrorDialogFragment(); dialogFrag.show(manager, TAG); } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java index 68dba54de6b..ebc8cecadbf 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java @@ -161,7 +161,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController public void onBroadcastStartFailed(int reason) { Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); updateSwitch(); - showRetryDialog(); + showErrorDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_START_FAILED, @@ -190,7 +190,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController mStoppingSharing.compareAndSet(true, false); updateSwitch(); AudioSharingUtils.postOnMainThread(mContext, - () -> dismissStaleDialogsOtherThanRetryDialog()); + () -> dismissStaleDialogsOtherThanErrorDialog()); AudioSharingUtils.toastMessage( mContext, mContext.getString(R.string.audio_sharing_sharing_stopped_label)); @@ -278,7 +278,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController + reason); if (mSinksInAdding.contains(sink)) { stopAudioSharing(); - showRetryDialog(); + showErrorDialog(); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED, @@ -742,17 +742,17 @@ public class AudioSharingSwitchBarController extends BasePreferenceController }); } - private void showRetryDialog() { + private void showErrorDialog() { AudioSharingUtils.postOnMainThread(mContext, () -> { - // Remove all opening dialogs before show retry dialog - dismissStaleDialogsOtherThanRetryDialog(); - AudioSharingRetryDialogFragment.show(mFragment); + // Remove all stale dialogs before showing error dialog + dismissStaleDialogsOtherThanErrorDialog(); + AudioSharingErrorDialogFragment.show(mFragment); }); } @UiThread - private void dismissStaleDialogsOtherThanRetryDialog() { + private void dismissStaleDialogsOtherThanErrorDialog() { List fragments = new ArrayList(); try { if (mFragment != null) { @@ -764,7 +764,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController } for (Fragment fragment : fragments) { if (fragment != null && fragment instanceof DialogFragment - && !(fragment instanceof AudioSharingRetryDialogFragment) + && !(fragment instanceof AudioSharingErrorDialogFragment) && ((DialogFragment) fragment).getDialog() != null) { Log.d(TAG, "Remove stale dialog = " + fragment.getTag()); ((DialogFragment) fragment).dismiss(); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragmentTest.java similarity index 91% rename from tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragmentTest.java rename to tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragmentTest.java index 4b0524b848a..fc38cd2817d 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingRetryDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingErrorDialogFragmentTest.java @@ -51,14 +51,14 @@ import org.robolectric.shadows.androidx.fragment.FragmentController; ShadowAlertDialogCompat.class, ShadowBluetoothAdapter.class, }) -public class AudioSharingRetryDialogFragmentTest { +public class AudioSharingErrorDialogFragmentTest { @Rule public final MockitoRule mocks = MockitoJUnit.rule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Fragment mParent; - private AudioSharingRetryDialogFragment mFragment; + private AudioSharingErrorDialogFragment mFragment; @Before public void setUp() { @@ -70,7 +70,7 @@ public class AudioSharingRetryDialogFragmentTest { BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); - mFragment = new AudioSharingRetryDialogFragment(); + mFragment = new AudioSharingErrorDialogFragment(); mParent = new Fragment(); FragmentController.setupFragment( mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null); @@ -91,7 +91,7 @@ public class AudioSharingRetryDialogFragmentTest { @Test public void onCreateDialog_flagOff_dialogNotExist() { mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingRetryDialogFragment.show(mParent); + AudioSharingErrorDialogFragment.show(mParent); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNull(); @@ -100,7 +100,7 @@ public class AudioSharingRetryDialogFragmentTest { @Test public void onCreateDialog_unattachedFragment_dialogNotExist() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingRetryDialogFragment.show(new Fragment()); + AudioSharingErrorDialogFragment.show(new Fragment()); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNull(); @@ -109,7 +109,7 @@ public class AudioSharingRetryDialogFragmentTest { @Test public void onCreateDialog_flagOn_showDialog() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingRetryDialogFragment.show(mParent); + AudioSharingErrorDialogFragment.show(mParent); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); @@ -119,7 +119,7 @@ public class AudioSharingRetryDialogFragmentTest { @Test public void onCreateDialog_clickOk_dialogDismiss() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); - AudioSharingRetryDialogFragment.show(mParent); + AudioSharingErrorDialogFragment.show(mParent); shadowMainLooper().idle(); AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(dialog).isNotNull(); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java index 8865e6f7234..58696dccbea 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarControllerTest.java @@ -821,7 +821,7 @@ public class AudioSharingSwitchBarControllerTest { } @Test - public void testAssistantCallbacks_onSourceAddFailed_twoDevices_showRetryAndLogAction() { + public void testAssistantCallbacks_onSourceAddFailed_twoDevices_showErrorAndLogAction() { FeatureFlagUtils.setEnabled( mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true); when(mBtnView.isEnabled()).thenReturn(true); @@ -857,7 +857,7 @@ public class AudioSharingSwitchBarControllerTest { // Progress dialog shows sharing progress for the user chosen sink. List childFragments = mParentFragment.getChildFragmentManager().getFragments(); assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly( - AudioSharingRetryDialogFragment.class.getName()); + AudioSharingErrorDialogFragment.class.getName()); verify(mFeatureFactory.metricsFeatureProvider) .action( mContext, From 6fe2f89f7c67430d7b865b1761a0fad645393bc5 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Mon, 23 Sep 2024 10:40:03 +0800 Subject: [PATCH 12/16] Migrate "Baseband version" preference Bug: 365886251 Flag: com.android.settings.flags.catalyst_firmware_version Test: Unit Change-Id: I8e4f946d01169e8008b8a336d308f5874ee918e6 --- .../BasebandVersionPreference.kt | 57 ++++++++++++++++++ .../BasebandVersionPreferenceController.java | 2 + .../firmwareversion/FirmwareVersionScreen.kt | 2 +- tests/robotests/Android.bp | 3 + ...sebandVersionPreferenceControllerTest.java | 2 + .../BasebandVersionPreferenceTest.kt | 60 +++++++++++++++++++ 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreference.kt create mode 100644 tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceTest.kt diff --git a/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreference.kt b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreference.kt new file mode 100644 index 00000000000..fb27dd814c8 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreference.kt @@ -0,0 +1,57 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import android.os.SystemProperties +import androidx.preference.Preference +import com.android.settings.R +import com.android.settings.Utils +import com.android.settingslib.metadata.PreferenceAvailabilityProvider +import com.android.settingslib.metadata.PreferenceMetadata +import com.android.settingslib.metadata.PreferenceSummaryProvider +import com.android.settingslib.preference.PreferenceBinding + +// LINT.IfChange +class BasebandVersionPreference : + PreferenceMetadata, + PreferenceSummaryProvider, + PreferenceAvailabilityProvider, + PreferenceBinding { + + override val key: String + get() = "base_band" + + override val title: Int + get() = R.string.baseband_version + + override fun getSummary(context: Context): CharSequence? = + SystemProperties.get(BASEBAND_PROPERTY, context.getString(R.string.device_info_default)) + + override fun isAvailable(context: Context) = !Utils.isWifiOnly(context) + + override fun bind(preference: Preference, metadata: PreferenceMetadata) { + super.bind(preference, metadata) + preference.isSelectable = false + preference.isCopyingEnabled = true + } + + companion object { + const val BASEBAND_PROPERTY: String = "gsm.version.baseband" + } +} +// LINT.ThenChange(BasebandVersionPreferenceController.java) diff --git a/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java index dd3d560282a..235638433be 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceController.java @@ -25,6 +25,7 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.BasePreferenceController; +// LINT.IfChange public class BasebandVersionPreferenceController extends BasePreferenceController { @VisibleForTesting @@ -45,3 +46,4 @@ public class BasebandVersionPreferenceController extends BasePreferenceControlle mContext.getString(R.string.device_info_default)); } } +// LINT.ThenChange(BasebandVersionPreference.kt) diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt index 58fdefe6e4a..3b70e72ae47 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt +++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt @@ -50,7 +50,7 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider +PreferenceWidget("os_firmware_version", R.string.firmware_version) +PreferenceWidget("security_key", R.string.security_patch) +PreferenceWidget("module_version", R.string.module_version) - +PreferenceWidget("base_band", R.string.baseband_version) + +BasebandVersionPreference() +PreferenceWidget("kernel_version", R.string.kernel_version) +PreferenceWidget("os_build_number", R.string.build_number) } diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp index 3fd430610d3..60a68033c95 100644 --- a/tests/robotests/Android.bp +++ b/tests/robotests/Android.bp @@ -69,6 +69,9 @@ android_robolectric_test { "com_android_server_accessibility_flags_lib", "flag-junit", "flag-junit-base", + "kotlin-test", + "mockito-robolectric-prebuilt", // mockito deps order matters! + "mockito-kotlin2", "notification_flags_lib", "platform-test-annotations", "testables", diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceControllerTest.java index 87fdb222c42..5d7e82e98eb 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceControllerTest.java @@ -38,6 +38,7 @@ import org.robolectric.RuntimeEnvironment; import java.util.Arrays; +// LINT.IfChange @RunWith(RobolectricTestRunner.class) public class BasebandVersionPreferenceControllerTest { @Mock @@ -68,3 +69,4 @@ public class BasebandVersionPreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } } +// LINT.ThenChange(BasebandVersionPreferenceTest.kt) diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceTest.kt b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceTest.kt new file mode 100644 index 00000000000..27220380712 --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/BasebandVersionPreferenceTest.kt @@ -0,0 +1,60 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import android.content.ContextWrapper +import android.sysprop.TelephonyProperties +import android.telephony.TelephonyManager +import androidx.test.core.app.ApplicationProvider +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.robolectric.RobolectricTestRunner + +// LINT.IfChange +@RunWith(RobolectricTestRunner::class) +class BasebandVersionPreferenceTest { + private lateinit var telephonyManager: TelephonyManager + + private val context: Context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when { + name == getSystemServiceName(TelephonyManager::class.java) -> telephonyManager + else -> super.getSystemService(name) + } + } + + private val basebandVersionPreference = BasebandVersionPreference() + + @Test + fun isAvailable_wifiOnly_unavailable() { + telephonyManager = mock { on { isDataCapable } doReturn false } + assertThat(basebandVersionPreference.isAvailable(context)).isFalse() + } + + @Test + fun isAvailable_hasMobile_available() { + TelephonyProperties.baseband_version(listOf("test")) + telephonyManager = mock { on { isDataCapable } doReturn true } + assertThat(basebandVersionPreference.isAvailable(context)).isTrue() + } +} +// LINT.ThenChange(BasebandVersionPreferenceControllerTest.java) From fb349fad1a62128f689efe6f7cb451678cfa2864 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Mon, 23 Sep 2024 11:34:25 +0800 Subject: [PATCH 13/16] Migrate "Kernel version" preference Bug: 365886251 Flag: com.android.settings.flags.catalyst_firmware_version Test: Unit Change-Id: Icb50e2d5200f7de40b6f8383c114982cd45d34b5 --- .../firmwareversion/FirmwareVersionScreen.kt | 2 +- .../KernelVersionPreference.kt | 45 +++++++++++++++++++ .../KernelVersionPreferenceController.java | 2 + ...KernelVersionPreferenceControllerTest.java | 2 + .../KernelVersionPreferenceTest.kt | 40 +++++++++++++++++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreference.kt create mode 100644 tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceTest.kt diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt index 3b70e72ae47..401cd16c03e 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt +++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt @@ -51,7 +51,7 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider +PreferenceWidget("security_key", R.string.security_patch) +PreferenceWidget("module_version", R.string.module_version) +BasebandVersionPreference() - +PreferenceWidget("kernel_version", R.string.kernel_version) + +KernelVersionPreference() +PreferenceWidget("os_build_number", R.string.build_number) } diff --git a/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreference.kt b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreference.kt new file mode 100644 index 00000000000..789117852b5 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreference.kt @@ -0,0 +1,45 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import androidx.preference.Preference +import com.android.settings.R +import com.android.settingslib.DeviceInfoUtils +import com.android.settingslib.metadata.PreferenceMetadata +import com.android.settingslib.metadata.PreferenceSummaryProvider +import com.android.settingslib.preference.PreferenceBinding + +// LINT.IfChange +class KernelVersionPreference : PreferenceMetadata, PreferenceSummaryProvider, PreferenceBinding { + + override val key: String + get() = "kernel_version" + + override val title: Int + get() = R.string.kernel_version + + override fun getSummary(context: Context): CharSequence? = + DeviceInfoUtils.getFormattedKernelVersion(context) + + override fun bind(preference: Preference, metadata: PreferenceMetadata) { + super.bind(preference, metadata) + preference.isSelectable = false + preference.isCopyingEnabled = true + } +} +// LINT.ThenChange(KernelVersionPreferenceController.java) diff --git a/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java index 0500c89371a..7a3bdafb5e7 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceController.java @@ -21,6 +21,7 @@ import android.content.Context; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.DeviceInfoUtils; +// LINT.IfChange public class KernelVersionPreferenceController extends BasePreferenceController { public KernelVersionPreferenceController(Context context, String preferenceKey) { @@ -37,3 +38,4 @@ public class KernelVersionPreferenceController extends BasePreferenceController return DeviceInfoUtils.getFormattedKernelVersion(mContext); } } +// LINT.ThenChange(KernelVersionPreference.kt) diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceControllerTest.java index 9ee0bb32d99..145940608a9 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceControllerTest.java @@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +// LINT.IfChange @RunWith(RobolectricTestRunner.class) public class KernelVersionPreferenceControllerTest { @@ -49,3 +50,4 @@ public class KernelVersionPreferenceControllerTest { DeviceInfoUtils.getFormattedKernelVersion(mContext)); } } +// LINT.ThenChange(KernelVersionPreferenceTest.kt) diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceTest.kt b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceTest.kt new file mode 100644 index 00000000000..162fc15eca5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/KernelVersionPreferenceTest.kt @@ -0,0 +1,40 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import com.android.settingslib.DeviceInfoUtils +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +// LINT.IfChange +@RunWith(RobolectricTestRunner::class) +class KernelVersionPreferenceTest { + private val context: Context = ApplicationProvider.getApplicationContext() + + private val kernelVersionPreference = KernelVersionPreference() + + @Test + fun getSummary() { + assertThat(kernelVersionPreference.getSummary(context)) + .isEqualTo(DeviceInfoUtils.getFormattedKernelVersion(context)) + } +} +// LINT.ThenChange(KernelVersionPreferenceControllerTest.java) From 9cbb04c5e055d59982f29eed5b56c399215e7982 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Mon, 23 Sep 2024 11:56:43 +0800 Subject: [PATCH 14/16] Migrate "Build number" preference Bug: 365886251 Flag: com.android.settings.flags.catalyst_firmware_version Test: Unit Change-Id: Iee68b5414713118ad3d1b9b3ec04437729bb2d0b --- .../firmwareversion/FirmwareVersionScreen.kt | 2 +- .../SimpleBuildNumberPreference.kt | 52 ++++++++++++++++++ ...SimpleBuildNumberPreferenceController.java | 2 + ...leBuildNumberPreferenceControllerTest.java | 2 + .../SimpleBuildNumberPreferenceTest.kt | 55 +++++++++++++++++++ 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreference.kt create mode 100644 tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceTest.kt diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt index 401cd16c03e..0908f9eaa85 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt +++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionScreen.kt @@ -52,7 +52,7 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider +PreferenceWidget("module_version", R.string.module_version) +BasebandVersionPreference() +KernelVersionPreference() - +PreferenceWidget("os_build_number", R.string.build_number) + +SimpleBuildNumberPreference() } private class PreferenceWidget(override val key: String, override val title: Int) : diff --git a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreference.kt b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreference.kt new file mode 100644 index 00000000000..62cc2f985e7 --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreference.kt @@ -0,0 +1,52 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import android.os.Build +import android.text.BidiFormatter +import android.view.View.LAYOUT_DIRECTION_RTL +import androidx.preference.Preference +import com.android.settings.R +import com.android.settingslib.metadata.PreferenceMetadata +import com.android.settingslib.metadata.PreferenceSummaryProvider +import com.android.settingslib.preference.PreferenceBinding + +// LINT.IfChange +class SimpleBuildNumberPreference : + PreferenceMetadata, PreferenceSummaryProvider, PreferenceBinding { + + override val key: String + get() = "os_build_number" + + override val title: Int + get() = R.string.build_number + + override fun isIndexable(context: Context) = false + + override fun getSummary(context: Context): CharSequence? { + val isRtl = context.resources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL + return BidiFormatter.getInstance(isRtl).unicodeWrap(Build.DISPLAY) + } + + override fun bind(preference: Preference, metadata: PreferenceMetadata) { + super.bind(preference, metadata) + preference.isSelectable = false + preference.isCopyingEnabled = true + } +} +// LINT.ThenChange(SimpleBuildNumberPreferenceController.java) diff --git a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java index 53f5ff9aa9d..11988f7002e 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java @@ -22,6 +22,7 @@ import android.text.BidiFormatter; import com.android.settings.core.BasePreferenceController; +// LINT.IfChange public class SimpleBuildNumberPreferenceController extends BasePreferenceController { public SimpleBuildNumberPreferenceController(Context context, @@ -39,3 +40,4 @@ public class SimpleBuildNumberPreferenceController extends BasePreferenceControl return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY); } } +// LINT.ThenChange(SimpleBuildNumberPreference.kt) diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java index 3f050db6ab4..4b7dfc5f749 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java @@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +// LINT.IfChange @RunWith(RobolectricTestRunner.class) public class SimpleBuildNumberPreferenceControllerTest { @@ -48,3 +49,4 @@ public class SimpleBuildNumberPreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); } } +// LINT.ThenChange(SimpleBuildNumberPreferenceTest.kt) diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceTest.kt b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceTest.kt new file mode 100644 index 00000000000..9c9dd710b14 --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceTest.kt @@ -0,0 +1,55 @@ +/* + * 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.deviceinfo.firmwareversion + +import android.content.Context +import android.os.Build +import android.text.BidiFormatter +import androidx.test.core.app.ApplicationProvider +import com.google.common.truth.Truth.assertThat +import java.util.Locale +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +// LINT.IfChange +@RunWith(RobolectricTestRunner::class) +class SimpleBuildNumberPreferenceTest { + private val context: Context = ApplicationProvider.getApplicationContext() + + private val simpleBuildNumberPreference = SimpleBuildNumberPreference() + + @Test + fun isIndexable() { + assertThat(simpleBuildNumberPreference.isIndexable(context)).isFalse() + } + + @Test + fun getSummary_ltr() { + context.resources.configuration.setLayoutDirection(Locale.ENGLISH) + assertThat(simpleBuildNumberPreference.getSummary(context)) + .isEqualTo(BidiFormatter.getInstance(false).unicodeWrap(Build.DISPLAY)) + } + + @Test + fun getSummary_rtl() { + context.resources.configuration.setLayoutDirection(Locale("ar")) + assertThat(simpleBuildNumberPreference.getSummary(context)) + .isEqualTo(BidiFormatter.getInstance(true).unicodeWrap(Build.DISPLAY)) + } +} +// LINT.ThenChange(SimpleBuildNumberPreferenceControllerTest.java) From 69604645574723f4b49988aee2fc7bb12f76521d Mon Sep 17 00:00:00 2001 From: songferngwang Date: Mon, 23 Sep 2024 10:39:56 +0000 Subject: [PATCH 15/16] remove the DSDS dialog If the sim onboarding on, then sim should use the sim onboarding flow. Bug: 362289792 Test: manual test Flag: EXEMPT bugfix Change-Id: Ibe22309db9dea5737de5ad351825a046599e6744 --- .../settings/sim/receivers/SimSlotChangeHandler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java index 6e28a0d5a96..f808924fa41 100644 --- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java +++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java @@ -206,7 +206,12 @@ public class SimSlotChangeHandler { if (hasActiveEsimSubscription()) { if (mTelMgr.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) { Log.i(TAG, "Enabled profile exists. DSDS condition satisfied."); - startDsdsDialogActivity(); + if (Flags.isDualSimOnboardingEnabled()) { + // enable dsds by sim onboarding flow + handleRemovableSimInsertWhenDsds(removableSlotInfo); + } else { + startDsdsDialogActivity(); + } } else { Log.i(TAG, "Enabled profile exists. DSDS condition not satisfied."); startChooseSimActivity(true); From bc3f736162191da068b3497b8a27258b00a837b3 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 23 Sep 2024 03:39:10 +0000 Subject: [PATCH 16/16] [Settings] Fix crash Bug: 366361808 Change-Id: I3f804685e215ed07b71a5efd51c9da9c5b978279 Test: manual Flag: EXEMPT bugfix --- src/com/android/settings/widget/TickButtonPreference.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/com/android/settings/widget/TickButtonPreference.java b/src/com/android/settings/widget/TickButtonPreference.java index 4778f8c8ee0..6bd17dea1b3 100644 --- a/src/com/android/settings/widget/TickButtonPreference.java +++ b/src/com/android/settings/widget/TickButtonPreference.java @@ -21,6 +21,8 @@ import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; +import androidx.annotation.Nullable; +import androidx.annotation.NonNull; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; @@ -35,6 +37,10 @@ public class TickButtonPreference extends TwoTargetPreference { super(context); } + public TickButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder);