diff --git a/res/values/strings.xml b/res/values/strings.xml index 39e0dbdf4e8..c49d6e3f767 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10399,7 +10399,7 @@ Allowing %1$s to always run in the background may reduce battery life. - \n\nYou can change this later from Settings > Apps. + \n\nYou can change this later from Settings -> Apps. %1$s use since last full charge diff --git a/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt b/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt index bf2776dc97f..0665e96d5b4 100644 --- a/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt +++ b/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt @@ -17,9 +17,12 @@ package com.android.settings.accessibility import android.annotation.DrawableRes +import android.app.settings.SettingsEnums.ACTION_REMOVE_ANIMATION import android.content.Context import android.provider.Settings +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_REMOVE_ANIMATION import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObserver @@ -37,6 +40,7 @@ class RemoveAnimationsPreference : R.string.accessibility_disable_animations, R.string.accessibility_disable_animations_summary, ), + PreferenceActionMetricsProvider, PreferenceLifecycleProvider { private var mSettingsKeyedObserver: KeyedObserver? = null @@ -44,6 +48,11 @@ class RemoveAnimationsPreference : override val icon: Int @DrawableRes get() = R.drawable.ic_accessibility_animation + override val preferenceActionMetrics: Int + get() = ACTION_REMOVE_ANIMATION + + override fun tags(context: Context) = arrayOf(KEY_REMOVE_ANIMATION) + override fun onStart(context: PreferenceLifecycleContext) { val observer = KeyedObserver { _, _ -> context.notifyPreferenceChange(KEY) } mSettingsKeyedObserver = observer diff --git a/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt index a9a05160557..54b1d9588e2 100644 --- a/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt +++ b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt @@ -15,13 +15,16 @@ */ package com.android.settings.accessibility +import android.app.settings.SettingsEnums.ACTION_VIBRATION_HAPTICS import android.content.Context import android.os.VibrationAttributes import android.os.Vibrator import android.provider.Settings import android.widget.CompoundButton import android.widget.CompoundButton.OnCheckedChangeListener +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_VIBRATION_HAPTICS import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsStore @@ -39,6 +42,7 @@ class VibrationMainSwitchPreference : key = Settings.System.VIBRATE_ON, title = R.string.accessibility_vibration_primary_switch_title, ), + PreferenceActionMetricsProvider, PreferenceLifecycleProvider, OnCheckedChangeListener { override val keywords: Int @@ -46,6 +50,11 @@ class VibrationMainSwitchPreference : lateinit var vibrator: Vibrator + override val preferenceActionMetrics: Int + get() = ACTION_VIBRATION_HAPTICS + + override fun tags(context: Context) = arrayOf(KEY_VIBRATION_HAPTICS) + override fun storage(context: Context): KeyValueStore = VibrationMainSwitchToggleStorage(SettingsSystemStore.get(context)) diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java index 33eba1074c4..86f0314716f 100644 --- a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java +++ b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java @@ -46,6 +46,7 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.HearingAidStatsLogUtils; +import com.android.settingslib.flags.Flags; import com.android.settingslib.utils.ThreadUtils; import com.google.common.collect.ImmutableList; @@ -62,6 +63,7 @@ import java.util.concurrent.TimeUnit; public abstract class BluetoothDevicePairingDetailBase extends DeviceListPreferenceFragment { private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15); private static final int AUTO_DISMISS_MESSAGE_ID = 1001; + private static final int AUTO_FINISH_MESSAGE_ID = 1002; private static final ImmutableList AUDIO_SHARING_PROFILES = ImmutableList.of( BluetoothProfile.LE_AUDIO, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, BluetoothProfile.VOLUME_CONTROL); @@ -77,7 +79,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere @Nullable ProgressDialogFragment mProgressDialog = null; @VisibleForTesting - boolean mShouldTriggerAudioSharingShareThenPairFlow = false; + boolean mShouldTriggerShareThenPairFlow = false; private CopyOnWriteArrayList mDevicesWithMetadataChangedListener = new CopyOnWriteArrayList<>(); @@ -89,7 +91,8 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere // onDeviceBondStateChanged(BOND_BONDED), BluetoothDevicePreference's summary has already // change from "Pairing..." to empty since it listens to metadata changes happens earlier. // - // In share then pair flow, we have to wait on this page till the device is connected. + // In pairing flow during audio sharing, we have to wait on this page till the device is + // connected to check the device type and handle extra logic for audio sharing. // 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 progress dialog with "Connecting to ...." once BluetoothDevice.getState() @@ -100,10 +103,11 @@ 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 && mProgressDialog == null + if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata()) + && mProgressDialog == null && device.getBondState() == BluetoothDevice.BOND_BONDED && mSelectedList.contains(device)) { - triggerAudioSharingShareThenPairFlow(device); + handleDeviceBondedInAudioSharing(device); // Once device is bonded, remove the listener removeOnMetadataChangedListener(device); } @@ -133,7 +137,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere return; } updateBluetooth(); - mShouldTriggerAudioSharingShareThenPairFlow = shouldTriggerAudioSharingShareThenPairFlow(); + mShouldTriggerShareThenPairFlow = shouldTriggerShareThenPairFlow(); } @Override @@ -177,11 +181,12 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere @Override public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { + boolean shouldSetTempBond = shouldSetTempBondMetadata(); if (bondState == BluetoothDevice.BOND_BONDED) { - if (cachedDevice != null && mShouldTriggerAudioSharingShareThenPairFlow) { + if (cachedDevice != null && (mShouldTriggerShareThenPairFlow || shouldSetTempBond)) { BluetoothDevice device = cachedDevice.getDevice(); if (device != null && mSelectedList.contains(device)) { - triggerAudioSharingShareThenPairFlow(device); + handleDeviceBondedInAudioSharing(device); removeOnMetadataChangedListener(device); return; } @@ -190,7 +195,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere finish(); return; } else if (bondState == BluetoothDevice.BOND_BONDING) { - if (mShouldTriggerAudioSharingShareThenPairFlow && cachedDevice != null) { + if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) { BluetoothDevice device = cachedDevice.getDevice(); if (device != null && mSelectedList.contains(device)) { addOnMetadataChangedListener(device); @@ -203,7 +208,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere pageId); HearingAidStatsLogUtils.setBondEntryForDevice(bondEntry, cachedDevice); } else if (bondState == BluetoothDevice.BOND_NONE) { - if (mShouldTriggerAudioSharingShareThenPairFlow && cachedDevice != null) { + if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) { BluetoothDevice device = cachedDevice.getDevice(); if (device != null && mSelectedList.contains(device)) { removeOnMetadataChangedListener(device); @@ -233,21 +238,29 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere final BluetoothDevice device = cachedDevice.getDevice(); if (device != null && mSelectedList.contains(device)) { - if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) { - if (mShouldTriggerAudioSharingShareThenPairFlow - && state == BluetoothAdapter.STATE_CONNECTED - && device.equals(mJustBonded) - && AUDIO_SHARING_PROFILES.contains(bluetoothProfile) - && isReadyForAudioSharing(cachedDevice, bluetoothProfile)) { - Log.d(getLogTag(), - "onProfileConnectionStateChanged, ready for audio sharing"); - dismissConnectingDialog(); - mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID); - finishFragmentWithResultForAudioSharing(device); + var unused = ThreadUtils.postOnBackgroundThread(() -> { + if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) { + if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata()) + && state == BluetoothAdapter.STATE_CONNECTED + && device.equals(mJustBonded) + && AUDIO_SHARING_PROFILES.contains(bluetoothProfile) + && isReadyForAudioSharing(cachedDevice, bluetoothProfile)) { + Log.d(getLogTag(), "onProfileConnectionStateChanged, lea eligible"); + dismissConnectingDialog(); + BluetoothUtils.setTemporaryBondMetadata(device); + if (mShouldTriggerShareThenPairFlow) { + mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID); + postOnMainThread(() -> + finishFragmentWithResultForAudioSharing(device)); + } else { + mHandler.removeMessages(AUTO_FINISH_MESSAGE_ID); + postOnMainThread(() -> finish()); + } + } + } else { + postOnMainThread(() -> finish()); } - } else { - finish(); - } + }); } else { onDeviceDeleted(cachedDevice); } @@ -314,7 +327,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere } @VisibleForTesting - boolean shouldTriggerAudioSharingShareThenPairFlow() { + boolean shouldTriggerShareThenPairFlow() { if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) { Activity activity = getActivity(); Intent intent = activity == null ? null : activity.getIntent(); @@ -328,6 +341,16 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere return false; } + private boolean shouldSetTempBondMetadata() { + return Flags.enableTemporaryBondDevicesUi() + && BluetoothUtils.isAudioSharingUIAvailable(getContext()) + && BluetoothUtils.isBroadcasting(mLocalManager) + && mLocalManager != null + && mLocalManager.getCachedDeviceManager() != null + && mLocalManager.getProfileManager().getLeAudioBroadcastAssistantProfile() != null + && !Utils.shouldBlockPairingInAudioSharing(mLocalManager); + } + private boolean isReadyForAudioSharing(@NonNull CachedBluetoothDevice cachedDevice, int justConnectedProfile) { for (int profile : AUDIO_SHARING_PROFILES) { @@ -382,11 +405,10 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere }); } - private void triggerAudioSharingShareThenPairFlow( - @NonNull BluetoothDevice device) { + private void handleDeviceBondedInAudioSharing(@Nullable BluetoothDevice device) { var unused = ThreadUtils.postOnBackgroundThread(() -> { if (mJustBonded != null) { - Log.d(getLogTag(), "Skip triggerAudioSharingShareThenPairFlow, already done"); + Log.d(getLogTag(), "Skip handleDeviceBondedInAudioSharing, already done"); return; } mJustBonded = device; @@ -395,17 +417,38 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress() : aliasName; showConnectingDialog(deviceName); - // Wait for AUTO_DISMISS_TIME_THRESHOLD_MS and check if the paired device supports audio - // sharing. - if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) { - mHandler.postDelayed(() -> - postOnMainThread( - () -> { - Log.d(getLogTag(), "Show incompatible dialog when timeout"); - dismissConnectingDialog(); - AudioSharingIncompatibleDialogFragment.show(this, deviceName, - () -> finish()); - }), AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS); + if (mShouldTriggerShareThenPairFlow) { + // For share then pair flow, we have strong signal that users wish to pair new + // device to join sharing. + // So we wait for AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device + // is lea in onProfileConnectionStateChanged, we finish the activity, set the device + // as temp bond and auto add source; otherwise, show dialog to notify that the + // device is incompatible for audio sharing. + if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) { + mHandler.postDelayed(() -> + postOnMainThread( + () -> { + Log.d(getLogTag(), + "Show incompatible dialog when timeout"); + dismissConnectingDialog(); + AudioSharingIncompatibleDialogFragment.show(this, + deviceName, + () -> finish()); + }), AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS); + } + } else { + // For other pairing request during audio sharing with sinks < 2, we wait for + // AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device is lea in + // onProfileConnectionStateChanged, we finish the activity and set the device as + // temp bond; otherwise, we just finish the activity. + if (!mHandler.hasMessages(AUTO_FINISH_MESSAGE_ID)) { + mHandler.postDelayed(() -> + postOnMainThread( + () -> { + Log.d(getLogTag(), "Finish activity when timeout"); + finish(); + }), AUTO_FINISH_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS); + } } }); } diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java index 6404f31a5f2..ea76fafc3a5 100644 --- a/src/com/android/settings/bluetooth/Utils.java +++ b/src/com/android/settings/bluetooth/Utils.java @@ -33,6 +33,7 @@ import android.provider.Settings; import android.util.Log; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; @@ -42,17 +43,21 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; import com.android.settingslib.utils.ThreadUtils; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; +import java.util.stream.Collectors; /** * Utils is a helper class that contains constants for various @@ -293,4 +298,30 @@ public final class Utils { ThreadUtils.postOnMainThread(runnable); }); } + + /** + * Check if need to block pairing during audio sharing + * + * @param localBtManager {@link LocalBluetoothManager} + * @return if need to block pairing during audio sharing + */ + public static boolean shouldBlockPairingInAudioSharing( + @NonNull LocalBluetoothManager localBtManager) { + if (!BluetoothUtils.isBroadcasting(localBtManager)) return false; + LocalBluetoothLeBroadcastAssistant assistant = + localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile(); + CachedBluetoothDeviceManager deviceManager = localBtManager.getCachedDeviceManager(); + List connectedDevices = + assistant == null ? ImmutableList.of() : assistant.getAllConnectedDevices(); + // Block the pairing if there is ongoing audio sharing session and + // a) there is already one temp bond sink connected + // or b) there are already two sinks joining the audio sharing + return assistant != null && deviceManager != null + && (connectedDevices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice) + || connectedDevices.stream().filter( + d -> BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(d, + localBtManager)) + .map(d -> BluetoothUtils.getGroupId(deviceManager.findDevice(d))).collect( + Collectors.toSet()).size() >= 2); + } } diff --git a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt index a3c710c59db..949d5bb418d 100644 --- a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt +++ b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt @@ -159,8 +159,6 @@ class TopologyScale( } } -const val TOPOLOGY_PREFERENCE_KEY = "display_topology_preference" - /** Represents a draggable block in the topology pane. */ class DisplayBlock(context : Context) : Button(context) { @VisibleForTesting var mSelectedImage: Drawable = ColorDrawable(Color.BLACK) @@ -240,7 +238,6 @@ class DisplayTopologyPreference(context : Context) // Prevent highlight when hovering with mouse. isSelectable = false - key = TOPOLOGY_PREFERENCE_KEY isPersistent = false injector = Injector(context) diff --git a/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java b/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java index 2b92e50a2b7..af03bab7579 100644 --- a/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java +++ b/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java @@ -64,33 +64,69 @@ import java.util.List; * The Settings screen for External Displays configuration and connection management. */ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmentBase { + @VisibleForTesting enum PrefBasics { + DISPLAY_TOPOLOGY(10, "display_topology_preference", null), + MIRROR(20, "mirror_preference", null), + + // If shown, use toggle should be before other per-display settings. + EXTERNAL_DISPLAY_USE(30, "external_display_use_preference", + R.string.external_display_use_title), + + ILLUSTRATION(35, "external_display_illustration", null), + + // If shown, external display size is before other per-display settings. + EXTERNAL_DISPLAY_SIZE(40, "external_display_size", R.string.screen_zoom_title), + EXTERNAL_DISPLAY_ROTATION(50, "external_display_rotation", + R.string.external_display_rotation), + EXTERNAL_DISPLAY_RESOLUTION(60, "external_display_resolution", + R.string.external_display_resolution_settings_title), + + // Built-in display link is after per-display settings. + BUILTIN_DISPLAY_LIST(70, "builtin_display_list_preference", + R.string.builtin_display_settings_category), + + DISPLAYS_LIST(80, "displays_list_preference", null), + + // If shown, footer should appear below everything. + FOOTER(90, "footer_preference", null); + + + PrefBasics(int order, String key, @Nullable Integer titleResource) { + this.order = order; + this.key = key; + this.titleResource = titleResource; + } + + // Fields must be public to make the linter happy. + public final int order; + public final String key; + @Nullable public final Integer titleResource; + + void apply(Preference preference) { + if (order != -1) { + preference.setOrder(order); + } + if (titleResource != null) { + preference.setTitle(titleResource); + } + preference.setKey(key); + preference.setPersistent(false); + } + } + static final int EXTERNAL_DISPLAY_SETTINGS_RESOURCE = R.xml.external_display_settings; - static final String DISPLAYS_LIST_PREFERENCE_KEY = "displays_list_preference"; - static final String BUILTIN_DISPLAY_LIST_PREFERENCE_KEY = "builtin_display_list_preference"; - static final String EXTERNAL_DISPLAY_USE_PREFERENCE_KEY = "external_display_use_preference"; - static final String EXTERNAL_DISPLAY_ROTATION_KEY = "external_display_rotation"; - static final String EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY = "external_display_resolution"; - static final String EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY = "external_display_size"; static final int EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE = R.string.external_display_change_resolution_footer_title; static final int EXTERNAL_DISPLAY_LANDSCAPE_DRAWABLE = R.drawable.external_display_mirror_landscape; static final int EXTERNAL_DISPLAY_TITLE_RESOURCE = R.string.external_display_settings_title; - static final int EXTERNAL_DISPLAY_USE_TITLE_RESOURCE = - R.string.external_display_use_title; static final int EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE = R.string.external_display_not_found_footer_title; static final int EXTERNAL_DISPLAY_PORTRAIT_DRAWABLE = R.drawable.external_display_mirror_portrait; - static final int EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE = - R.string.external_display_rotation; - static final int EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE = - R.string.external_display_resolution_settings_title; - static final int EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE = R.string.screen_zoom_title; static final int EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE = R.string.screen_zoom_short_summary; - static final int BUILTIN_DISPLAY_SETTINGS_CATEGORY_RESOURCE = - R.string.builtin_display_settings_category; + @VisibleForTesting static final String PREVIOUSLY_SHOWN_LIST_KEY = "mPreviouslyShownListOfDisplays"; private boolean mStarted; @@ -253,9 +289,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen ListPreference getRotationPreference(@NonNull Context context) { if (mRotationPref == null) { mRotationPref = new ListPreference(context); - mRotationPref.setPersistent(false); - mRotationPref.setKey(EXTERNAL_DISPLAY_ROTATION_KEY); - mRotationPref.setTitle(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE); + PrefBasics.EXTERNAL_DISPLAY_ROTATION.apply(mRotationPref); } return mRotationPref; } @@ -265,9 +299,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen Preference getResolutionPreference(@NonNull Context context) { if (mResolutionPreference == null) { mResolutionPreference = new Preference(context); - mResolutionPreference.setPersistent(false); - mResolutionPreference.setKey(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); - mResolutionPreference.setTitle(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE); + PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.apply(mResolutionPreference); } return mResolutionPreference; } @@ -277,9 +309,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen MainSwitchPreference getUseDisplayPreference(@NonNull Context context) { if (mUseDisplayPref == null) { mUseDisplayPref = new MainSwitchPreference(context); - mUseDisplayPref.setPersistent(false); - mUseDisplayPref.setKey(EXTERNAL_DISPLAY_USE_PREFERENCE_KEY); - mUseDisplayPref.setTitle(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE); + PrefBasics.EXTERNAL_DISPLAY_USE.apply(mUseDisplayPref); } return mUseDisplayPref; } @@ -289,8 +319,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen IllustrationPreference getIllustrationPreference(@NonNull Context context) { if (mImagePreference == null) { mImagePreference = new IllustrationPreference(context); - mImagePreference.setPersistent(false); - mImagePreference.setKey("external_display_illustration"); + PrefBasics.ILLUSTRATION.apply(mImagePreference); } return mImagePreference; } @@ -308,9 +337,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen private PreferenceCategory getDisplaysListPreference(@NonNull Context context) { if (mDisplaysPreference == null) { mDisplaysPreference = new PreferenceCategory(context); - mDisplaysPreference.setPersistent(false); - mDisplaysPreference.setOrder(40); - mDisplaysPreference.setKey(DISPLAYS_LIST_PREFERENCE_KEY); + PrefBasics.DISPLAYS_LIST.apply(mDisplaysPreference); } return mDisplaysPreference; } @@ -319,10 +346,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen private PreferenceCategory getBuiltinDisplayListPreference(@NonNull Context context) { if (mBuiltinDisplayPreference == null) { mBuiltinDisplayPreference = new PreferenceCategory(context); - mBuiltinDisplayPreference.setPersistent(false); - mBuiltinDisplayPreference.setOrder(30); - mBuiltinDisplayPreference.setKey(BUILTIN_DISPLAY_LIST_PREFERENCE_KEY); - mBuiltinDisplayPreference.setTitle(BUILTIN_DISPLAY_SETTINGS_CATEGORY_RESOURCE); + PrefBasics.BUILTIN_DISPLAY_LIST.apply(mBuiltinDisplayPreference); } return mBuiltinDisplayPreference; } @@ -338,7 +362,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen @NonNull Preference getDisplayTopologyPreference(@NonNull Context context) { if (mDisplayTopologyPreference == null) { mDisplayTopologyPreference = new DisplayTopologyPreference(context); - mDisplayTopologyPreference.setOrder(10); + PrefBasics.DISPLAY_TOPOLOGY.apply(mDisplayTopologyPreference); } return mDisplayTopologyPreference; } @@ -346,7 +370,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen @NonNull Preference getMirrorPreference(@NonNull Context context) { if (mMirrorPreference == null) { mMirrorPreference = new MirrorPreference(context); - mMirrorPreference.setOrder(20); + PrefBasics.MIRROR.apply(mMirrorPreference); } return mMirrorPreference; } @@ -386,16 +410,18 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen private void updateScreenForDisplayId(final int displayId, @NonNull final PrefRefresh screen, @NonNull Context context) { - final boolean forceShowList = displayId == INVALID_DISPLAY - && isTopologyPaneEnabled(mInjector); final var displaysToShow = externalDisplaysToShow(displayId); - if (!forceShowList && displaysToShow.isEmpty() && displayId == INVALID_DISPLAY) { + if (displaysToShow.isEmpty() && displayId == INVALID_DISPLAY) { showTextWhenNoDisplaysToShow(screen, context); - } else if (!forceShowList && displaysToShow.size() == 1 + } else if (displaysToShow.size() == 1 && ((displayId == INVALID_DISPLAY && !mPreviouslyShownListOfDisplays) || displaysToShow.get(0).getDisplayId() == displayId)) { showDisplaySettings(displaysToShow.get(0), screen, context); + if (displayId == INVALID_DISPLAY && isTopologyPaneEnabled(mInjector)) { + // Only show the topology pane if the user did not arrive via the displays list. + maybeAddV2Components(context, screen); + } } else if (displayId == INVALID_DISPLAY) { // If ever shown a list of displays - keep showing it for consistency after // disconnecting one of the displays, and only one display is left. @@ -446,21 +472,30 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen screen.addPreference(updateResolutionPreference(context, display)); screen.addPreference(updateRotationPreference(context, display, displayRotation)); if (isResolutionSettingEnabled(mInjector)) { - screen.addPreference(updateFooterPreference(context, - EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE)); + // Do not show the footer about changing resolution affecting apps. This is not in the + // UX design for v2, and there is no good place to put it, since (a) if it is on the + // bottom of the screen, the external resolution setting must be below the built-in + // display options for the per-display fragment, which is too hidden for the per-display + // fragment, or (b) the footer is above the Built-in display settings, rather than the + // bottom of the screen, which contradicts the visual style and purpose of the + // FooterPreference class, or (c) we must hide the built-in display settings, which is + // inconsistent with the topology pane, which shows that display. + // TODO(b/352648432): probably remove footer once the pane and rest of v2 UI is in + // place. + if (!isTopologyPaneEnabled(mInjector)) { + screen.addPreference(updateFooterPreference(context, + EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE)); + } } if (isDisplaySizeSettingEnabled(mInjector)) { screen.addPreference(updateSizePreference(context)); } } - private void showDisplaysList(@NonNull List displaysToShow, - @NonNull PrefRefresh screen, @NonNull Context context) { + private void maybeAddV2Components(Context context, PrefRefresh screen) { if (isTopologyPaneEnabled(mInjector)) { screen.addPreference(getDisplayTopologyPreference(context)); - if (!displaysToShow.isEmpty()) { - screen.addPreference(getMirrorPreference(context)); - } + screen.addPreference(getMirrorPreference(context)); // If topology is shown, we also show a preference for the built-in display for // consistency with the topology. @@ -468,7 +503,11 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen screen.addPreference(builtinCategory); builtinCategory.addPreference(getBuiltinDisplaySizeAndTextPreference(context)); } + } + private void showDisplaysList(@NonNull List displaysToShow, + @NonNull PrefRefresh screen, @NonNull Context context) { + maybeAddV2Components(context, screen); var displayGroupPref = getDisplaysListPreference(context); if (!displaysToShow.isEmpty()) { screen.addPreference(displayGroupPref); @@ -501,8 +540,9 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen groupCleanable.addPreference(category); var prefItem = new DisplayPreference(context, display); - prefItem.setTitle(context.getString(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE) - + " | " + context.getString(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE)); + prefItem.setTitle( + context.getString(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.titleResource) + " | " + + context.getString(PrefBasics.EXTERNAL_DISPLAY_ROTATION.titleResource)); prefItem.setKey(itemKey); category.addPreference(prefItem); @@ -577,6 +617,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen private Preference updateFooterPreference(@NonNull final Context context, final int title) { var pref = getFooterPreference(context); pref.setTitle(title); + PrefBasics.FOOTER.apply(pref); return pref; } @@ -625,10 +666,8 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen private Preference updateSizePreference(@NonNull final Context context) { var pref = (Preference) getSizePreference(context); - pref.setKey(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); + PrefBasics.EXTERNAL_DISPLAY_SIZE.apply(pref); pref.setSummary(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE); - pref.setPersistent(false); - pref.setTitle(EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE); pref.setOnPreferenceClickListener( (Preference p) -> { writePreferenceClickMetric(p); diff --git a/src/com/android/settings/connecteddevice/display/Mirroring.kt b/src/com/android/settings/connecteddevice/display/Mirroring.kt index 37ff375fa7f..453f270ba4e 100644 --- a/src/com/android/settings/connecteddevice/display/Mirroring.kt +++ b/src/com/android/settings/connecteddevice/display/Mirroring.kt @@ -23,8 +23,6 @@ import androidx.preference.SwitchPreferenceCompat import com.android.settings.R -const val MIRROR_PREFERENCE_KEY = "mirror_builtin_display" - /** * A switch preference which is backed by the MIRROR_BUILT_IN_DISPLAY global setting. */ @@ -32,7 +30,6 @@ class MirrorPreference(context: Context): SwitchPreferenceCompat(context) { init { setTitle(R.string.external_display_mirroring_title) - key = MIRROR_PREFERENCE_KEY isPersistent = false } diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java index 89f286c368a..f86f7aeefc3 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java @@ -450,8 +450,16 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { String dataNetworkTypeName = null; String voiceNetworkTypeName = null; final int subId = mSubscriptionInfo.getSubscriptionId(); - final int actualDataNetworkType = getTelephonyManager().getDataNetworkType(); - final int actualVoiceNetworkType = getTelephonyManager().getVoiceNetworkType(); + int actualDataNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + int actualVoiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + PackageManager pm = mContext.getPackageManager(); + if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)) { + actualDataNetworkType = getTelephonyManager().getDataNetworkType(); + } + if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) { + actualVoiceNetworkType = getTelephonyManager().getVoiceNetworkType(); + } + final int overrideNetworkType = mTelephonyDisplayInfo == null ? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE : mTelephonyDisplayInfo.getOverrideNetworkType(); diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt index 453593fd5c0..a8227acd84d 100644 --- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt +++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt @@ -16,12 +16,14 @@ package com.android.settings.display +import android.app.settings.SettingsEnums.ACTION_AMBIENT_DISPLAY_ALWAYS_ON import android.content.Context import android.hardware.display.AmbientDisplayConfiguration import android.os.SystemProperties import android.os.UserHandle import android.os.UserManager import android.provider.Settings.Secure.DOZE_ALWAYS_ON +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.contract.KEY_AMBIENT_DISPLAY_ALWAYS_ON @@ -41,6 +43,7 @@ import com.android.settingslib.metadata.SwitchPreference // LINT.IfChange class AmbientDisplayAlwaysOnPreference : SwitchPreference(KEY, R.string.doze_always_on_title, R.string.doze_always_on_summary), + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceRestrictionMixin { @@ -48,6 +51,11 @@ class AmbientDisplayAlwaysOnPreference : override val keywords: Int get() = R.string.keywords_always_show_time_info + override val preferenceActionMetrics: Int + get() = ACTION_AMBIENT_DISPLAY_ALWAYS_ON + + override fun tags(context: Context) = arrayOf(KEY_AMBIENT_DISPLAY_ALWAYS_ON) + override val restrictionKeys: Array get() = arrayOf(UserManager.DISALLOW_AMBIENT_DISPLAY) diff --git a/src/com/android/settings/display/BatteryPercentageSwitchPreference.kt b/src/com/android/settings/display/BatteryPercentageSwitchPreference.kt index 0cdca343ea8..2c228af57fa 100644 --- a/src/com/android/settings/display/BatteryPercentageSwitchPreference.kt +++ b/src/com/android/settings/display/BatteryPercentageSwitchPreference.kt @@ -15,30 +15,32 @@ */ package com.android.settings.display -import android.app.settings.SettingsEnums +import android.app.settings.SettingsEnums.OPEN_BATTERY_PERCENTAGE import android.content.Context import android.provider.Settings -import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R import com.android.settings.Utils -import com.android.settings.overlay.FeatureFactory.Companion.featureFactory +import com.android.settings.contract.KEY_BATTERY_PERCENTAGE import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider -import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference -import com.android.settingslib.preference.SwitchPreferenceBinding // LINT.IfChange class BatteryPercentageSwitchPreference : SwitchPreference(KEY, R.string.battery_percentage, R.string.battery_percentage_description), - SwitchPreferenceBinding, - PreferenceAvailabilityProvider, - Preference.OnPreferenceChangeListener { + PreferenceActionMetricsProvider, + PreferenceAvailabilityProvider { + + override val preferenceActionMetrics: Int + get() = OPEN_BATTERY_PERCENTAGE + + override fun tags(context: Context) = arrayOf(KEY_BATTERY_PERCENTAGE) override fun storage(context: Context): KeyValueStore = BatteryPercentageStorage(context, SettingsSystemStore.get(context)) @@ -66,22 +68,6 @@ class BatteryPercentageSwitchPreference : override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY - override fun bind(preference: Preference, metadata: PreferenceMetadata) { - super.bind(preference, metadata) - preference.onPreferenceChangeListener = this - } - - override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { - val showPercentage = newValue as Boolean - - featureFactory.metricsFeatureProvider.action( - preference.context, - SettingsEnums.OPEN_BATTERY_PERCENTAGE, - showPercentage, - ) - return true - } - @Suppress("UNCHECKED_CAST") private class BatteryPercentageStorage( private val context: Context, diff --git a/src/com/android/settings/display/BrightnessLevelPreference.kt b/src/com/android/settings/display/BrightnessLevelPreference.kt index 84f88c8abdd..8f0b791b60f 100644 --- a/src/com/android/settings/display/BrightnessLevelPreference.kt +++ b/src/com/android/settings/display/BrightnessLevelPreference.kt @@ -16,6 +16,7 @@ package com.android.settings.display import android.app.ActivityOptions +import android.app.settings.SettingsEnums.ACTION_BRIGHTNESS_LEVEL import android.content.Context import android.content.Intent import android.content.Intent.ACTION_SHOW_BRIGHTNESS_DIALOG @@ -26,9 +27,11 @@ import android.hardware.display.DisplayManager.DisplayListener import android.os.UserManager import android.provider.Settings.System import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.Utils +import com.android.settings.contract.KEY_BRIGHTNESS_LEVEL import com.android.settings.core.SettingsBaseActivity import com.android.settingslib.RestrictedPreference import com.android.settingslib.datastore.AbstractKeyedDataObservable @@ -56,6 +59,7 @@ class BrightnessLevelPreference : IntRangeValuePreference, PreferenceBinding, PreferenceRestrictionMixin, + PreferenceActionMetricsProvider, PreferenceSummaryProvider, Preference.OnPreferenceClickListener { @@ -68,6 +72,11 @@ class BrightnessLevelPreference : override val keywords: Int get() = R.string.keywords_display_brightness_level + override val preferenceActionMetrics: Int + get() = ACTION_BRIGHTNESS_LEVEL + + override fun tags(context: Context) = arrayOf(KEY_BRIGHTNESS_LEVEL) + override fun getSummary(context: Context): CharSequence? = NumberFormat.getPercentInstance().format(context.brightnessPercent) diff --git a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt index 81592cabd31..4d132ddd667 100644 --- a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt +++ b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt @@ -15,6 +15,7 @@ */ package com.android.settings.display +import android.app.settings.SettingsEnums.ACTION_SMOOTH_DISPLAY import android.content.Context import android.hardware.display.DisplayManager import android.provider.DeviceConfig @@ -23,7 +24,9 @@ import com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RAT import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay import com.android.server.display.feature.flags.Flags +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_SMOOTH_DISPLAY import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate @@ -41,12 +44,18 @@ import kotlin.math.roundToInt // LINT.IfChange class PeakRefreshRateSwitchPreference : SwitchPreference(KEY, R.string.peak_refresh_rate_title), + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceLifecycleProvider { private var propertiesChangedListener: DeviceConfig.OnPropertiesChangedListener? = null + override val preferenceActionMetrics: Int + get() = ACTION_SMOOTH_DISPLAY + + override fun tags(context: Context) = arrayOf(KEY_SMOOTH_DISPLAY) + override fun storage(context: Context): KeyValueStore = PeakRefreshRateStore(context, SettingsSystemStore.get(context)) diff --git a/src/com/android/settings/display/darkmode/DarkModeScreen.kt b/src/com/android/settings/display/darkmode/DarkModeScreen.kt index 527cd192b79..86ead6b3fd8 100644 --- a/src/com/android/settings/display/darkmode/DarkModeScreen.kt +++ b/src/com/android/settings/display/darkmode/DarkModeScreen.kt @@ -17,11 +17,14 @@ package com.android.settings.display.darkmode import android.Manifest +import android.app.settings.SettingsEnums.ACTION_DARK_THEME import android.content.Context import android.os.PowerManager import androidx.preference.Preference import androidx.preference.PreferenceScreen +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_DARK_THEME import com.android.settings.flags.Flags import com.android.settingslib.PrimarySwitchPreferenceBinding import com.android.settingslib.datastore.KeyValueStore @@ -42,6 +45,7 @@ class DarkModeScreen(context: Context) : PreferenceScreenCreator, PreferenceScreenBinding, // binding for screen page PrimarySwitchPreferenceBinding, // binding for screen entry point widget + PreferenceActionMetricsProvider, BooleanValuePreference, PreferenceSummaryProvider { @@ -56,6 +60,11 @@ class DarkModeScreen(context: Context) : override val keywords: Int get() = R.string.keywords_dark_ui_mode + override val preferenceActionMetrics: Int + get() = ACTION_DARK_THEME + + override fun tags(context: Context) = arrayOf(KEY_DARK_THEME) + override fun getReadPermissions(context: Context) = Permissions.EMPTY override fun getWritePermissions(context: Context) = diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt index 268dea2778a..0eebaa2343a 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt @@ -16,10 +16,13 @@ package com.android.settings.fuelgauge +import android.app.settings.SettingsEnums.ACTION_BATTERY_LEVEL import android.content.Context import androidx.annotation.VisibleForTesting import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_BATTERY_LEVEL import com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT import com.android.settingslib.Utils import com.android.settingslib.datastore.KeyValueStore @@ -37,7 +40,10 @@ import com.android.settingslib.widget.UsageProgressBarPreference // LINT.IfChange class BatteryHeaderPreference : - IntRangeValuePreference, PreferenceBinding, PreferenceLifecycleProvider { + IntRangeValuePreference, + PreferenceBinding, + PreferenceActionMetricsProvider, + PreferenceLifecycleProvider { @VisibleForTesting var batteryBroadcastReceiver: BatteryBroadcastReceiver? = null @@ -47,6 +53,11 @@ class BatteryHeaderPreference : override val title: Int get() = R.string.summary_placeholder + override val preferenceActionMetrics: Int + get() = ACTION_BATTERY_LEVEL + + override fun tags(context: Context) = arrayOf(KEY_BATTERY_LEVEL) + override fun createWidget(context: Context) = UsageProgressBarPreference(context) override fun bind(preference: Preference, metadata: PreferenceMetadata) { diff --git a/src/com/android/settings/network/AdaptiveConnectivityTogglePreference.kt b/src/com/android/settings/network/AdaptiveConnectivityTogglePreference.kt index c9ba7141b49..51e0ddd61db 100644 --- a/src/com/android/settings/network/AdaptiveConnectivityTogglePreference.kt +++ b/src/com/android/settings/network/AdaptiveConnectivityTogglePreference.kt @@ -16,10 +16,13 @@ package com.android.settings.network +import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY import android.content.Context import android.net.wifi.WifiManager import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.R +import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsSecureStore @@ -31,7 +34,13 @@ import com.android.settingslib.metadata.SensitivityLevel // LINT.IfChange class AdaptiveConnectivityTogglePreference : - MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title) { + MainSwitchPreference(KEY, R.string.adaptive_connectivity_main_switch_title), + PreferenceActionMetricsProvider { + + override val preferenceActionMetrics: Int + get() = ACTION_ADAPTIVE_CONNECTIVITY + + override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) override fun storage(context: Context): KeyValueStore = AdaptiveConnectivityToggleStorage(context, SettingsSecureStore.get(context)) diff --git a/src/com/android/settings/network/CellularSecurityPreferenceController.java b/src/com/android/settings/network/CellularSecurityPreferenceController.java index 6ab32e31729..9ad2eac4ac0 100644 --- a/src/com/android/settings/network/CellularSecurityPreferenceController.java +++ b/src/com/android/settings/network/CellularSecurityPreferenceController.java @@ -35,7 +35,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.internal.telephony.flags.Flags; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.telephony.CellularSecuritySettingsFragment; @@ -71,8 +70,7 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll @Override public int getAvailabilityStatus() { - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY) - || !Flags.enableModemCipherTransparencyUnsolEvents()) { + if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { return UNSUPPORTED_ON_DEVICE; } if (mTelephonyManager == null) { diff --git a/src/com/android/settings/network/ims/ImsQueryEnhanced4gLteModeUserSetting.java b/src/com/android/settings/network/ims/ImsQueryEnhanced4gLteModeUserSetting.java index c6c5ad3e924..a3e0f69c7a6 100644 --- a/src/com/android/settings/network/ims/ImsQueryEnhanced4gLteModeUserSetting.java +++ b/src/com/android/settings/network/ims/ImsQueryEnhanced4gLteModeUserSetting.java @@ -47,6 +47,8 @@ public class ImsQueryEnhanced4gLteModeUserSetting implements ImsQuery { return imsMmTelManager.isAdvancedCallingSettingEnabled(); } catch (IllegalArgumentException exception) { Log.w(LOG_TAG, "fail to get VoLte settings. subId=" + mSubId, exception); + } catch (UnsupportedOperationException ex) { + // expected on devices without IMS } return false; } diff --git a/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java b/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java index 8d498e2619c..4d1ee878239 100644 --- a/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java +++ b/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java @@ -26,7 +26,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.android.internal.telephony.flags.Flags; import com.android.settings.core.BasePreferenceController; import com.android.settings.network.SubscriptionUtil; @@ -60,9 +59,6 @@ public class CellularSecurityNotificationsDividerController extends @Override public int getAvailabilityStatus() { - if (!Flags.enableModemCipherTransparencyUnsolEvents()) { - return UNSUPPORTED_ON_DEVICE; - } if (!isSafetyCenterSupported()) { return UNSUPPORTED_ON_DEVICE; } diff --git a/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java b/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java index 6b18f3c4b18..347f95b50f3 100644 --- a/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java +++ b/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java @@ -26,7 +26,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.android.internal.telephony.flags.Flags; import com.android.settings.network.SubscriptionUtil; import java.util.List; @@ -75,10 +74,6 @@ public class CellularSecurityNotificationsPreferenceController extends return UNSUPPORTED_ON_DEVICE; } - if (!areFlagsEnabled()) { - return UNSUPPORTED_ON_DEVICE; - } - // Check there are valid SIM cards which can be displayed to the user, otherwise this // setting should not be shown. List availableSubs = SubscriptionUtil.getAvailableSubscriptions(mContext); @@ -106,10 +101,6 @@ public class CellularSecurityNotificationsPreferenceController extends */ @Override public boolean isChecked() { - if (!areFlagsEnabled()) { - return false; - } - try { // Note: the default behavior for this toggle is disabled (as the underlying // TelephonyManager APIs are disabled by default) @@ -144,11 +135,6 @@ public class CellularSecurityNotificationsPreferenceController extends Log.i(LOG_TAG, "Disabling cellular security notifications."); } - // Check flag status - if (!areFlagsEnabled()) { - return false; - } - try { setNotifications(isChecked); } catch (Exception e) { @@ -177,13 +163,6 @@ public class CellularSecurityNotificationsPreferenceController extends && mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled(); } - private boolean areFlagsEnabled() { - if (!Flags.enableModemCipherTransparencyUnsolEvents()) { - return false; - } - return true; - } - protected boolean isSafetyCenterSupported() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { return false; diff --git a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java index d1988c4a3b7..3886c3beeab 100644 --- a/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java +++ b/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceController.java @@ -112,8 +112,12 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc return CONDITIONALLY_UNAVAILABLE; } - if (!queryState.isReadyToVoLte()) { - return CONDITIONALLY_UNAVAILABLE; + try { + if (!queryState.isReadyToVoLte()) { + return CONDITIONALLY_UNAVAILABLE; + } + } catch (UnsupportedOperationException ex) { + return UNSUPPORTED_ON_DEVICE; } return (isUserControlAllowed(carrierConfig) && queryState.isAllowUserControl()) ? AVAILABLE : AVAILABLE_UNSEARCHABLE; diff --git a/src/com/android/settings/notification/CallVolumePreference.kt b/src/com/android/settings/notification/CallVolumePreference.kt index f3ee3ca7022..a0d7561f7f3 100644 --- a/src/com/android/settings/notification/CallVolumePreference.kt +++ b/src/com/android/settings/notification/CallVolumePreference.kt @@ -19,6 +19,7 @@ package com.android.settings.notification import android.Manifest.permission.MODIFY_AUDIO_SETTINGS import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED import android.Manifest.permission.MODIFY_PHONE_STATE +import android.app.settings.SettingsEnums.ACTION_CALL_VOLUME import android.content.Context import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE import android.media.AudioManager @@ -26,8 +27,10 @@ import android.media.AudioManager.STREAM_BLUETOOTH_SCO import android.media.AudioManager.STREAM_VOICE_CALL import android.os.UserManager import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R +import com.android.settings.contract.KEY_CALL_VOLUME import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions @@ -44,6 +47,7 @@ import com.android.settingslib.preference.PreferenceBinding open class CallVolumePreference : IntRangeValuePreference, PreferenceBinding, + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceRestrictionMixin { @@ -53,6 +57,11 @@ open class CallVolumePreference : override val title: Int get() = R.string.call_volume_option_title + override val preferenceActionMetrics: Int + get() = ACTION_CALL_VOLUME + + override fun tags(context: Context) = arrayOf(KEY_CALL_VOLUME) + override fun getIcon(context: Context) = R.drawable.ic_local_phone_24_lib override fun isAvailable(context: Context) = diff --git a/src/com/android/settings/notification/MediaVolumePreference.kt b/src/com/android/settings/notification/MediaVolumePreference.kt index b2a2fbe7bc7..8af2353dfdc 100644 --- a/src/com/android/settings/notification/MediaVolumePreference.kt +++ b/src/com/android/settings/notification/MediaVolumePreference.kt @@ -18,13 +18,16 @@ package com.android.settings.notification import android.Manifest.permission.MODIFY_AUDIO_SETTINGS import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED +import android.app.settings.SettingsEnums.ACTION_MEDIA_VOLUME import android.content.Context import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE import android.media.AudioManager.STREAM_MUSIC import android.os.UserManager import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R +import com.android.settings.contract.KEY_MEDIA_VOLUME import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions @@ -41,6 +44,7 @@ import com.android.settingslib.preference.PreferenceBinding open class MediaVolumePreference : IntRangeValuePreference, PreferenceBinding, + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceRestrictionMixin { @@ -50,6 +54,11 @@ open class MediaVolumePreference : override val title: Int get() = R.string.media_volume_option_title + override val preferenceActionMetrics: Int + get() = ACTION_MEDIA_VOLUME + + override fun tags(context: Context) = arrayOf(KEY_MEDIA_VOLUME) + override fun getIcon(context: Context) = when { VolumeHelper.isMuted(context, STREAM_MUSIC) -> R.drawable.ic_media_stream_off diff --git a/src/com/android/settings/notification/SeparateRingVolumePreference.kt b/src/com/android/settings/notification/SeparateRingVolumePreference.kt index 16e6e5950c9..fba3eb404a7 100644 --- a/src/com/android/settings/notification/SeparateRingVolumePreference.kt +++ b/src/com/android/settings/notification/SeparateRingVolumePreference.kt @@ -21,6 +21,7 @@ import android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED import android.app.INotificationManager import android.app.NotificationManager import android.app.NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED +import android.app.settings.SettingsEnums.ACTION_RING_VOLUME import android.content.BroadcastReceiver import android.content.Context import android.content.Context.NOTIFICATION_SERVICE @@ -39,8 +40,10 @@ import android.os.Vibrator import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS import androidx.preference.Preference +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R +import com.android.settings.contract.KEY_RING_VOLUME import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions @@ -59,6 +62,7 @@ import com.android.settingslib.preference.PreferenceBinding open class SeparateRingVolumePreference : IntRangeValuePreference, PreferenceBinding, + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceLifecycleProvider, @@ -72,6 +76,11 @@ open class SeparateRingVolumePreference : override val title: Int get() = R.string.separate_ring_volume_option_title + override val preferenceActionMetrics: Int + get() = ACTION_RING_VOLUME + + override fun tags(context: Context) = arrayOf(KEY_RING_VOLUME) + override fun getIcon(context: Context) = context.getIconRes() override fun isAvailable(context: Context) = !createAudioHelper(context).isSingleVolume diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt index 21b0e88d7ac..fbe431718ec 100644 --- a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt +++ b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt @@ -17,7 +17,8 @@ package com.android.settings.wifi.tether import android.Manifest -import android.app.settings.SettingsEnums +import android.app.settings.SettingsEnums.ACTION_WIFI_HOTSPOT +import android.app.settings.SettingsEnums.WIFI_TETHER_SETTINGS import android.content.Context import android.content.Intent import android.net.TetheringManager @@ -27,9 +28,11 @@ import android.net.wifi.WifiManager import android.os.UserManager import android.text.BidiFormatter import android.util.Log +import com.android.settings.PreferenceActionMetricsProvider import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.Utils +import com.android.settings.contract.KEY_WIFI_HOTSPOT import com.android.settings.core.SubSettingLauncher import com.android.settings.datausage.DataSaverMainSwitchPreference.Companion.KEY as DATA_SAVER_KEY import com.android.settings.wifi.WifiUtils.canShowWifiHotspot @@ -56,10 +59,16 @@ import com.android.settingslib.wifi.WifiUtils.Companion.getWifiTetherSummaryForC class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStore) : SwitchPreference(KEY, R.string.wifi_hotspot_checkbox_text), PrimarySwitchPreferenceBinding, + PreferenceActionMetricsProvider, PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceRestrictionMixin { + override val preferenceActionMetrics: Int + get() = ACTION_WIFI_HOTSPOT + + override fun tags(context: Context) = arrayOf(KEY_WIFI_HOTSPOT) + private val wifiHotspotStore = WifiHotspotStore(context, dataSaverStore) override fun isAvailable(context: Context) = @@ -97,7 +106,7 @@ class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStor .apply { setDestination(WifiTetherSettings::class.java.name) setTitleRes(R.string.wifi_hotspot_checkbox_text) - setSourceMetricsCategory(SettingsEnums.WIFI_TETHER_SETTINGS) + setSourceMetricsCategory(WIFI_TETHER_SETTINGS) } .toIntent() diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java index bd6ac4bf2c0..38a607a76a1 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java @@ -18,6 +18,7 @@ package com.android.settings.bluetooth; import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE; import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_PAIR_AND_JOIN_SHARING; +import static com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS; import static com.google.common.truth.Truth.assertThat; @@ -36,6 +37,7 @@ import static org.robolectric.Shadows.shadowOf; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.content.Context; @@ -44,6 +46,8 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Looper; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Pair; @@ -62,9 +66,15 @@ import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.flags.Flags; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -112,6 +122,14 @@ public class BluetoothDevicePairingDetailBaseTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private LocalBluetoothManager mLocalManager; @Mock + private CachedBluetoothDeviceManager mDeviceManager; + @Mock + private LocalBluetoothProfileManager mProfileManager; + @Mock + private LocalBluetoothLeBroadcast mBroadcast; + @Mock + private LocalBluetoothLeBroadcastAssistant mAssistant; + @Mock private CachedBluetoothDevice mCachedBluetoothDevice; @Mock private Drawable mDrawable; @@ -197,11 +215,13 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onDeviceBondStateChanged_bonded_pairAndJoinSharingDisabled_finish() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void onDeviceBondStateChanged_bonded_notPairInSharing_finish() { when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(false); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED); verify(mFragment).finish(); @@ -209,12 +229,14 @@ public class BluetoothDevicePairingDetailBaseTest { @Test @Config(shadows = ShadowDialogFragment.class) - public void onDeviceBondStateChanged_bonded_pairAndJoinSharingEnabled_handle() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void onDeviceBondStateChanged_bonded_shareThenPair_handle() { ShadowDialogFragment.reset(); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(true); + setUpFragmentWithShareThenPairIntent(true); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED); shadowOf(Looper.getMainLooper()).idle(); @@ -231,11 +253,37 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onDeviceBondStateChanged_bonding_pairAndJoinSharingDisabled_doNothing() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @Config(shadows = ShadowDialogFragment.class) + @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void onDeviceBondStateChanged_bonded_pairAfterShare_handle() { + ShadowDialogFragment.reset(); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(false); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true); + mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED); + shadowOf(Looper.getMainLooper()).idle(); + + ProgressDialogFragment progressDialog = mFragment.mProgressDialog; + assertThat(progressDialog).isNotNull(); + assertThat(progressDialog.getMessage()).isEqualTo( + mContext.getString(R.string.progress_dialog_connect_device_content, + TEST_DEVICE_ADDRESS)); + assertThat( + ShadowDialogFragment.isIsShowing(ProgressDialogFragment.class.getName())).isTrue(); + verify(mFragment, never()).finish(); + + ShadowDialogFragment.reset(); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void onDeviceBondStateChanged_bonding_notPairInSharing_doNothing() { + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + mFragment.mSelectedList.add(mBluetoothDevice); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING); verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(any(BluetoothDevice.class), @@ -243,11 +291,13 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onDeviceBondStateChanged_bonding_pairAndJoinSharingEnabled_addListener() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void onDeviceBondStateChanged_bonding_shareThenPair_addListener() { when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(true); + setUpFragmentWithShareThenPairIntent(true); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING); verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice), @@ -256,8 +306,22 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onDeviceBondStateChanged_unbonded_pairAndJoinSharingDisabled_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void onDeviceBondStateChanged_bonding_pairAfterShare_addListener() { + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + mFragment.mSelectedList.add(mBluetoothDevice); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true); + mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING); + + verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice), + any(Executor.class), + any(BluetoothAdapter.OnMetadataChangedListener.class)); + } + + @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void onDeviceBondStateChanged_unbonded_notPairInSharing_doNothing() { when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE); @@ -267,11 +331,13 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onDeviceBondStateChanged_unbonded_pairAndJoinSharingEnabled_removeListener() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) + @DisableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void onDeviceBondStateChanged_unbonded_shareThenPair_removeListener() { when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(true); + setUpFragmentWithShareThenPairIntent(true); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE); @@ -280,8 +346,23 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test - public void onProfileConnectionStateChanged_deviceInSelectedListAndConnected_finish() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void onDeviceBondStateChanged_unbonded_pairAfterShare_removeListener() { + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + mFragment.mSelectedList.add(mBluetoothDevice); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true); + mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING); + mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE); + + verify(mBluetoothAdapter).removeOnMetadataChangedListener(eq(mBluetoothDevice), + any(BluetoothAdapter.OnMetadataChangedListener.class)); + } + + @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void + onProfileConnectionStateChanged_deviceInSelectedListAndConnected_notInSharing_finish() { final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); mFragment.mSelectedList.add(mBluetoothDevice); mFragment.mSelectedList.add(device); @@ -291,19 +372,22 @@ public class BluetoothDevicePairingDetailBaseTest { mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.A2DP); + shadowOf(Looper.getMainLooper()).idle(); verify(mFragment).finish(); } @Test @Config(shadows = ShadowDialogFragment.class) + @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) public void - onProfileConnectionStateChanged_deviceInSelectedListAndConnected_pairAndJoinSharing() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); + onProfileConnectionStateChanged_inSelectedListAndConnected_shareThenPair_handle() { ShadowDialogFragment.reset(); - when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); - mFragment.mSelectedList.add(mBluetoothDevice); - setUpFragmentWithPairAndJoinSharingIntent(true); + BluetoothDevice device = spy(mBluetoothDevice); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + mFragment.mSelectedList.add(device); + setUpFragmentWithShareThenPairIntent(true); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false); mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED); shadowOf(Looper.getMainLooper()).idle(); @@ -316,6 +400,7 @@ public class BluetoothDevicePairingDetailBaseTest { BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); shadowOf(Looper.getMainLooper()).idle(); + verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any()); ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); verify(mFragment.getActivity()).setResult(eq(Activity.RESULT_OK), captor.capture()); Intent intent = captor.getValue(); @@ -325,15 +410,44 @@ public class BluetoothDevicePairingDetailBaseTest { BluetoothDevice.class) : null; assertThat(btDevice).isNotNull(); - assertThat(btDevice).isEqualTo(mBluetoothDevice); + assertThat(btDevice).isEqualTo(device); verify(mFragment).finish(); ShadowDialogFragment.reset(); } @Test + @Config(shadows = ShadowDialogFragment.class) + @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void + onProfileConnectionStateChanged_inSelectedListAndConnected_pairAfterShare_handle() { + ShadowDialogFragment.reset(); + BluetoothDevice device = spy(mBluetoothDevice); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + mFragment.mSelectedList.add(device); + setUpFragmentWithShareThenPairIntent(false); + setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true); + mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED); + shadowOf(Looper.getMainLooper()).idle(); + + when(mCachedBluetoothDevice.isConnected()).thenReturn(true); + when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true); + when(mCachedBluetoothDevice.isConnectedLeAudioBroadcastAssistantDevice()).thenReturn(true); + when(mCachedBluetoothDevice.isConnectedVolumeControlDevice()).thenReturn(true); + + mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + shadowOf(Looper.getMainLooper()).idle(); + + verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any()); + verify(mFragment).finish(); + + ShadowDialogFragment.reset(); + } + + @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) public void onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); mFragment.mSelectedList.add(device); @@ -347,8 +461,8 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) public void onProfileConnectionStateChanged_deviceDisconnected_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); mFragment.mSelectedList.add(mBluetoothDevice); mFragment.mSelectedList.add(device); @@ -363,8 +477,8 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) public void onProfileConnectionStateChanged_deviceInPreferenceMapAndConnected_removed() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); final BluetoothDevicePreference preference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, true, BluetoothDevicePreference.SortType.TYPE_FIFO); @@ -381,8 +495,8 @@ public class BluetoothDevicePairingDetailBaseTest { } @Test + @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) public void onProfileConnectionStateChanged_deviceNotInPreferenceMap_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); final BluetoothDevicePreference preference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, @@ -404,9 +518,9 @@ public class BluetoothDevicePairingDetailBaseTest { // not crash } - private void setUpFragmentWithPairAndJoinSharingIntent(boolean enablePairAndJoinSharing) { + private void setUpFragmentWithShareThenPairIntent(boolean enableShareThenPair) { Bundle args = new Bundle(); - args.putBoolean(EXTRA_PAIR_AND_JOIN_SHARING, enablePairAndJoinSharing); + args.putBoolean(EXTRA_PAIR_AND_JOIN_SHARING, enableShareThenPair); Intent intent = new Intent(); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, args); FragmentActivity activity = spy(Robolectric.setupActivity(FragmentActivity.class)); @@ -420,8 +534,39 @@ public class BluetoothDevicePairingDetailBaseTest { Lifecycle lifecycle = mock(Lifecycle.class); when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED); doReturn(lifecycle).when(mFragment).getLifecycle(); - mFragment.mShouldTriggerAudioSharingShareThenPairFlow = - mFragment.shouldTriggerAudioSharingShareThenPairFlow(); + mFragment.mShouldTriggerShareThenPairFlow = mFragment.shouldTriggerShareThenPairFlow(); + } + + private void setUpAudioSharingStates(boolean enabled, boolean needSetTempBondMetadata) { + when(mLocalManager.getProfileManager()).thenReturn(mProfileManager); + when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); + when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); + when(mLocalManager.getCachedDeviceManager()).thenReturn(mDeviceManager); + if (!enabled) { + when(mBroadcast.isEnabled(null)).thenReturn(false); + } else { + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBroadcastId()).thenReturn(1); + BluetoothDevice device1 = mock(BluetoothDevice.class); + CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class); + when(mDeviceManager.findDevice(device1)).thenReturn(cachedDevice1); + when(cachedDevice1.getGroupId()).thenReturn(1); + when(cachedDevice1.getDevice()).thenReturn(device1); + BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); + when(state.getBroadcastId()).thenReturn(1); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state)); + if (needSetTempBondMetadata) { + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1)); + } else { + BluetoothDevice device2 = mock(BluetoothDevice.class); + CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class); + when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2); + when(cachedDevice2.getGroupId()).thenReturn(2); + when(cachedDevice2.getDevice()).thenReturn(device2); + when(mAssistant.getAllConnectedDevices()).thenReturn( + ImmutableList.of(device1, device2)); + } + } } private static class TestBluetoothDevicePairingDetailBase extends diff --git a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java index 25808b58a0a..4fafcda0c15 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java @@ -15,6 +15,9 @@ */ package com.android.settings.bluetooth; +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -22,34 +25,72 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.content.Context; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowBluetoothUtils; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.google.common.collect.ImmutableList; + +import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowBluetoothUtils.class}) public class UtilsTest { - + private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25; + private static final String TEMP_BOND_METADATA = + "le_audio_sharing"; + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; + @Mock + private LocalBluetoothManager mLocalBtManager; + @Mock + private LocalBluetoothProfileManager mProfileManager; + @Mock + private LocalBluetoothLeBroadcast mBroadcast; + @Mock + private LocalBluetoothLeBroadcastAssistant mAssistant; + @Mock + private CachedBluetoothDeviceManager mDeviceManager; private MetricsFeatureProvider mMetricsFeatureProvider; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mMetricsFeatureProvider = FakeFeatureFactory.setupForTest().getMetricsFeatureProvider(); + ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; + mLocalBtManager = Utils.getLocalBtManager(mContext); + when(mLocalBtManager.getProfileManager()).thenReturn(mProfileManager); + when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mDeviceManager); + when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); + when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); + } + + @After + public void tearDown() { + ShadowBluetoothUtils.reset(); } @Test @@ -60,4 +101,65 @@ public class UtilsTest { verify(mMetricsFeatureProvider).visible(eq(mContext), anyInt(), eq(MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR), anyInt()); } + + @Test + public void shouldBlockPairingInAudioSharing_broadcastOff_returnFalse() { + when(mBroadcast.isEnabled(null)).thenReturn(false); + assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isFalse(); + } + + @Test + public void shouldBlockPairingInAudioSharing_singlePermanentBondSinkInSharing_returnFalse() { + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBroadcastId()).thenReturn(1); + BluetoothDevice device = mock(BluetoothDevice.class); + CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); + when(mDeviceManager.findDevice(device)).thenReturn(cachedDevice); + when(cachedDevice.getGroupId()).thenReturn(1); + when(cachedDevice.getDevice()).thenReturn(device); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device)); + BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); + when(state.getBroadcastId()).thenReturn(1); + when(mAssistant.getAllSources(device)).thenReturn(ImmutableList.of(state)); + assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isFalse(); + } + + @Test + public void shouldBlockPairingInAudioSharing_singleTempBondSinkInSharing_returnTrue() { + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBroadcastId()).thenReturn(1); + BluetoothDevice device = mock(BluetoothDevice.class); + CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); + when(mDeviceManager.findDevice(device)).thenReturn(cachedDevice); + when(cachedDevice.getGroupId()).thenReturn(1); + when(cachedDevice.getDevice()).thenReturn(device); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device)); + BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); + when(state.getBroadcastId()).thenReturn(1); + when(mAssistant.getAllSources(device)).thenReturn(ImmutableList.of(state)); + when(device.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) + .thenReturn(TEMP_BOND_METADATA.getBytes()); + assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue(); + } + + @Test + public void shouldBlockPairingInAudioSharing_twoSinksInSharing_returnTrue() { + when(mBroadcast.isEnabled(null)).thenReturn(true); + when(mBroadcast.getLatestBroadcastId()).thenReturn(1); + BluetoothDevice device1 = mock(BluetoothDevice.class); + BluetoothDevice device2 = mock(BluetoothDevice.class); + CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class); + CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class); + when(mDeviceManager.findDevice(device1)).thenReturn(cachedDevice1); + when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2); + when(cachedDevice1.getGroupId()).thenReturn(1); + when(cachedDevice2.getGroupId()).thenReturn(2); + when(cachedDevice1.getDevice()).thenReturn(device1); + when(cachedDevice2.getDevice()).thenReturn(device2); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1, device2)); + BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class); + when(state.getBroadcastId()).thenReturn(1); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state)); + assertThat(Utils.shouldBlockPairingInAudioSharing(mLocalBtManager)).isTrue(); + } } diff --git a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragmentTest.java b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragmentTest.java index d22dbaeed00..12af7726a42 100644 --- a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragmentTest.java +++ b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragmentTest.java @@ -17,19 +17,10 @@ package com.android.settings.connecteddevice.display; import static android.view.Display.INVALID_DISPLAY; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DISPLAYS_LIST_PREFERENCE_KEY; import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE; import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_KEY; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE; import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SETTINGS_RESOURCE; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY; import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_PREFERENCE_KEY; -import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_USE_TITLE_RESOURCE; import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PREVIOUSLY_SHOWN_LIST_KEY; import static com.android.settings.flags.Flags.FLAG_DISPLAY_SIZE_CONNECTED_DISPLAY_SETTING; import static com.android.settings.flags.Flags.FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST; @@ -61,6 +52,7 @@ import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.DisplayPreference; +import com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PrefBasics; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.MainSwitchPreference; @@ -97,23 +89,22 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa fragment.onSaveInstanceStateCallback(outState); assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isFalse(); assertThat(mHandler.getPendingMessages().size()).isEqualTo(1); - PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(pref).isNull(); verify(mMockedInjector, never()).getAllDisplays(); mHandler.flush(); assertThat(mHandler.getPendingMessages().size()).isEqualTo(0); verify(mMockedInjector).getAllDisplays(); - pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(pref).isNotNull(); assertThat(pref.getPreferenceCount()).isEqualTo(2); fragment.onSaveInstanceStateCallback(outState); assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isTrue(); - pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key); assertThat(pref).isNull(); - pref = mPreferenceScreen.findPreference( - ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key); assertThat(pref).isNull(); } @@ -126,56 +117,51 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays(); mHandler.flush(); - var pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY); + var pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key); assertThat(pref).isNotNull(); - pref = mPreferenceScreen.findPreference(MirroringKt.MIRROR_PREFERENCE_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key); assertThat(pref).isNotNull(); - PreferenceCategory listPref = - mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); - assertThat(listPref).isNotNull(); - assertThat(listPref.getPreferenceCount()).isEqualTo(1); - - listPref = mPreferenceScreen.findPreference( - ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY); - assertThat(listPref).isNotNull(); - assertThat(listPref.getPreferenceCount()).isEqualTo(1); - } - - @Test - @UiThreadTest - public void testShowDisplayListWithPane_NoExternalDisplays() { - mFlags.setFlag(FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST, true); - - initFragment(); - doReturn(new Display[0]).when(mMockedInjector).getAllDisplays(); - mHandler.flush(); - - var pref = mPreferenceScreen.findPreference(DisplayTopologyKt.TOPOLOGY_PREFERENCE_KEY); - assertThat(pref).isNotNull(); - pref = mPreferenceScreen.findPreference(MirroringKt.MIRROR_PREFERENCE_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(pref).isNull(); PreferenceCategory listPref = - mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); - assertThat(listPref).isNull(); - - listPref = mPreferenceScreen.findPreference( - ExternalDisplayPreferenceFragment.BUILTIN_DISPLAY_LIST_PREFERENCE_KEY); - assertThat(listPref).isNotNull(); - assertThat(listPref.getPreferenceCount()).isEqualTo(1); + mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key); var builtinPref = listPref.getPreference(0); assertThat(builtinPref.getOnPreferenceClickListener().onPreferenceClick(builtinPref)) .isTrue(); assertThat(mLaunchedBuiltinSettings).isTrue(); } + @Test + @UiThreadTest + public void testDontShowDisplayListOrPane_NoExternalDisplays() { + mFlags.setFlag(FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST, true); + + initFragment(); + doReturn(new Display[0]).when(mMockedInjector).getAllDisplays(); + mHandler.flush(); + + // When no external display is attached, interactive preferences are omitted. + var pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key); + assertThat(pref).isNull(); + pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key); + assertThat(pref).isNull(); + + PreferenceCategory listPref = + mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); + assertThat(listPref).isNull(); + + listPref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key); + assertThat(listPref).isNull(); + } + @Test @UiThreadTest public void testLaunchDisplaySettingFromList() { initFragment(); mHandler.flush(); - PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(pref).isNotNull(); var display1Category = (PreferenceCategory) pref.getPreference(0); var display1Pref = (DisplayPreference) display1Category.getPreference(0); @@ -204,7 +190,7 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa // Only one display available doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays(); mHandler.flush(); - PreferenceCategory pref = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(pref).isNotNull(); assertThat(pref.getPreferenceCount()).isEqualTo(1); } @@ -219,15 +205,15 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa // Init initFragment(); mHandler.flush(); - PreferenceCategory list = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(list).isNull(); - var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); + var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key); assertThat(pref).isNotNull(); - pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key); assertThat(pref).isNotNull(); var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER); assertThat(footerPref).isNotNull(); - var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); + var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key); assertThat(sizePref).isNull(); verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE); } @@ -241,15 +227,15 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa // Init initFragment(); mHandler.flush(); - PreferenceCategory list = mPreferenceScreen.findPreference(DISPLAYS_LIST_PREFERENCE_KEY); + PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key); assertThat(list).isNull(); - var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); + var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key); assertThat(pref).isNotNull(); - pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key); assertThat(pref).isNotNull(); var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER); assertThat(footerPref).isNotNull(); - var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); + var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key); assertThat(sizePref).isNotNull(); verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE); } @@ -263,13 +249,13 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa verify(mMockedInjector, never()).getDisplay(anyInt()); mHandler.flush(); verify(mMockedInjector).getDisplay(mDisplayIdArg); - var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); + var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key); assertThat(pref).isNotNull(); - pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key); assertThat(pref).isNotNull(); var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER); assertThat(footerPref).isNotNull(); - var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); + var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key); assertThat(sizePref).isNotNull(); verify(footerPref).setTitle(EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE); } @@ -283,20 +269,20 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa mHandler.flush(); verify(mMockedInjector).getDisplay(mDisplayIdArg); var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference( - EXTERNAL_DISPLAY_USE_PREFERENCE_KEY); + PrefBasics.EXTERNAL_DISPLAY_USE.key); assertThat(mainPref).isNotNull(); assertThat("" + mainPref.getTitle()).isEqualTo( - getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE)); + getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource)); assertThat(mainPref.isChecked()).isFalse(); assertThat(mainPref.isEnabled()).isTrue(); assertThat(mainPref.getOnPreferenceChangeListener()).isNotNull(); - var pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); + var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key); assertThat(pref).isNull(); - pref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_ROTATION_KEY); + pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key); assertThat(pref).isNull(); var footerPref = (FooterPreference) mPreferenceScreen.findPreference(KEY_FOOTER); assertThat(footerPref).isNull(); - var sizePref = mPreferenceScreen.findPreference(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); + var sizePref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key); assertThat(sizePref).isNull(); } @@ -307,10 +293,10 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa initFragment(); mHandler.flush(); var mainPref = (MainSwitchPreference) mPreferenceScreen.findPreference( - EXTERNAL_DISPLAY_USE_PREFERENCE_KEY); + PrefBasics.EXTERNAL_DISPLAY_USE.key); assertThat(mainPref).isNotNull(); assertThat("" + mainPref.getTitle()).isEqualTo( - getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE)); + getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource)); assertThat(mainPref.isChecked()).isFalse(); assertThat(mainPref.isEnabled()).isFalse(); assertThat(mainPref.getOnPreferenceChangeListener()).isNull(); @@ -327,9 +313,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa var fragment = initFragment(); mHandler.flush(); var pref = fragment.getRotationPreference(mContext); - assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_ROTATION_KEY); + assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key); assertThat("" + pref.getTitle()).isEqualTo( - getText(EXTERNAL_DISPLAY_ROTATION_TITLE_RESOURCE)); + getText(PrefBasics.EXTERNAL_DISPLAY_ROTATION.titleResource)); assertThat(pref.getEntries().length).isEqualTo(4); assertThat(pref.getEntryValues().length).isEqualTo(4); assertThat(pref.getEntryValues()[0].toString()).isEqualTo("0"); @@ -359,9 +345,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa var fragment = initFragment(); mHandler.flush(); var pref = fragment.getResolutionPreference(mContext); - assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_RESOLUTION_PREFERENCE_KEY); + assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key); assertThat("" + pref.getTitle()).isEqualTo( - getText(EXTERNAL_DISPLAY_RESOLUTION_TITLE_RESOURCE)); + getText(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.titleResource)); assertThat("" + pref.getSummary()).isEqualTo("1920 x 1080"); assertThat(pref.isEnabled()).isTrue(); assertThat(pref.getOnPreferenceClickListener()).isNotNull(); @@ -378,8 +364,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa var fragment = initFragment(); mHandler.flush(); var pref = fragment.getSizePreference(mContext); - assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_SIZE_PREFERENCE_KEY); - assertThat("" + pref.getTitle()).isEqualTo(getText(EXTERNAL_DISPLAY_SIZE_TITLE_RESOURCE)); + assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_SIZE.key); + assertThat("" + pref.getTitle()) + .isEqualTo(getText(PrefBasics.EXTERNAL_DISPLAY_SIZE.titleResource)); assertThat("" + pref.getSummary()) .isEqualTo(getText(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE)); assertThat(pref.isEnabled()).isTrue(); @@ -398,8 +385,9 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa var fragment = initFragment(); mHandler.flush(); var pref = fragment.getUseDisplayPreference(mContext); - assertThat(pref.getKey()).isEqualTo(EXTERNAL_DISPLAY_USE_PREFERENCE_KEY); - assertThat("" + pref.getTitle()).isEqualTo(getText(EXTERNAL_DISPLAY_USE_TITLE_RESOURCE)); + assertThat(pref.getKey()).isEqualTo(PrefBasics.EXTERNAL_DISPLAY_USE.key); + assertThat("" + pref.getTitle()) + .isEqualTo(getText(PrefBasics.EXTERNAL_DISPLAY_USE.titleResource)); assertThat(pref.isEnabled()).isTrue(); assertThat(pref.isChecked()).isTrue(); assertThat(pref.getOnPreferenceChangeListener()).isNotNull(); diff --git a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java index 776261a126e..eb03ee581c9 100644 --- a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java +++ b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.pm.PackageManager; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.ServiceState; @@ -67,9 +68,9 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.Executor; @RunWith(AndroidJUnit4.class) public class SimStatusDialogControllerTest { @@ -95,6 +96,7 @@ public class SimStatusDialogControllerTest { private SimStatusDialogController mController; private Context mContext; + private PackageManager mPackageManager; @Mock private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; @@ -112,6 +114,12 @@ public class SimStatusDialogControllerTest { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); when(mDialog.getContext()).thenReturn(mContext); + mPackageManager = spy(mContext.getPackageManager()); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)) + .thenReturn(true); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) + .thenReturn(true); mLifecycle = new Lifecycle(mLifecycleOwner); mTelephonyManager = spy(mContext.getSystemService(TelephonyManager.class)); diff --git a/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java index 05ca990e789..0cb42ecb09c 100644 --- a/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; import android.os.Build; -import android.platform.test.flag.junit.SetFlagsRule; import android.safetycenter.SafetyCenterManager; import android.telephony.TelephonyManager; @@ -42,11 +41,8 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.telephony.flags.Flags; - import org.junit.Assume; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -54,8 +50,6 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public final class CellularSecurityPreferenceControllerTest { - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - @Mock private TelephonyManager mTelephonyManager; private Preference mPreference; @@ -91,9 +85,6 @@ public final class CellularSecurityPreferenceControllerTest { @Test public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() { - // Enable telephony API flags for testing - enableFlags(true); - // Hardware support is enabled doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled(); doReturn(true).when(mTelephonyManager) @@ -120,9 +111,6 @@ public final class CellularSecurityPreferenceControllerTest { @Test public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() { - // Enable telephony API flags for testing - enableFlags(true); - // Hardware support is disabled doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager) .isNullCipherNotificationsEnabled(); @@ -133,11 +121,4 @@ public final class CellularSecurityPreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } - - private void enableFlags(boolean enabled) { - if (enabled) { - } else { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS); - } - } } diff --git a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java index 516c1970d0b..f8b3798207c 100644 --- a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java @@ -28,7 +28,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Build; -import android.platform.test.flag.junit.SetFlagsRule; import android.safetycenter.SafetyCenterManager; import android.telephony.TelephonyManager; @@ -39,11 +38,8 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.telephony.flags.Flags; - import org.junit.Assume; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -51,8 +47,6 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class CellularSecurityNotificationsDividerControllerTest { - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - @Mock private TelephonyManager mTelephonyManager; private Preference mPreference; @@ -86,9 +80,6 @@ public class CellularSecurityNotificationsDividerControllerTest { @Test public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() { - // Enable telephony API flags for testing - enableFlags(true); - // Hardware support is enabled doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled(); doReturn(true).when(mTelephonyManager) @@ -99,9 +90,6 @@ public class CellularSecurityNotificationsDividerControllerTest { @Test public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() { - // Enable telephony API flags for testing - enableFlags(true); - // Hardware support is disabled doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager) .isNullCipherNotificationsEnabled(); @@ -110,12 +98,4 @@ public class CellularSecurityNotificationsDividerControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } - - private void enableFlags(boolean enabled) { - if (enabled) { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS); - } else { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS); - } - } } diff --git a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java index 27cba35e189..8b4ce1adb97 100644 --- a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java @@ -29,7 +29,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Build; -import android.platform.test.flag.junit.SetFlagsRule; import android.safetycenter.SafetyCenterManager; import android.telephony.TelephonyManager; @@ -40,11 +39,8 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.telephony.flags.Flags; - import org.junit.Assume; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -52,8 +48,6 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class CellularSecurityNotificationsPreferenceControllerTest { - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - @Mock private TelephonyManager mTelephonyManager; private Preference mPreference; @@ -87,9 +81,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest { @Test public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() { - // All flags enabled - enableFlags(true); - // Hardware support is enabled doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled(); doReturn(true).when(mTelephonyManager) @@ -100,9 +91,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest { @Test public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() { - // All flags enabled - enableFlags(true); - // Hardware support is disabled doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager) .isNullCipherNotificationsEnabled(); @@ -114,8 +102,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest { @Test public void setChecked_shouldReturnTrue() { - enableFlags(true); - // Hardware support is enabled, enabling the feature doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(true); doNothing().when(mTelephonyManager) @@ -140,8 +126,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest { @Test public void isChecked_hardwareUnsupported_shouldReturnFalse() { - enableFlags(true); - // Hardware support is disabled doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager) .isNullCipherNotificationsEnabled(); @@ -153,8 +137,6 @@ public class CellularSecurityNotificationsPreferenceControllerTest { @Test public void isChecked_notificationsDisabled_shouldReturnFalse() { - enableFlags(true); - // Hardware support is enabled, but APIs are disabled doReturn(false).when(mTelephonyManager).isNullCipherNotificationsEnabled(); doReturn(false).when(mTelephonyManager) @@ -165,12 +147,4 @@ public class CellularSecurityNotificationsPreferenceControllerTest { doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled(); assertThat(mController.isChecked()).isFalse(); } - - private void enableFlags(boolean enabled) { - if (enabled) { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS); - } else { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS); - } - } }