Merge "Remove volume plus flag in Settings" into main
diff --git a/aconfig/settings_threadnetwork_flag_declarations.aconfig b/aconfig/settings_threadnetwork_flag_declarations.aconfig
new file mode 100644
index 0000000..70945d3
--- /dev/null
+++ b/aconfig/settings_threadnetwork_flag_declarations.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.settings.flags"
+
+flag {
+ name: "thread_settings_enabled"
+ namespace: "thread_network"
+ description: "Controls whether the Thread Settings UX is displayed"
+ bug: "329384658"
+}
diff --git a/res/layout/homepage_preference.xml b/res/layout/homepage_preference.xml
index f0b1b71..38cb491 100644
--- a/res/layout/homepage_preference.xml
+++ b/res/layout/homepage_preference.xml
@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -77,7 +78,7 @@
android:layout_gravity="start"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
+ android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
android:maxLines="4"
android:hyphenationFrequency="normalFast"
android:lineBreakWordStyle="phrase"
diff --git a/res/layout/wifi_network_config.xml b/res/layout/wifi_network_config.xml
index 3de1a38..dbd3e67 100644
--- a/res/layout/wifi_network_config.xml
+++ b/res/layout/wifi_network_config.xml
@@ -708,6 +708,13 @@
style="@style/wifi_item_spinner"
android:prompt="@string/wifi_privacy_settings"
android:entries="@array/wifi_privacy_entries"/>
+
+ <Spinner android:id="@+id/dhcp_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/wifi_item_spinner"
+ android:prompt="@string/wifi_privacy_device_name_settings"
+ android:entries="@array/wifi_dhcp_entries"/>
</LinearLayout>
<LinearLayout
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index a572841..a27fbaa 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -19,7 +19,7 @@
<color name="homepage_accessibility_background">#783BE5</color>
<color name="homepage_support_background">#3F5FBD</color>
<color name="contextual_card_background">@*android:color/material_grey_900</color>
- <color name="search_bar_background">?androidprv:attr/materialColorSurfaceContainerHigh</color>
+ <color name="search_bar_background">?androidprv:attr/materialColorSurfaceBright</color>
<color name="notification_importance_button_unselected">#5F6368</color>
<!-- Palette list preference colors. -->
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index fe3f429..6122e0d 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1095,6 +1095,11 @@
<item>Use device MAC</item>
</string-array>
+ <string-array name="wifi_dhcp_entries">
+ <item>Send device name to network</item>
+ <item>Don\u0027t send device name to network</item>
+ </string-array>
+
<string-array name="wifi_hidden_entries">
<item>No</item>
<item>Yes</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2f0e1d9..5c98fac 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1263,6 +1263,12 @@
<string name="privatespace_hide_off_summary">Off</string>
<!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
<string name="privatespace_hide_on_summary">On</string>
+ <!-- Title for the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=60] -->
+ <string name="private_space_hide_dialog_title">Private space will hide when you lock it next</string>
+ <!-- Text message in the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=90] -->
+ <string name="private_space_hide_dialog_message">To access your space when it’s hidden, enter \“private space\” in the search bar on your apps list</string>
+ <!-- Label for the dialog shown when Private space hidden setting is turned on. [CHAR LIMIT=90] -->
+ <string name="private_space_hide_dialog_button">Got it</string>
<!-- System category for the Private Space page. [CHAR LIMIT=30] -->
<string name="private_space_category_system">System</string>
<!-- Title for the preference to delete Private Space. [CHAR LIMIT=40] -->
@@ -1847,11 +1853,6 @@
<!-- Bluetooth developer settings: Maximum number of connected audio devices -->
<string name="bluetooth_max_connected_audio_devices_dialog_title">Select maximum number of connected Bluetooth audio devices</string>
- <!-- Nfc developer settings: The title of the setting. [CHAR LIMIT=60] -->
- <string name="nfc_stack_debuglog_title">NFC stack debug log</string>
- <!-- Nfc developer settings: The description of the setting. -->
- <string name="nfc_stack_debuglog_summary">Increase NFC stack logging level</string>
-
<!-- Nfc developer settings: The title of the setting to enable nfc verbose vendor log. [CHAR LIMIT=60] -->
<string name="nfc_verbose_vendor_log_title">NFC verbose vendor debug log</string>
<!-- Nfc developer settings: The description of the setting to enable nfc verbose vendor log. [CHAR_LIMIT=NONE] -->
@@ -10478,6 +10479,9 @@
<!-- Summary text for 3-button navigation [CHAR LIMIT=NONE] -->
<string name="legacy_navigation_summary">Go back, Home, and switch apps with buttons at the bottom of your screen.</string>
+ <!-- Accessibility string for gesture nav tutorial button [CHAR_LIMIT=NONE] -->
+ <string name="nav_tutorial_button_description">Start gesture navigation tutorial</string>
+
<!-- Search keywords for System Navigation settings. [CHAR_LIMIT=NONE]-->
<string name="keywords_system_navigation">system navigation, 2 button navigation, 3 button navigation, gesture navigation, swipe</string>
@@ -11996,6 +12000,9 @@
<string name="confirm_format_ext4_text">16K developer option is supported with ext4 filesystem. Device will be wiped and filesystem will be changed to ext4 after confirmation.</string>
<!-- Toast on failure to reformat data to ext4 -->
<string name="format_ext4_failure_toast">Failed to reformat and wipe the data partiton to ext4.</string>
+ <!-- Dialog to OEM unlock the device before using 16K developer option -->
+ <string name="confirm_oem_unlock_for_16k_title">OEM unlock required</string>
+ <string name="confirm_oem_unlock_for_16k_text">Device needs to be OEM unlocked before using 16K developer option. OEM unlock will also require formatting userdata. Please OEM unlock the device and try again.</string>
<!-- DSU Loader. Do not translate. -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0a28b01..fe2084f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -249,7 +249,7 @@
<item name="android:layout_gravity">center</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textSize">@dimen/search_bar_text_size</item>
- <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
<item name="android:singleLine">true</item>
</style>
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index 71d9fcb..9efac28 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -231,7 +231,7 @@
<style name="SuwAlertDialogThemeCompat" parent="@style/Theme.AppCompat.Dialog.Alert">
<!-- Referenced SudThemeGlifV3 style -->
<item name="android:textAllCaps">false</item>
-
+ <item name="android:colorBackground">@android:color/system_neutral1_900</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<!-- copied from Theme.DeviceDefault.Dialog.Alert -->
<item name="colorAccent">@*android:color/accent_device_default_dark</item>
@@ -243,7 +243,7 @@
<style name="SuwAlertDialogThemeCompat.Light" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
<!-- Referenced SudThemeGlifV3.Light style -->
<item name="android:textAllCaps">false</item>
-
+ <item name="android:colorBackground">@android:color/system_neutral1_50</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
<item name="colorAccent">@*android:color/accent_device_default_light</item>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index b1ebbb8..23eb1f2 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -470,11 +470,6 @@
android:entryValues="@array/bluetooth_max_connected_audio_devices_values" />
<SwitchPreferenceCompat
- android:key="nfc_stack_debuglog_enabled"
- android:title="@string/nfc_stack_debuglog_title"
- android:summary="@string/nfc_stack_debuglog_summary" />
-
- <SwitchPreferenceCompat
android:key="nfc_verbose_vendor_log"
android:title="@string/nfc_verbose_vendor_log_title"
android:summary="@string/nfc_verbose_vendor_log_summary" />
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index cb1ce44..15d5303 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -69,9 +69,11 @@
android:summary="@string/lockscreen_trivial_controls_summary"
settings:controller="com.android.settings.display.ControlsTrivialPrivacyPreferenceController"/>
+ <!-- Shortcuts -->
<Preference
android:key="customizable_lock_screen_quick_affordances"
android:title="@string/lockscreen_quick_affordances_title"
+ android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.display.CustomizableLockScreenQuickAffordancesPreferenceController" />
<SwitchPreferenceCompat
diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml
index 598f9d8..eacff88 100644
--- a/res/xml/wifi_network_details_fragment2.xml
+++ b/res/xml/wifi_network_details_fragment2.xml
@@ -112,6 +112,10 @@
android:title="@string/wifi_auto_connect_title"
android:summary="@string/wifi_auto_connect_summary"/>
+ <com.android.settings.spa.preference.ComposePreference
+ android:key="certificate_details"
+ settings:controller="com.android.settings.wifi.details2.CertificateDetailsPreferenceController"/>
+
<!-- Add device Preference -->
<Preference
android:key="add_device_to_network"
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 6e36ee3..c38ebfe 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1289,7 +1289,8 @@
*/
@ColorInt
public static int getHomepageIconColor(Context context) {
- return getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
+ return getColorAttrDefaultColor(
+ context, com.android.internal.R.attr.materialColorOnSurface);
}
/**
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index fe89bf2..35fe6e4 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -175,6 +175,9 @@
// Observe changes from accessibility selection menu
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+ }
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_STICKY_KEYS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SLOW_KEYS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS);
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
index 8af284d..41c5d75 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -125,6 +125,9 @@
final List<String> shortcutFeatureKeys = new ArrayList<>();
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+ }
mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler());
mSettingsContentObserver.registerKeysToObserverCallback(shortcutFeatureKeys, key -> {
updateShortcutPreferenceData();
diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
index 28c5335..4ea2226 100644
--- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java
+++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
@@ -74,6 +74,9 @@
mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+ }
if (Flags.forceInvertColor()) {
mShortcutFeatureKeys.add(ToggleForceInvertPreferenceController.SETTINGS_KEY);
}
diff --git a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
index 0b762f3..c797559 100644
--- a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
+++ b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
@@ -192,7 +192,7 @@
public void onDeviceBondStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
int bondState) {
if (DEBUG) {
- Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getDevice() + ", state = "
+ Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice + ", state = "
+ bondState);
}
if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -276,13 +276,13 @@
}
mDevicePreferenceMap.put(cachedDevice, preference);
if (DEBUG) {
- Log.d(TAG, "Add device. device: " + cachedDevice.getDevice());
+ Log.d(TAG, "Add device. device: " + cachedDevice);
}
}
void removeDevice(CachedBluetoothDevice cachedDevice) {
if (DEBUG) {
- Log.d(TAG, "removeDevice: " + cachedDevice.getDevice());
+ Log.d(TAG, "removeDevice: " + cachedDevice);
}
BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
if (mAvailableHearingDeviceGroup != null && preference != null) {
@@ -331,13 +331,13 @@
cachedDevice = mCachedDeviceManager.addDevice(device);
} else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
if (DEBUG) {
- Log.d(TAG, "Skip this device, already bonded: " + cachedDevice.getDevice());
+ Log.d(TAG, "Skip this device, already bonded: " + cachedDevice);
}
return;
}
if (cachedDevice.getHearingAidInfo() == null) {
if (DEBUG) {
- Log.d(TAG, "Set hearing aid info on device: " + cachedDevice.getDevice());
+ Log.d(TAG, "Set hearing aid info on device: " + cachedDevice);
}
cachedDevice.setHearingAidInfo(new HearingAidInfo.Builder().build());
}
@@ -455,7 +455,7 @@
void discoverServices(CachedBluetoothDevice cachedDevice) {
if (DEBUG) {
- Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice.getDevice());
+ Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice);
}
BluetoothGatt gatt = cachedDevice.getDevice().connectGatt(getContext(), false,
new BluetoothGattCallback() {
@@ -465,7 +465,7 @@
super.onConnectionStateChange(gatt, status, newState);
if (DEBUG) {
Log.d(TAG, "onConnectionStateChange, status: " + status + ", newState: "
- + newState + ", device: " + cachedDevice.getDevice());
+ + newState + ", device: " + cachedDevice);
}
if (status == GATT_SUCCESS
&& newState == BluetoothProfile.STATE_CONNECTED) {
@@ -481,14 +481,14 @@
super.onServicesDiscovered(gatt, status);
if (DEBUG) {
Log.d(TAG, "onServicesDiscovered, status: " + status + ", device: "
- + cachedDevice.getDevice());
+ + cachedDevice);
}
if (status == GATT_SUCCESS) {
if (gatt.getService(BluetoothUuid.HEARING_AID.getUuid()) != null
|| gatt.getService(BluetoothUuid.HAS.getUuid()) != null) {
if (DEBUG) {
Log.d(TAG, "compatible with Android, device: "
- + cachedDevice.getDevice());
+ + cachedDevice);
}
addDevice(cachedDevice);
}
diff --git a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
index 58aa0cc..21800b9 100644
--- a/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
+++ b/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceController.java
@@ -22,6 +22,7 @@
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
@@ -159,8 +160,11 @@
}
private boolean updateKeyboardVibrationSetting(boolean enable) {
- final boolean success = Settings.System.putInt(mContext.getContentResolver(),
- KEYBOARD_VIBRATION_ENABLED, enable ? ON : OFF);
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ final boolean success = Settings.System.putInt(contentResolver,
+ KEYBOARD_VIBRATION_ENABLED, enable ? ON : OFF);
+ contentResolver.notifyChange(Settings.System.getUriFor(KEYBOARD_VIBRATION_ENABLED),
+ null /* observer */, ContentResolver.NOTIFY_NO_DELAY);
if (!success) {
Log.w(TAG, "Update settings database error!");
}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 6d5f536..ed47007 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -179,6 +179,9 @@
final List<String> shortcutFeatureKeys = new ArrayList<>();
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
+ }
return shortcutFeatureKeys;
}
diff --git a/src/com/android/settings/applications/AppStoreUtil.java b/src/com/android/settings/applications/AppStoreUtil.java
index b73b14a..636669c 100644
--- a/src/com/android/settings/applications/AppStoreUtil.java
+++ b/src/com/android/settings/applications/AppStoreUtil.java
@@ -83,6 +83,7 @@
}
/** Convenience method that looks up the installerPackageName for you. */
+ @Nullable
public static Intent getAppStoreLink(Context context, String packageName) {
String installerPackageName = getInstallerPackageName(context, packageName);
return getAppStoreLink(context, installerPackageName, packageName);
diff --git a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
index faa1b51..81e8439 100644
--- a/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
+++ b/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetails.java
@@ -384,20 +384,21 @@
}
private void handleInstallBannerClick() {
- if (mInstallAppIntent == null) {
- logEvent(
- DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED);
- return;
- }
- if (!mInstalledInWork) {
+ if (mInstallAppIntent != null
+ && !mInstalledInWork
+ && isInstallableInProfile(mInstallAppIntent, mWorkProfile)) {
logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
mContext.startActivityAsUser(mInstallAppIntent, mWorkProfile);
return;
}
- if (!mInstalledInPersonal) {
+ if (mInstallAppIntent != null
+ && !mInstalledInPersonal
+ && isInstallableInProfile(mInstallAppIntent, mPersonalProfile)) {
logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
mContext.startActivityAsUser(mInstallAppIntent, mPersonalProfile);
+ return;
}
+ logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED);
}
/**
@@ -447,7 +448,8 @@
R.string.interact_across_profiles_install_personal_app_title,
mAppLabel),
mAppLabel));
- if (mInstallAppIntent != null) {
+ if (mInstallAppIntent != null
+ && isInstallableInProfile(mInstallAppIntent, mPersonalProfile)) {
mInstallBanner.setSummary(
R.string.interact_across_profiles_install_app_summary);
}
@@ -461,7 +463,8 @@
R.string.interact_across_profiles_install_work_app_title,
mAppLabel),
mAppLabel));
- if (mInstallAppIntent != null) {
+ if (mInstallAppIntent != null
+ && isInstallableInProfile(mInstallAppIntent, mWorkProfile)) {
mInstallBanner.setSummary(
R.string.interact_across_profiles_install_app_summary);
}
@@ -488,6 +491,12 @@
return info != null;
}
+ private boolean isInstallableInProfile(Intent intent, UserHandle profile) {
+ return !mContext.getPackageManager()
+ .queryIntentActivitiesAsUser(intent, /* flags= */ 0, profile)
+ .isEmpty();
+ }
+
private void refreshUiForConfigurableApps() {
mInstallBanner.setVisible(false);
mSwitchPref.setEnabled(true);
diff --git a/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt b/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
index f5c0a87..1c01750 100644
--- a/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
+++ b/src/com/android/settings/connecteddevice/threadnetwork/ThreadNetworkPreferenceController.kt
@@ -34,9 +34,9 @@
import androidx.lifecycle.LifecycleOwner
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
-import com.android.net.thread.platform.flags.Flags
import com.android.settings.R
import com.android.settings.core.TogglePreferenceController
+import com.android.settings.flags.Flags
import java.util.concurrent.Executor
/** Controller for the "Thread" toggle in "Connected devices > Connection preferences". */
@@ -110,7 +110,7 @@
}
override fun getAvailabilityStatus(): Int {
- return if (!Flags.threadEnabledPlatform()) {
+ return if (!Flags.threadSettingsEnabled()) {
CONDITIONALLY_UNAVAILABLE
} else if (!isThreadSupportedOnDevice) {
UNSUPPORTED_ON_DEVICE
diff --git a/src/com/android/settings/development/Enable16KOemUnlockDialog.java b/src/com/android/settings/development/Enable16KOemUnlockDialog.java
new file mode 100644
index 0000000..65690df
--- /dev/null
+++ b/src/com/android/settings/development/Enable16KOemUnlockDialog.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/** Dialog when user interacts 16K pages developer option and device is not OEM unlocked */
+public class Enable16KOemUnlockDialog extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+ public static final String TAG = "Enable16KOemUnlockDialog";
+
+ /** This method is used to prompt user to do OEM unlock before using 16k */
+ public static void show(@NonNull Fragment hostFragment) {
+ final FragmentManager manager = hostFragment.getActivity().getSupportFragmentManager();
+ Fragment existingFragment = manager.findFragmentByTag(TAG);
+ if (existingFragment == null) {
+ existingFragment = new Enable16KOemUnlockDialog();
+ }
+
+ if (existingFragment instanceof Enable16KOemUnlockDialog) {
+ existingFragment.setTargetFragment(hostFragment, 0 /* requestCode */);
+ ((Enable16KOemUnlockDialog) existingFragment).show(manager, TAG);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_ENABLE_16K_PAGES;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.confirm_oem_unlock_for_16k_title)
+ .setMessage(R.string.confirm_oem_unlock_for_16k_text)
+ .setPositiveButton(android.R.string.ok, this /* onClickListener */)
+ .create();
+ }
+
+ @Override
+ public void onClick(@NonNull DialogInterface dialog, int buttonId) {
+ // Do nothing. OEM unlock has to be done by user
+ }
+
+ @Override
+ public void onDismiss(@NonNull DialogInterface dialog) {
+ super.onDismiss(dialog);
+ }
+}
diff --git a/src/com/android/settings/development/Enable16kPagesPreferenceController.java b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
index 7049e79..bed5c04 100644
--- a/src/com/android/settings/development/Enable16kPagesPreferenceController.java
+++ b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
@@ -28,7 +28,10 @@
import android.os.UpdateEngine;
import android.os.UpdateEngineStable;
import android.os.UpdateEngineStableCallback;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
+import android.service.oemlock.OemLockManager;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -116,6 +119,12 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mEnable16k = (Boolean) newValue;
+ // Prompt user to do oem unlock first
+ if (!isDeviceOEMUnlocked()) {
+ Enable16KOemUnlockDialog.show(mFragment);
+ return false;
+ }
+
if (isDataf2fs()) {
EnableExt4WarningDialog.show(mFragment, this);
return false;
@@ -418,4 +427,30 @@
return false;
}
+
+ private boolean isDeviceOEMUnlocked() {
+ // OEM unlock is checked for bootloader, carrier and user. Check all three to ensure
+ // that device is unlocked and it is also allowed by user as well as carrier
+ final OemLockManager oemLockManager = mContext.getSystemService(OemLockManager.class);
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ if (oemLockManager == null || userManager == null) {
+ Log.e(TAG, "Required services not found on device to check for OEM unlock state.");
+ return false;
+ }
+
+ // If either of device or carrier is not allowed to unlock, return false
+ if (!oemLockManager.isDeviceOemUnlocked()
+ || !oemLockManager.isOemUnlockAllowedByCarrier()) {
+ Log.e(TAG, "Device is not OEM unlocked or it is not allowed by carrier");
+ return false;
+ }
+
+ final UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
+ if (userManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, userHandle)) {
+ Log.e(TAG, "Factory reset is not allowed for user.");
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
index 04898dc..fe7db4f 100644
--- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java
+++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
@@ -50,6 +50,8 @@
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
static final Uri HARDWARE_SHORTCUT_ENABLED_URI =
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ static final Uri QS_SHORTCUT_ENABLED_URI =
+ Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_QS_TARGETS);
public enum OneHandedTimeout {
NEVER(0), SHORT(4), MEDIUM(8), LONG(12);
@@ -254,6 +256,16 @@
if (!TextUtils.isEmpty(targetsHW) && targetsHW.contains(ONE_HANDED_MODE_TARGET_NAME)) {
return true;
}
+
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ // Checks QS_SHORTCUT_KEY
+ final String targetsQs = Settings.Secure.getStringForUser(context.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS, sCurrentUserId);
+ if (!TextUtils.isEmpty(targetsQs) && targetsQs.contains(ONE_HANDED_MODE_TARGET_NAME)) {
+ return true;
+ }
+ }
+
return false;
}
@@ -301,6 +313,9 @@
resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this);
resolver.registerContentObserver(SOFTWARE_SHORTCUT_ENABLED_URI, true, this);
resolver.registerContentObserver(HARDWARE_SHORTCUT_ENABLED_URI, true, this);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ resolver.registerContentObserver(QS_SHORTCUT_ENABLED_URI, true, this);
+ }
}
@Override
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index c40212b..c38be94 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -247,6 +247,7 @@
switch (systemNavKey) {
case KEY_SYSTEM_NAV_GESTURAL:
if (isGestureTutorialAvailable()){
+ videoPref.setContentDescription(R.string.nav_tutorial_button_description);
videoPref.setOnPreferenceClickListener(preference -> {
startActivity(mLaunchSandboxIntent);
return true;
diff --git a/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java b/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
index 28c2915..30253a8 100644
--- a/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
+++ b/src/com/android/settings/inputmethod/TrackpadTapDraggingPreferenceController.java
@@ -16,16 +16,22 @@
package com.android.settings.inputmethod;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.input.InputSettings;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class TrackpadTapDraggingPreferenceController extends TogglePreferenceController {
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+
public TrackpadTapDraggingPreferenceController(Context context, String key) {
super(context, key);
+ mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
@Override
@@ -36,7 +42,8 @@
@Override
public boolean setChecked(boolean isChecked) {
InputSettings.setTouchpadTapDragging(mContext, isChecked);
- // TODO(b/321978150): add a metric for tap dragging settings changes.
+ mMetricsFeatureProvider.action(
+ mContext, SettingsEnums.ACTION_GESTURE_TAP_DRAGGING_CHANGED, isChecked);
return true;
}
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index 9892f0d..782ab7d 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -25,7 +25,6 @@
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.system.ResetDashboardFragment;
@@ -51,7 +50,12 @@
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
- EraseEuiccDataDialogFragment.show(mHostFragment);
+ if (SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext)
+ && !SubscriptionUtil.isConnectedToWifi(mContext)) {
+ EuiccRacConnectivityDialogFragment.show(mHostFragment);
+ } else {
+ EraseEuiccDataDialogFragment.show(mHostFragment);
+ }
return true;
}
diff --git a/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java b/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java
new file mode 100644
index 0000000..76a587e
--- /dev/null
+++ b/src/com/android/settings/network/EuiccRacConnectivityDialogFragment.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.system.ResetDashboardFragment;
+
+public class EuiccRacConnectivityDialogFragment extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener {
+ public static final String TAG = "EuiccRacConnectivityDlg";
+
+ static void show(ResetDashboardFragment host) {
+ final EuiccRacConnectivityDialogFragment dialog = new EuiccRacConnectivityDialogFragment();
+ dialog.setTargetFragment(host, /* requestCode= */ 0);
+ final FragmentManager manager = host.getActivity().getSupportFragmentManager();
+ dialog.show(manager, TAG);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.RESET_EUICC;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ String title = getString(R.string.wifi_warning_dialog_title);
+ String message = getString(R.string.wifi_warning_dialog_text);
+
+ AlertDialog.Builder builder =
+ new AlertDialog.Builder(getContext())
+ .setOnDismissListener(this)
+ // Return is on the right side
+ .setPositiveButton(R.string.wifi_warning_return_button, null)
+ // Continue is on the left side
+ .setNegativeButton(R.string.wifi_warning_continue_button, this);
+
+ View content =
+ LayoutInflater.from(getContext())
+ .inflate(R.layout.sim_warning_dialog_wifi_connectivity, null);
+
+ // Found the layout resource
+ if (content != null) {
+ TextView dialogTitle = content.findViewById(R.id.title);
+ if (!TextUtils.isEmpty(title) && dialogTitle != null) {
+ dialogTitle.setText(title);
+ dialogTitle.setVisibility(View.VISIBLE);
+ }
+ TextView dialogMessage = content.findViewById(R.id.msg);
+ if (!TextUtils.isEmpty(message) && dialogMessage != null) {
+ dialogMessage.setText(message);
+ dialogMessage.setVisibility(View.VISIBLE);
+ }
+
+ builder.setView(content);
+ } else { // Not found the layout resource, use standard layout
+ if (!TextUtils.isEmpty(title)) {
+ builder.setTitle(title);
+ }
+ if (!TextUtils.isEmpty(message)) {
+ builder.setMessage(message);
+ }
+ }
+
+ AlertDialog dialog = builder.create();
+ dialog.setCanceledOnTouchOutside(false);
+ return dialog;
+ }
+
+ @Override
+ public void onClick(@NonNull DialogInterface dialog, int which) {
+ final Fragment fragment = getTargetFragment();
+ if (!(fragment instanceof ResetDashboardFragment)) {
+ Log.e(TAG, "getTargetFragment return unexpected type");
+ return;
+ }
+
+ // Positions of the buttons have been switch:
+ // negative button = left button = the button to continue
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ EraseEuiccDataDialogFragment.show(((ResetDashboardFragment) fragment));
+ }
+ }
+}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 497af25..6d6f4c5 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -523,20 +523,21 @@
/**
* Starts a dialog activity to handle eSIM deletion.
+ *
* @param context {@code Context}
* @param subId The id of subscription need to be deleted.
+ * @param carrierId The carrier id of the subscription.
*/
- public static void startDeleteEuiccSubscriptionDialogActivity(Context context, int subId,
- int carrierId) {
+ public static void startDeleteEuiccSubscriptionDialogActivity(
+ @NonNull Context context, int subId, int carrierId) {
if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
Log.i(TAG, "Unable to delete subscription due to invalid subscription ID.");
return;
}
- final int[] carriersThatUseRAC = context.getResources().getIntArray(
- R.array.config_carrier_use_rac);
- boolean isCarrierRac = Arrays.stream(carriersThatUseRAC).anyMatch(cid -> cid == carrierId);
- if (isCarrierRac && !isConnectedToWifiOrDifferentSubId(context, subId)) {
+ if (isCarrierRac(context, carrierId)
+ && (!isConnectedToWifi(context)
+ || isConnectedToMobileDataWithDifferentSubId(context, subId))) {
context.startActivity(EuiccRacConnectivityDialogActivity.getIntent(context, subId));
} else {
context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
@@ -814,27 +815,75 @@
}
/**
- * Returns {@code true} if device is connected to Wi-Fi or mobile data provided by a different
- * subId.
+ * Checks if the device is connected to Wi-Fi.
+ *
+ * @param context context
+ * @return {@code true} if connected to Wi-Fi
+ */
+ static boolean isConnectedToWifi(@NonNull Context context) {
+ NetworkCapabilities capabilities = getNetworkCapabilities(context);
+
+ return capabilities != null
+ && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+ }
+
+ /**
+ * Checks if the device is connected to mobile data provided by a different subId.
*
* @param context context
* @param targetSubId subscription that is going to be deleted
+ * @return {@code true} if connected to mobile data provided by a different subId
*/
@VisibleForTesting
- static boolean isConnectedToWifiOrDifferentSubId(@NonNull Context context, int targetSubId) {
+ static boolean isConnectedToMobileDataWithDifferentSubId(
+ @NonNull Context context, int targetSubId) {
+ NetworkCapabilities capabilities = getNetworkCapabilities(context);
+
+ return capabilities != null
+ && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && targetSubId != SubscriptionManager.getActiveDataSubscriptionId();
+ }
+
+ /**
+ * Checks if any subscription carrier use reusable activation codes.
+ *
+ * @param context The context used to retrieve carriers that uses reusable activation codes.
+ * @return {@code true} if any subscription has a matching carrier that uses reusable activation
+ * codes
+ */
+ static boolean hasSubscriptionWithRacCarrier(@NonNull Context context) {
+ List<SubscriptionInfo> subs = getAvailableSubscriptions(context);
+ final int[] carriersThatUseRac =
+ context.getResources().getIntArray(R.array.config_carrier_use_rac);
+
+ return Arrays.stream(carriersThatUseRac)
+ .anyMatch(cid -> subs.stream().anyMatch(sub -> sub.getCarrierId() == cid));
+ }
+
+ /**
+ * Checks if a carrier use reusable activation codes.
+ *
+ * @param context The context used to retrieve carriers that uses reusable activation codes.
+ * @param carrierId The carrier id to check if it use reusable activation codes.
+ * @return {@code true} if carrier id use reusable activation codes.
+ */
+ @VisibleForTesting
+ static boolean isCarrierRac(@NonNull Context context, int carrierId) {
+ final int[] carriersThatUseRAC =
+ context.getResources().getIntArray(R.array.config_carrier_use_rac);
+
+ return Arrays.stream(carriersThatUseRAC).anyMatch(cid -> cid == carrierId);
+ }
+
+ /**
+ * Retrieves NetworkCapabilities for the active network.
+ *
+ * @param context context
+ * @return NetworkCapabilities or null if not available
+ */
+ private static NetworkCapabilities getNetworkCapabilities(@NonNull Context context) {
ConnectivityManager connectivityManager =
context.getSystemService(ConnectivityManager.class);
- NetworkCapabilities capabilities =
- connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
-
- if (capabilities != null) {
- if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
- // Connected to WiFi
- return true;
- } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return targetSubId != SubscriptionManager.getActiveDataSubscriptionId();
- }
- }
- return false;
+ return connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
}
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
index 907bab1..1e635a5 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
@@ -84,6 +84,13 @@
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ if (!this::lazyViewModel.isInitialized) {
+ Log.e(
+ this.javaClass.simpleName,
+ "lateinit property lazyViewModel has not been initialized"
+ )
+ return
+ }
preference.isVisible = false
val viewModel by lazyViewModel
diff --git a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
index 8ec313b..e134681 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
@@ -78,6 +78,13 @@
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ if (!this::lazyViewModel.isInitialized) {
+ Log.e(
+ this.javaClass.simpleName,
+ "lateinit property lazyViewModel has not been initialized"
+ )
+ return
+ }
val viewModel by lazyViewModel
val coroutineScope = viewLifecycleOwner.lifecycleScope
diff --git a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
index 65a4b7e..10a8b53 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
+import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -66,6 +67,13 @@
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ if (!this::lazyViewModel.isInitialized) {
+ Log.e(
+ this.javaClass.simpleName,
+ "lateinit property lazyViewModel has not been initialized"
+ )
+ return
+ }
val viewModel by lazyViewModel
val coroutineScope = viewLifecycleOwner.lifecycleScope
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
index ac055b0..4736eb7 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
+import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -26,6 +27,7 @@
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.flags.Flags
+import com.android.settings.network.SimOnboardingActivity
import com.android.settings.network.SubscriptionInfoListViewModel
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
@@ -57,6 +59,14 @@
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ if (!this::lazyViewModel.isInitialized) {
+ Log.e(
+ this.javaClass.simpleName,
+ "lateinit property lazyViewModel has not been initialized"
+ )
+ return
+ }
+
val viewModel by lazyViewModel
viewModel.subscriptionInfoListFlow
diff --git a/src/com/android/settings/network/telephony/NetworkSelectRepository.kt b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt
new file mode 100644
index 0000000..1f5fbc2
--- /dev/null
+++ b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.NetworkRegistrationInfo
+import android.telephony.TelephonyManager
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class NetworkSelectRepository(context: Context, subId: Int) {
+ private val telephonyManager =
+ context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
+
+ data class NetworkRegistrationAndForbiddenInfo(
+ val networkList: List<NetworkRegistrationInfo>,
+ val forbiddenPlmns: List<String>,
+ )
+
+ /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
+ fun launchUpdateNetworkRegistrationInfo(
+ lifecycleOwner: LifecycleOwner,
+ action: (NetworkRegistrationAndForbiddenInfo) -> Unit,
+ ) {
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ withContext(Dispatchers.Default) {
+ getNetworkRegistrationInfo()
+ }?.let(action)
+ }
+ }
+ }
+
+ fun getNetworkRegistrationInfo(): NetworkRegistrationAndForbiddenInfo? {
+ if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null
+ // Try to get the network registration states
+ val serviceState = telephonyManager.serviceState ?: return null
+ val networkList = serviceState.getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ )
+ if (networkList.isEmpty()) return null
+ // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
+ // containing forbidden PLMN.
+ // Getting current network from ServiceState is no longer a good idea.
+ // Add an additional rule to avoid from showing forbidden PLMN to the user.
+ return NetworkRegistrationAndForbiddenInfo(networkList, getForbiddenPlmns())
+ }
+
+ /**
+ * Update forbidden PLMNs from the USIM App
+ */
+ private fun getForbiddenPlmns(): List<String> {
+ return telephonyManager.forbiddenPlmns?.toList() ?: emptyList()
+ }
+}
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index eb89d9e..19bc390 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -24,12 +24,10 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Settings;
-import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -52,13 +50,11 @@
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos;
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete;
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError;
-import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanResult;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.ThreadUtils;
import kotlin.Unit;
-import kotlin.jvm.functions.Function1;
import java.util.ArrayList;
import java.util.Arrays;
@@ -101,6 +97,8 @@
private NetworkScanRepository mNetworkScanRepository;
private boolean mUpdateScanResult = false;
+ private NetworkSelectRepository mNetworkSelectRepository;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -138,6 +136,7 @@
mCarrierConfigManager.registerCarrierConfigChangeListener(mNetworkScanExecutor,
mCarrierConfigChangeListener);
mNetworkScanRepository = new NetworkScanRepository(context, mSubId);
+ mNetworkSelectRepository = new NetworkSelectRepository(context, mSubId);
}
@Keep
@@ -202,35 +201,37 @@
mProgressHeader = setPinnedHeaderView(
com.android.settingslib.widget.progressbar.R.layout.progress_header
).findViewById(com.android.settingslib.widget.progressbar.R.id.progress_bar_animation);
- forceUpdateConnectedPreferenceCategory();
+ mNetworkSelectRepository.launchUpdateNetworkRegistrationInfo(
+ getViewLifecycleOwner(),
+ (info) -> {
+ forceUpdateConnectedPreferenceCategory(info);
+ return Unit.INSTANCE;
+ });
launchNetworkScan();
}
private void launchNetworkScan() {
- mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), new Function1<>() {
- @Override
- public Unit invoke(@NonNull NetworkScanResult networkScanResult) {
- if (!mUpdateScanResult) {
- // Not update UI if not in scan mode.
- return Unit.INSTANCE;
- }
- if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
- scanResultHandler(networkScanCellInfos.getCellInfos());
- return Unit.INSTANCE;
- }
- if (!isPreferenceScreenEnabled()) {
- clearPreferenceSummary();
- enablePreferenceScreen(true);
- } else if (networkScanResult instanceof NetworkScanComplete
- && mCellInfoList == null) {
- // In case the scan timeout before getting any results
- addMessagePreference(R.string.empty_networks_list);
- } else if (networkScanResult instanceof NetworkScanError) {
- addMessagePreference(R.string.network_query_error);
- }
-
+ mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), (networkScanResult) -> {
+ if (!mUpdateScanResult) {
+ // Not update UI if not in scan mode.
return Unit.INSTANCE;
}
+ if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
+ scanResultHandler(networkScanCellInfos.getCellInfos());
+ return Unit.INSTANCE;
+ }
+ if (!isPreferenceScreenEnabled()) {
+ clearPreferenceSummary();
+ enablePreferenceScreen(true);
+ } else if (networkScanResult instanceof NetworkScanComplete
+ && mCellInfoList == null) {
+ // In case the scan timeout before getting any results
+ addMessagePreference(R.string.empty_networks_list);
+ } else if (networkScanResult instanceof NetworkScanError) {
+ addMessagePreference(R.string.network_query_error);
+ }
+
+ return Unit.INSTANCE;
});
}
@@ -238,7 +239,6 @@
public void onStart() {
super.onStart();
- updateForbiddenPlmns();
setProgressBarVisible(true);
mUpdateScanResult = true;
}
@@ -477,45 +477,26 @@
* - If the device has no data, we will remove the connected network operators list from the
* screen.
*/
- private void forceUpdateConnectedPreferenceCategory() {
- if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
- // Try to get the network registration states
- final ServiceState ss = mTelephonyManager.getServiceState();
- if (ss == null) {
- return;
+ private void forceUpdateConnectedPreferenceCategory(
+ NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo info) {
+ for (NetworkRegistrationInfo regInfo : info.getNetworkList()) {
+ final CellIdentity cellIdentity = regInfo.getCellIdentity();
+ if (cellIdentity == null) {
+ continue;
}
- final List<NetworkRegistrationInfo> networkList =
- ss.getNetworkRegistrationInfoListForTransportType(
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- if (networkList == null || networkList.size() == 0) {
- return;
+ final NetworkOperatorPreference pref = new NetworkOperatorPreference(
+ getPrefContext(), info.getForbiddenPlmns(), mShow4GForLTE);
+ pref.updateCell(null, cellIdentity);
+ if (pref.isForbiddenNetwork()) {
+ continue;
}
- // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
- // containing forbidden PLMN.
- // Getting current network from ServiceState is no longer a good idea.
- // Add an additional rule to avoid from showing forbidden PLMN to the user.
- if (mForbiddenPlmns == null) {
- updateForbiddenPlmns();
- }
- for (NetworkRegistrationInfo regInfo : networkList) {
- final CellIdentity cellIdentity = regInfo.getCellIdentity();
- if (cellIdentity == null) {
- continue;
- }
- final NetworkOperatorPreference pref = new NetworkOperatorPreference(
- getPrefContext(), mForbiddenPlmns, mShow4GForLTE);
- pref.updateCell(null, cellIdentity);
- if (pref.isForbiddenNetwork()) {
- continue;
- }
- pref.setSummary(R.string.network_connected);
- // Update the signal strength icon, since the default signalStrength value
- // would be zero
- // (it would be quite confusing why the connected network has no signal)
- pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
- mPreferenceCategory.addPreference(pref);
- break;
- }
+ pref.setSummary(R.string.network_connected);
+ // Update the signal strength icon, since the default signalStrength value
+ // would be zero
+ // (it would be quite confusing why the connected network has no signal)
+ pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
+ mPreferenceCategory.addPreference(pref);
+ break;
}
}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index 0ee1d87..f184092 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -22,6 +22,7 @@
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.ims.ImsMmTelManager
+import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
@@ -76,6 +77,13 @@
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ if(mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID){
+ Log.e(
+ this.javaClass.simpleName,
+ "mSubId is INVALID_SUBSCRIPTION_ID"
+ )
+ return
+ }
wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow()
.collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
preference.isVisible = isReady
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
index d709574..67a2356 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
@@ -23,6 +23,7 @@
import android.provider.Settings
import android.telephony.CarrierConfigManager
import android.telephony.ServiceState
+import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
@@ -80,7 +81,7 @@
@VisibleForTesting
var progressDialog: ProgressDialog? = null
- private var subId by notNull<Int>()
+ private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
/**
* Initialization based on given subscription id.
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceController.java b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
index 903defa..81814ad 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
@@ -19,13 +19,21 @@
import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL;
import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
+import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
/**
- * A class that is used to show details page for the setting to hide private space entry point
- * in All Apps.
+ * Toggle Preference Controller responsible for managing the visibility of private space entry point
+ * in the "All Apps" section. This includes:
+ *
+ * <p>Toggling the entry point's visibility (hiding/unhiding)
+ *
+ * <p>Displaying a dialog to inform the user that the entry point will be hidden when private space
+ * is locked (if the hide option is enabled)
*/
public class HidePrivateSpaceController extends TogglePreferenceController {
private final PrivateSpaceMaintainer mPrivateSpaceMaintainer;
@@ -39,7 +47,7 @@
@AvailabilityStatus
public int getAvailabilityStatus() {
return android.os.Flags.allowPrivateProfile()
- && android.multiuser.Flags.enablePrivateSpaceFeatures()
+ && android.multiuser.Flags.enablePrivateSpaceFeatures()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@@ -55,6 +63,9 @@
mPrivateSpaceMaintainer.setHidePrivateSpaceEntryPointSetting(
isChecked ? HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL
: HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL);
+ if (isChecked) {
+ showAlertDialog();
+ }
return true;
}
@@ -62,4 +73,16 @@
public int getSliceHighlightMenuRes() {
return 0;
}
+
+ private void showAlertDialog() {
+ new AlertDialog.Builder(mContext)
+ .setTitle(R.string.private_space_hide_dialog_title)
+ .setMessage(R.string.private_space_hide_dialog_message)
+ .setPositiveButton(
+ R.string.private_space_hide_dialog_button,
+ (DialogInterface dialog, int which) -> {
+ dialog.dismiss();
+ })
+ .show();
+ }
}
diff --git a/src/com/android/settings/security/ContentProtectionPreferenceUtils.java b/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
index d84d7c5..b1167ea 100644
--- a/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
+++ b/src/com/android/settings/security/ContentProtectionPreferenceUtils.java
@@ -15,15 +15,23 @@
*/
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
import static com.android.internal.R.string.config_defaultContentProtectionService;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.DeviceConfig;
import android.view.contentcapture.ContentCaptureManager;
-import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.Utils;
/** Util class for content protection preference. */
public class ContentProtectionPreferenceUtils {
@@ -60,4 +68,49 @@
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER,
ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER);
}
+
+ /** Returns the managed profile or null if none exists. */
+ @Nullable
+ public static UserHandle getManagedProfile(@NonNull Context context) {
+ UserManager userManager = context.getSystemService(UserManager.class);
+ if (userManager == null) {
+ return null;
+ }
+ return Utils.getManagedProfile(userManager);
+ }
+
+ /** Returns the current content protection policy. */
+ @DevicePolicyManager.ContentProtectionPolicy
+ public static int getContentProtectionPolicy(
+ @NonNull Context context, @Nullable UserHandle managedProfile) {
+ if (!manageDevicePolicyEnabled()) {
+ return DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ }
+ Context policyContext = createContentProtectionPolicyContext(context, managedProfile);
+ return getContentProtectionPolicyWithGivenContext(policyContext);
+ }
+
+ @NonNull
+ private static Context createContentProtectionPolicyContext(
+ @NonNull Context context, @Nullable UserHandle managedProfile) {
+ if (managedProfile == null) {
+ return context;
+ }
+ try {
+ return context.createPackageContextAsUser(
+ context.getPackageName(), /* flags= */ 0, managedProfile);
+ } catch (PackageManager.NameNotFoundException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @DevicePolicyManager.ContentProtectionPolicy
+ private static int getContentProtectionPolicyWithGivenContext(@NonNull Context context) {
+ DevicePolicyManager devicePolicyManager =
+ context.getSystemService(DevicePolicyManager.class);
+ if (devicePolicyManager == null) {
+ return DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ }
+ return devicePolicyManager.getContentProtectionPolicy(/* admin= */ null);
+ }
}
diff --git a/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java b/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
index 101364b..9203d61 100644
--- a/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
+++ b/src/com/android/settings/security/ContentProtectionTogglePreferenceController.java
@@ -15,12 +15,17 @@
*/
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
+import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
+import android.os.UserHandle;
import android.provider.Settings;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -40,12 +45,22 @@
static final String KEY_CONTENT_PROTECTION_PREFERENCE = "content_protection_user_consent";
@Nullable private SettingsMainSwitchPreference mSwitchBar;
+
@Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
- private final ContentResolver mContentResolver;
+
+ @NonNull private final ContentResolver mContentResolver;
+
+ @DevicePolicyManager.ContentProtectionPolicy
+ private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
public ContentProtectionTogglePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mContentResolver = context.getContentResolver();
+
+ if (manageDevicePolicyEnabled()) {
+ mEnforcedAdmin = getEnforcedAdmin();
+ mContentProtectionPolicy = getContentProtectionPolicy(getManagedProfile());
+ }
}
@Override
@@ -56,14 +71,30 @@
@Override
public boolean isChecked() {
if (mEnforcedAdmin != null) {
- // If fully managed device, it should always unchecked
- return false;
+ if (!manageDevicePolicyEnabled()) {
+ // If fully managed device, it should always unchecked
+ return false;
+ }
+
+ if (mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_DISABLED) {
+ return false;
+ }
+ if (mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_ENABLED) {
+ return true;
+ }
}
return Settings.Global.getInt(mContentResolver, KEY_CONTENT_PROTECTION_PREFERENCE, 0) >= 0;
}
@Override
public boolean setChecked(boolean isChecked) {
+ if (manageDevicePolicyEnabled()) {
+ if (mEnforcedAdmin != null
+ && mContentProtectionPolicy
+ != DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
+ return false;
+ }
+ }
Settings.Global.putInt(
mContentResolver, KEY_CONTENT_PROTECTION_PREFERENCE, isChecked ? 1 : -1);
return true;
@@ -80,16 +111,20 @@
}
}
- /**
- * Temporary workaround for SettingsMainSwitchPreference.setDisabledByAdmin without user
- * restriction.
- */
+ // Workaround for SettingsMainSwitchPreference.setDisabledByAdmin without user restriction.
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- // Assign the value to mEnforcedAdmin since it's needed in isChecked()
- mEnforcedAdmin = getEnforcedAdmin();
- if (mSwitchBar != null && mEnforcedAdmin != null) {
+
+ if (!manageDevicePolicyEnabled()) {
+ // Assign the value to mEnforcedAdmin since it's needed in isChecked()
+ mEnforcedAdmin = getEnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ }
+ if (mSwitchBar != null
+ && mEnforcedAdmin != null
+ && mContentProtectionPolicy
+ != DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
mSwitchBar.setDisabledByAdmin(mEnforcedAdmin);
}
}
@@ -107,7 +142,20 @@
}
@VisibleForTesting
+ @Nullable
+ protected UserHandle getManagedProfile() {
+ return ContentProtectionPreferenceUtils.getManagedProfile(mContext);
+ }
+
+ @VisibleForTesting
+ @Nullable
protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin() {
return RestrictedLockUtilsInternal.getDeviceOwner(mContext);
}
+
+ @VisibleForTesting
+ @DevicePolicyManager.ContentProtectionPolicy
+ protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+ return ContentProtectionPreferenceUtils.getContentProtectionPolicy(mContext, userHandle);
+ }
}
diff --git a/src/com/android/settings/security/ContentProtectionWorkSwitchController.java b/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
index 0404dcd..b9119ee 100644
--- a/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
+++ b/src/com/android/settings/security/ContentProtectionWorkSwitchController.java
@@ -15,9 +15,11 @@
*/
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.manageDevicePolicyEnabled;
+
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.UserHandle;
-import android.os.UserManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -25,7 +27,6 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settings.Utils;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -33,25 +34,49 @@
/** Preference controller for content protection work profile switch bar. */
public class ContentProtectionWorkSwitchController extends TogglePreferenceController {
+ @Nullable private UserHandle mManagedProfile;
+
+ @DevicePolicyManager.ContentProtectionPolicy
+ private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
public ContentProtectionWorkSwitchController(
@NonNull Context context, @NonNull String preferenceKey) {
super(context, preferenceKey);
+
+ if (manageDevicePolicyEnabled()) {
+ mManagedProfile = getManagedProfile();
+ if (mManagedProfile != null) {
+ mContentProtectionPolicy = getContentProtectionPolicy(mManagedProfile);
+ }
+ }
}
@Override
public int getAvailabilityStatus() {
- return getManagedProfile() != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ if (!manageDevicePolicyEnabled()) {
+ return getManagedProfile() != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ }
+ if (mManagedProfile == null) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+ if (mContentProtectionPolicy
+ == DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+ return AVAILABLE;
}
- // The switch is always set to unchecked until Android V by design
@Override
public boolean isChecked() {
- return false;
+ if (!manageDevicePolicyEnabled()) {
+ return false;
+ }
+ return mContentProtectionPolicy == DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
}
- // The switch is disabled until Android V by design
@Override
public boolean setChecked(boolean isChecked) {
+ // Controlled by the admin API
return false;
}
@@ -59,10 +84,13 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- RestrictedSwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
- UserHandle managedProfile = getManagedProfile();
+ UserHandle managedProfile =
+ manageDevicePolicyEnabled() ? mManagedProfile : getManagedProfile();
if (managedProfile != null) {
- switchPreference.setDisabledByAdmin(getEnforcedAdmin(managedProfile));
+ RestrictedSwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
+ if (switchPreference != null) {
+ switchPreference.setDisabledByAdmin(getEnforcedAdmin(managedProfile));
+ }
}
}
@@ -74,13 +102,18 @@
@VisibleForTesting
@Nullable
protected UserHandle getManagedProfile() {
- return Utils.getManagedProfile(mContext.getSystemService(UserManager.class));
+ return ContentProtectionPreferenceUtils.getManagedProfile(mContext);
}
@VisibleForTesting
@Nullable
- protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(
- @NonNull UserHandle managedProfile) {
- return RestrictedLockUtils.getProfileOrDeviceOwner(mContext, managedProfile);
+ protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(@NonNull UserHandle userHandle) {
+ return RestrictedLockUtils.getProfileOrDeviceOwner(mContext, userHandle);
+ }
+
+ @VisibleForTesting
+ @DevicePolicyManager.ContentProtectionPolicy
+ protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+ return ContentProtectionPreferenceUtils.getContentProtectionPolicy(mContext, userHandle);
}
}
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 568188f..f701323 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -22,11 +22,11 @@
import com.android.settings.spa.about.AboutPhonePageProvider
import com.android.settings.spa.app.AllAppListPageProvider
import com.android.settings.spa.app.AppsMainPageProvider
-import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
import com.android.settings.spa.app.appcompat.UserAspectRatioAppsPageProvider
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
import com.android.settings.spa.app.appinfo.CloneAppInfoSettingsProvider
import com.android.settings.spa.app.backgroundinstall.BackgroundInstalledAppsPageProvider
+import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
import com.android.settings.spa.app.specialaccess.AllFilesAccessAppListProvider
import com.android.settings.spa.app.specialaccess.BackupTasksAppsListProvider
diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
index 3b2d5ec..94e4a88 100644
--- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
@@ -16,6 +16,7 @@
package com.android.settings.spa.network
+import android.telephony.SubscriptionInfo
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
@@ -63,52 +64,55 @@
cancelAction
),
) {
- labelSimBody(onboardingService)
+ LabelSimBody(onboardingService)
}
}
@Composable
-private fun labelSimBody(onboardingService: SimOnboardingService) {
+private fun LabelSimBody(onboardingService: SimOnboardingService) {
Column(Modifier.padding(SettingsDimension.itemPadding)) {
SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
}
for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
- var titleSimName by remember {
- mutableStateOf(
- onboardingService.getSubscriptionInfoDisplayName(subInfo)
- )
- }
- var summaryNumber = subInfo.number
- // TODO using the SubscriptionUtil.getFormattedPhoneNumber
- val alertDialogPresenter = rememberAlertDialogPresenter(
- confirmButton = AlertDialogButton(
- stringResource(R.string.mobile_network_sim_name_rename)
- ) {
- onboardingService.addItemForRenaming(subInfo, titleSimName)
- },
- dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
- titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
- },
- title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
- text = {
- Text(summaryNumber,
- modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical))
- SettingsOutlinedTextField(
- value = titleSimName,
- label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
- enabled = true,
- shape = MaterialTheme.shapes.extraLarge
- ) {
- titleSimName = it
- }
- },
- )
- Preference(object : PreferenceModel {
- override val title = titleSimName
- override val summary: () -> String
- get() = { summaryNumber }
- override val onClick = alertDialogPresenter::open
- })
+ LabelSimPreference(onboardingService, subInfo)
}
-}
\ No newline at end of file
+}
+
+@Composable
+private fun LabelSimPreference(
+ onboardingService: SimOnboardingService,
+ subInfo: SubscriptionInfo,
+) {
+ var titleSimName by remember {
+ mutableStateOf(onboardingService.getSubscriptionInfoDisplayName(subInfo))
+ }
+ val phoneNumber = phoneNumber(subInfo)
+ val alertDialogPresenter = rememberAlertDialogPresenter(
+ confirmButton = AlertDialogButton(stringResource(R.string.mobile_network_sim_name_rename)) {
+ onboardingService.addItemForRenaming(subInfo, titleSimName)
+ },
+ dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
+ titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
+ },
+ title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
+ text = {
+ Text(
+ phoneNumber.value ?: "",
+ modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)
+ )
+ SettingsOutlinedTextField(
+ value = titleSimName,
+ label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
+ shape = MaterialTheme.shapes.extraLarge
+ ) {
+ titleSimName = it
+ }
+ },
+ )
+ Preference(object : PreferenceModel {
+ override val title = titleSimName
+ override val summary = { phoneNumber.value ?: "" }
+ override val onClick = alertDialogPresenter::open
+ })
+}
diff --git a/src/com/android/settings/spa/network/SimsSection.kt b/src/com/android/settings/spa/network/SimsSection.kt
index 9e4cf9f..0b638c4 100644
--- a/src/com/android/settings/spa/network/SimsSection.kt
+++ b/src/com/android/settings/spa/network/SimsSection.kt
@@ -25,6 +25,7 @@
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Add
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -58,9 +59,7 @@
val checked = remember(subInfo.subscriptionId) {
context.isSubscriptionEnabledFlow(subInfo.subscriptionId)
}.collectAsStateWithLifecycle(initialValue = false)
- val phoneNumber = remember(subInfo) {
- context.phoneNumberFlow(subInfo)
- }.collectAsStateWithLifecycle(initialValue = null)
+ val phoneNumber = phoneNumber(subInfo)
RestrictedTwoTargetSwitchPreference(
model = object : SwitchPreferenceModel {
override val title = subInfo.displayName.toString()
@@ -81,6 +80,14 @@
}
@Composable
+fun phoneNumber(subInfo: SubscriptionInfo): State<String?> {
+ val context = LocalContext.current
+ return remember(subInfo) {
+ context.phoneNumberFlow(subInfo)
+ }.collectAsStateWithLifecycle(initialValue = null)
+}
+
+@Composable
private fun AddSim() {
val context = LocalContext.current
if (remember { MobileNetworkUtils.showEuiccSettings(context) }) {
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 5d45cb2..39c77a1 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -72,6 +72,7 @@
import com.android.settings.R;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.Utils;
import com.android.settingslib.utils.ThreadUtils;
@@ -154,6 +155,10 @@
@VisibleForTesting static final int PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC = 0;
@VisibleForTesting static final int PRIVACY_SPINNER_INDEX_DEVICE_MAC = 1;
+ // Should be the same index value as wifi_dhcp_entries in arrays.xml
+ @VisibleForTesting static final int DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE = 0;
+ @VisibleForTesting static final int DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE = 1;
+
/* Phase2 methods supported by PEAP are limited */
private ArrayAdapter<CharSequence> mPhase2PeapAdapter;
/* Phase2 methods supported by TTLS are limited */
@@ -194,6 +199,7 @@
private Spinner mMeteredSettingsSpinner;
private Spinner mHiddenSettingsSpinner;
private Spinner mPrivacySettingsSpinner;
+ private Spinner mDhcpSettingsSpinner;
private TextView mHiddenWarningView;
private TextView mProxyHostView;
private TextView mProxyPortView;
@@ -291,6 +297,7 @@
mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
+ mDhcpSettingsSpinner = mView.findViewById(R.id.dhcp_settings);
if (mWifiManager.isConnectedMacRandomizationSupported()) {
View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
privacySettingsLayout.setVisibility(View.VISIBLE);
@@ -323,6 +330,12 @@
config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT
? PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC : PRIVACY_SPINNER_INDEX_DEVICE_MAC);
+ mDhcpSettingsSpinner.setSelection(
+ config.isSendDhcpHostnameEnabled()
+ ? DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE :
+ DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE
+ );
+
if (config.getIpConfiguration().getIpAssignment() == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
@@ -841,6 +854,12 @@
: WifiConfiguration.RANDOMIZATION_NONE;
}
+ if (mDhcpSettingsSpinner != null) {
+ config.setSendDhcpHostnameEnabled(WifiPrivacyPreferenceController.Companion
+ .translatePrefValueToSendDhcpHostnameEnabled(mDhcpSettingsSpinner
+ .getSelectedItemPosition()));
+ }
+
return config;
}
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index 7c9b1d1..1e40568 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -74,6 +74,7 @@
import com.android.settings.R;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.Utils;
@@ -208,6 +209,8 @@
private Spinner mHiddenSettingsSpinner;
@Nullable
private Spinner mPrivacySettingsSpinner;
+ @Nullable
+ private Spinner mDhcpSettingsSpinner;
private TextView mHiddenWarningView;
private TextView mProxyHostView;
private TextView mProxyPortView;
@@ -308,6 +311,7 @@
mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
if (!mHideMeteredAndPrivacy && mWifiManager.isConnectedMacRandomizationSupported()) {
mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
+ mDhcpSettingsSpinner = mView.findViewById(R.id.dhcp_settings);
mView.findViewById(R.id.privacy_settings_fields).setVisibility(View.VISIBLE);
}
mHiddenSettingsSpinner.setOnItemSelectedListener(this);
@@ -342,6 +346,13 @@
mPrivacySettingsSpinner.setSelection(prefMacValue);
}
+ if (mDhcpSettingsSpinner != null) {
+ final int prefDhcpValue = WifiPrivacyPreferenceController.Companion
+ .translateSendDhcpHostnameEnabledToPrefValue(
+ config.isSendDhcpHostnameEnabled());
+ mDhcpSettingsSpinner.setSelection(prefDhcpValue);
+ }
+
if (config.getIpConfiguration().getIpAssignment() == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
@@ -854,6 +865,12 @@
.getSelectedItemPosition());
}
+ if (mDhcpSettingsSpinner != null) {
+ config.setSendDhcpHostnameEnabled(WifiPrivacyPreferenceController.Companion
+ .translatePrefValueToSendDhcpHostnameEnabled(mDhcpSettingsSpinner
+ .getSelectedItemPosition()));
+ }
+
return config;
}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index e1774e3..06b3e5d 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -55,6 +55,7 @@
import com.android.settings.wifi.WifiDialog2;
import com.android.settings.wifi.WifiUtils;
import com.android.settings.wifi.details2.AddDevicePreferenceController2;
+import com.android.settings.wifi.details2.CertificateDetailsPreferenceController;
import com.android.settings.wifi.details2.WifiAutoConnectPreferenceController2;
import com.android.settings.wifi.details2.WifiDetailPreferenceController2;
import com.android.settings.wifi.details2.WifiMeteredPreferenceController2;
@@ -122,8 +123,12 @@
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
+ String wifiEntryKey = getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY);
+ setupNetworksDetailTracker();
use(WifiPrivacyPreferenceController.class)
- .setWifiEntryKey(getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY));
+ .setWifiEntryKey(wifiEntryKey);
+ use(CertificateDetailsPreferenceController.class)
+ .setWifiEntry(mNetworkDetailsTracker.getWifiEntry());
}
@Override
diff --git a/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt b/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt
new file mode 100644
index 0000000..8e1fa23
--- /dev/null
+++ b/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceController.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.details2
+
+import android.content.Context
+import android.content.DialogInterface
+import android.net.http.SslCertificate
+import android.security.KeyChain
+import android.security.keystore.KeyProperties
+import android.security.keystore2.AndroidKeyStoreLoadStoreParameter
+import android.util.Log
+import android.view.View
+import android.widget.ArrayAdapter
+import android.widget.LinearLayout
+import android.widget.Spinner
+import androidx.appcompat.app.AlertDialog
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.spa.preference.ComposePreferenceController
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.wifi.flags.Flags
+import com.android.wifitrackerlib.WifiEntry
+import java.security.KeyStore
+import java.security.cert.X509Certificate
+
+class CertificateDetailsPreferenceController(context: Context, preferenceKey: String) :
+ ComposePreferenceController(context, preferenceKey) {
+
+ private lateinit var wifiEntry: WifiEntry
+ lateinit var certificateAliases: String
+ lateinit var certX509: X509Certificate
+
+ fun setWifiEntry(entry: WifiEntry) {
+ wifiEntry = entry
+ }
+
+ override fun getAvailabilityStatus(): Int {
+ return if (Flags.androidVWifiApi() && getCertX509(wifiEntry)) AVAILABLE
+ else CONDITIONALLY_UNAVAILABLE
+ }
+
+ @Composable
+ override fun Content() {
+ CertificateDetails()
+ }
+
+ @Composable
+ fun CertificateDetails() {
+ val context = LocalContext.current
+ Preference(object : PreferenceModel {
+ override val title = stringResource(com.android.internal.R.string.ssl_certificate)
+ override val summary = { certificateAliases }
+ override val onClick: () -> Unit = { createCertificateDetailsDialog(context, certX509) }
+ })
+ }
+
+ private fun getCertX509(wifiEntry: WifiEntry): Boolean {
+ certificateAliases =
+ wifiEntry.wifiConfiguration?.enterpriseConfig?.caCertificateAliases?.get(0)
+ ?: return false
+ return try {
+ val keyStore = KeyStore.getInstance("AndroidKeyStore")
+ keyStore.load(AndroidKeyStoreLoadStoreParameter(KeyProperties.NAMESPACE_WIFI))
+ val cert = keyStore.getCertificate(certificateAliases)
+ certX509 = KeyChain.toCertificate(cert.encoded)
+ true
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to open Android Keystore.", e)
+ false
+ }
+ }
+
+ private fun createCertificateDetailsDialog(context: Context, certX509: X509Certificate) {
+ val listener =
+ DialogInterface.OnClickListener { dialog, id ->
+ dialog.dismiss()
+ }
+ val titles = ArrayList<String>()
+ val sslCert = SslCertificate(certX509)
+ titles.add(sslCert.issuedTo.cName)
+ val arrayAdapter = ArrayAdapter(
+ context,
+ android.R.layout.simple_spinner_item,
+ titles
+ )
+ arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ val spinner = Spinner(context)
+ spinner.setAdapter(arrayAdapter)
+
+ val certLayout = LinearLayout(context)
+ certLayout.orientation = LinearLayout.VERTICAL
+ // Prevent content overlapping with spinner
+ certLayout.setClipChildren(true)
+ certLayout.addView(spinner)
+
+ val view = sslCert.inflateCertificateView(context)
+ view.visibility = View.VISIBLE
+ certLayout.addView(view)
+ certLayout.visibility = View.VISIBLE
+
+ val dialog = AlertDialog.Builder(context)
+ .setView(certLayout)
+ .setTitle(com.android.internal.R.string.ssl_certificate)
+ .setPositiveButton(R.string.wifi_settings_ssid_block_button_close, null)
+ .setNegativeButton(R.string.trusted_credentials_remove_label, listener).create()
+ dialog.show()
+ dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false)
+ }
+
+ companion object {
+ const val TAG = "CertificateDetailsPreferenceController"
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
index 42741e3..2ed2e5a 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController.kt
@@ -63,4 +63,32 @@
}
})
}
+
+ companion object {
+ private const val PREF_SEND_DHCP_HOST_NAME_ENABLE = 0
+ private const val PREF_SEND_DHCP_HOST_NAME_DISABLE = 1
+
+ /**
+ * Returns preference index value.
+ *
+ * @param isSendDhcpHostnameEnabled determines whether device name can be sent.
+ * @return index value of preference
+ */
+ fun translateSendDhcpHostnameEnabledToPrefValue(
+ isSendDhcpHostnameEnabled: Boolean
+ ): Int {
+ return if (isSendDhcpHostnameEnabled) PREF_SEND_DHCP_HOST_NAME_ENABLE
+ else PREF_SEND_DHCP_HOST_NAME_DISABLE
+ }
+
+ /**
+ * Returns whether device name can be sent.
+ *
+ * @param prefDhcpRandomized is preference index value
+ * @return is send dhcp host name enabled
+ */
+ fun translatePrefValueToSendDhcpHostnameEnabled(prefDhcpRandomized: Int): Boolean {
+ return prefDhcpRandomized == PREF_SEND_DHCP_HOST_NAME_ENABLE
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 05e56ca..624a39a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -38,8 +38,12 @@
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.os.Build;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.Flags;
import androidx.fragment.app.Fragment;
import androidx.test.core.app.ApplicationProvider;
@@ -59,6 +63,8 @@
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager;
+import com.google.common.truth.BooleanSubject;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -103,6 +109,7 @@
@Rule
public final MockitoRule mocks = MockitoJUnit.rule();
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@Spy
private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
@@ -316,30 +323,39 @@
}
@Test
- public void onCreate_haveRegisterToSpecificUrisAndActions() {
+ @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void onCreate_flagDisabled_haveRegisterToSpecificUrisAndActions() {
setupFragment();
- ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
- Collection<ContentObserver> a11yButtonTargetsObservers =
- shadowContentResolver.getContentObservers(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
- Collection<ContentObserver> a11yShortcutTargetServiceObservers =
- shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ AccessibilitySettingsContentObserver.class).isTrue();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+ AccessibilitySettingsContentObserver.class).isTrue();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ AccessibilitySettingsContentObserver.class).isFalse();
List<BroadcastReceiver> broadcastReceivers =
shadowOf((Application) ApplicationProvider.getApplicationContext())
.getRegisteredReceivers()
.stream().map(wrapper -> wrapper.broadcastReceiver).toList();
- assertThat(
- a11yButtonTargetsObservers.stream()
- .anyMatch(contentObserver ->
- contentObserver instanceof AccessibilitySettingsContentObserver))
- .isTrue();
- assertThat(
- a11yShortcutTargetServiceObservers.stream()
- .anyMatch(contentObserver ->
- contentObserver instanceof AccessibilitySettingsContentObserver))
- .isTrue();
+ assertThat(broadcastReceivers.stream().anyMatch(
+ broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void onCreate_flagEnabled_haveRegisterToSpecificUrisAndActions() {
+ setupFragment();
+
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ AccessibilitySettingsContentObserver.class).isTrue();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+ AccessibilitySettingsContentObserver.class).isTrue();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ AccessibilitySettingsContentObserver.class).isTrue();
+ List<BroadcastReceiver> broadcastReceivers =
+ shadowOf((Application) ApplicationProvider.getApplicationContext())
+ .getRegisteredReceivers()
+ .stream().map(wrapper -> wrapper.broadcastReceiver).toList();
assertThat(broadcastReceivers.stream().anyMatch(
broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isTrue();
}
@@ -350,27 +366,16 @@
mActivityController.pause().stop().destroy();
- ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
- Collection<ContentObserver> a11yButtonTargetsObservers =
- shadowContentResolver.getContentObservers(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
- Collection<ContentObserver> a11yShortcutTargetServiceObservers =
- shadowContentResolver.getContentObservers(Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ AccessibilitySettingsContentObserver.class).isFalse();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+ AccessibilitySettingsContentObserver.class).isFalse();
+ assertUriObserversContainsClazz(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ AccessibilitySettingsContentObserver.class).isFalse();
List<BroadcastReceiver> broadcastReceivers =
shadowOf((Application) ApplicationProvider.getApplicationContext())
.getRegisteredReceivers()
.stream().map(wrapper -> wrapper.broadcastReceiver).toList();
- assertThat(
- a11yButtonTargetsObservers.stream()
- .anyMatch(contentObserver ->
- contentObserver instanceof AccessibilitySettingsContentObserver))
- .isFalse();
- assertThat(
- a11yShortcutTargetServiceObservers.stream()
- .anyMatch(contentObserver ->
- contentObserver instanceof AccessibilitySettingsContentObserver))
- .isFalse();
assertThat(broadcastReceivers.stream().anyMatch(
broadcastReceiver -> broadcastReceiver instanceof PackageMonitor)).isFalse();
}
@@ -491,4 +496,14 @@
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
enabled ? componentName.flattenToString() : "");
}
+
+ private BooleanSubject assertUriObserversContainsClazz(
+ String settingUri, Class<?> clazz) {
+ ShadowContentResolver shadowContentResolver = shadowOf(mContext.getContentResolver());
+ Collection<ContentObserver> observers =
+ shadowContentResolver.getContentObservers(
+ Settings.Secure.getUriFor(settingUri));
+
+ return assertThat(observers.stream().anyMatch(clazz::isInstance));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
index e14686e..db82be6 100644
--- a/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HearingDevicePairingFragmentTest.java
@@ -178,7 +178,7 @@
}
@Test
- public void handleLeScanResult_isNotAndroidCompatible_() {
+ public void handleLeScanResult_isNotAndroidCompatible_discoverServices() {
ScanResult scanResult = mock(ScanResult.class);
doReturn(mDevice).when(scanResult).getDevice();
doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
@@ -190,6 +190,19 @@
}
@Test
+ public void handleLeScanResult_alreadyBonded_doNothing() {
+ ScanResult scanResult = mock(ScanResult.class);
+ doReturn(mDevice).when(scanResult).getDevice();
+ doReturn(mCachedDevice).when(mCachedDeviceManager).findDevice(mDevice);
+ doReturn(BluetoothDevice.BOND_BONDED).when(mCachedDevice).getBondState();
+
+ mFragment.handleLeScanResult(scanResult);
+
+ verify(mFragment, never()).addDevice(mCachedDevice);
+ verify(mFragment, never()).discoverServices(mCachedDevice);
+ }
+
+ @Test
public void onProfileConnectionStateChanged_deviceConnected_inSelectedList_finish() {
doReturn(true).when(mCachedDevice).isConnected();
mFragment.mSelectedDeviceList.add(mDevice);
diff --git a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
index 2d5905e..832a313 100644
--- a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java
@@ -30,6 +30,7 @@
import static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.os.vibrator.Flags;
@@ -60,6 +61,9 @@
@Mock
private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private ContentResolver mContentResolver;
+
private Context mContext;
private Resources mResources;
private KeyboardVibrationTogglePreferenceController mController;
@@ -72,6 +76,7 @@
mContext = spy(ApplicationProvider.getApplicationContext());
mResources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(mResources);
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new KeyboardVibrationTogglePreferenceController(mContext, "preferenceKey");
mPreference = new SwitchPreference(mContext);
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
index 326a7a0..4501d27 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceControllerTest.java
@@ -16,7 +16,6 @@
package com.android.settings.accessibility;
-import static com.android.server.accessibility.Flags.enableMagnificationOneFingerPanningGesture;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
@@ -28,7 +27,10 @@
import static org.mockito.Mockito.verify;
import android.content.Context;
-import android.platform.test.flag.junit.SetFlagsRule;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import androidx.preference.PreferenceManager;
@@ -51,8 +53,9 @@
private static final String ONE_FINGER_PANNING_KEY =
Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED;
- @Rule public final SetFlagsRule mSetFlagsRule =
- new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
@@ -88,16 +91,16 @@
}
@Test
- public void getAvailabilityStatus_defaultState_disabled() {
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
+ public void getAvailabilityStatus_flagDisabled_disabled() {
int status = mController.getAvailabilityStatus();
assertThat(status).isEqualTo(DISABLED_FOR_USER);
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
public void getAvailabilityStatus_featureFlagEnabled_enabled() {
- enableFlag();
-
int status = mController.getAvailabilityStatus();
assertThat(status).isEqualTo(AVAILABLE);
@@ -158,9 +161,8 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
public void performClick_switchDefaultState_shouldReturnTrue() {
- enableFlag();
-
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(true);
@@ -168,13 +170,6 @@
assertThat(mSwitchPreference.isChecked()).isTrue();
}
- private void enableFlag() {
- mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE);
- assertThat(enableMagnificationOneFingerPanningGesture()).isTrue();
- // This ensures that preference change listeners are added correctly.
- mController.displayPreference(mScreen);
- }
-
private String enabledSummary() {
return mContext.getString(
R.string.accessibility_magnification_one_finger_panning_summary_on);
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index e963bd0..6fb1c3f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -24,6 +24,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -146,8 +147,9 @@
}
@Test
+ @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
@Config(shadows = {ShadowFragment.class})
- public void onResume_haveRegisterToSpecificUris() {
+ public void onResume_flagEnabled_haveRegisterToSpecificUris() {
mFragment.onAttach(mContext);
mFragment.onCreate(Bundle.EMPTY);
@@ -162,6 +164,36 @@
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)),
eq(false),
any(AccessibilitySettingsContentObserver.class));
+ verify(mContentResolver).registerContentObserver(
+ eq(Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS)),
+ eq(false),
+ any(AccessibilitySettingsContentObserver.class));
+ }
+
+ @Test
+ @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+ @Config(shadows = {ShadowFragment.class})
+ public void onResume_flagDisabled_haveRegisterToSpecificUris() {
+ mFragment.onAttach(mContext);
+ mFragment.onCreate(Bundle.EMPTY);
+
+ mFragment.onResume();
+
+ verify(mContentResolver).registerContentObserver(
+ eq(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)),
+ eq(false),
+ any(AccessibilitySettingsContentObserver.class));
+ verify(mContentResolver).registerContentObserver(
+ eq(Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)),
+ eq(false),
+ any(AccessibilitySettingsContentObserver.class));
+ verify(mContentResolver, never()).registerContentObserver(
+ eq(Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS)),
+ eq(false),
+ any(AccessibilitySettingsContentObserver.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
index 3d24fbb..1d85705 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
@@ -292,7 +292,39 @@
}
@Test
- public void onResume_haveRegisterToSpecificUris() {
+ @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void onResume_flagEnabled_haveRegisterToSpecificUris() {
+ ShadowContentResolver shadowContentResolver = Shadows.shadowOf(
+ mContext.getContentResolver());
+ Uri[] observedUri = new Uri[]{
+ Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE),
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS),
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED),
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED)
+ };
+ for (Uri uri : observedUri) {
+ // verify no observer registered before launching the fragment
+ assertThat(shadowContentResolver.getContentObservers(uri)).isEmpty();
+ }
+
+ mFragController.create(R.id.main_content, /* bundle= */ null).start().resume();
+
+ for (Uri uri : observedUri) {
+ Collection<ContentObserver> observers = shadowContentResolver.getContentObservers(uri);
+ assertThat(observers.size()).isEqualTo(1);
+ assertThat(observers.stream().findFirst().get()).isInstanceOf(
+ AccessibilitySettingsContentObserver.class);
+ }
+ }
+
+ @Test
+ @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void onResume_flagDisabled_haveRegisterToSpecificUris() {
ShadowContentResolver shadowContentResolver = Shadows.shadowOf(
mContext.getContentResolver());
Uri[] observedUri = new Uri[]{
@@ -317,6 +349,9 @@
assertThat(observers.stream().findFirst().get()).isInstanceOf(
AccessibilitySettingsContentObserver.class);
}
+ assertThat(shadowContentResolver.getContentObservers(
+ Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS))).hasSize(0);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
index 9559043..ee5f72e 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsUtilsTest.java
@@ -16,13 +16,20 @@
package com.android.settings.gestures;
+import static com.android.settings.gestures.OneHandedSettingsUtils.ONE_HANDED_MODE_TARGET_NAME;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
+import android.view.accessibility.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -30,7 +37,8 @@
@RunWith(RobolectricTestRunner.class)
public class OneHandedSettingsUtilsTest {
-
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final int OFF = 0;
private static final int ON = 1;
@@ -120,4 +128,66 @@
OneHandedSettingsUtils.OneHandedTimeout.LONG.getValue(), mCurrentUserId))
.isEqualTo(12);
}
+
+ @Test
+ public void getShortcutEnabled_a11yButtonVolumeKeysShortcutEnabled_returnTrue() {
+ setupShortcuts(
+ /* enableFab= */ true, /* enableVolumeKeys= */ true, /* enableQs=*/ false);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ public void getShortcutEnabled_a11yButtonShortcutEnabled_returnTrue() {
+ setupShortcuts(
+ /* enableFab= */ true, /* enableVolumeKeys= */ false, /* enableQs=*/ false);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ public void getShortcutEnabled_volumeKeysShortcutEnabled_returnTrue() {
+ setupShortcuts(
+ /* enableFab= */ false, /* enableVolumeKeys= */ true, /* enableQs=*/ false);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ public void getShortcutEnabled_noShortcutsEnabled_returnFalse() {
+ setupShortcuts(
+ /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ false);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void getShortcutEnabled_qsShortcutEnabled_returnTrue() {
+ setupShortcuts(
+ /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ true);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void getShortcutEnabled_flagDisabled_qsShortcutEnabled_returnFalse() {
+ setupShortcuts(
+ /* enableFab= */ false, /* enableVolumeKeys= */ false, /* enableQs=*/ true);
+
+ assertThat(OneHandedSettingsUtils.getShortcutEnabled(mContext)).isFalse();
+ }
+
+ private void setupShortcuts(boolean enableFab, boolean enableVolumeKeys, boolean enableQs) {
+ setupShortcut(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, enableFab);
+ setupShortcut(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, enableVolumeKeys);
+ setupShortcut(Settings.Secure.ACCESSIBILITY_QS_TARGETS, enableQs);
+ }
+
+ private void setupShortcut(String shortcutSettingKey, boolean enabled) {
+ final String targetName = enabled ? ONE_HANDED_MODE_TARGET_NAME : "";
+ Settings.Secure.putStringForUser(
+ mContext.getContentResolver(), shortcutSettingKey, targetName, mCurrentUserId);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
index 2595510..ae504be 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilRoboTest.java
@@ -16,11 +16,11 @@
package com.android.settings.network;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import static org.mockito.ArgumentMatchers.any;
import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
@@ -59,19 +59,19 @@
}
@Test
- public void isConnectedToWifiOrDifferentSubId_hasDataOnSubId2_returnTrue() {
+ public void isConnectedToMobileDataWithDifferentSubId_hasDataOnSubId2_returnTrue() {
addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_2);
- assertTrue(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+ assertTrue(SubscriptionUtil.isConnectedToMobileDataWithDifferentSubId(mContext, SUBID_1));
}
@Test
- public void isConnectedToWifiOrDifferentSubId_hasDataOnSubId1_returnFalse() {
+ public void isConnectedToMobileDataWithDifferentSubId_hasDataOnSubId1_returnFalse() {
addNetworkTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
mShadowSubscriptionManager.setActiveDataSubscriptionId(SUBID_1);
- assertFalse(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+ assertFalse(SubscriptionUtil.isConnectedToMobileDataWithDifferentSubId(mContext, SUBID_1));
}
private void addNetworkTransportType(int networkType) {
diff --git a/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java b/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
new file mode 100644
index 0000000..7ff18a5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.privatespace;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowAlertDialog.class})
+public class HidePrivateSpaceControllerTest {
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private static final String KEY = "private_space_hidden";
+ private static final String DETAIL_PAGE_KEY = "private_space_hidden_details";
+ private HidePrivateSpaceController mHidePrivateSpaceController;
+ private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
+ private FragmentActivity mActivity;
+
+ @Before
+ public void setUp() {
+ Context context = RuntimeEnvironment.application;
+ mHidePrivateSpaceController = new HidePrivateSpaceController(context, DETAIL_PAGE_KEY);
+ mHidePrivateSpaceSummaryController = new HidePrivateSpaceSummaryController(context, KEY);
+ mActivity = Robolectric.setupActivity(FragmentActivity.class);
+ }
+
+ /** Tests that when flags enabled the controller is available. */
+ @Test
+ public void getAvailabilityStatus_flagEnabled_returnsAvailable() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+ assertThat(mHidePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ /** Tests that when flags disabled the controller is unsupported. */
+ @Test
+ public void getAvailabilityStatus_flagDisabled_returnsUnsupported() {
+ mSetFlagsRule.disableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+
+ assertThat(mHidePrivateSpaceController.getAvailabilityStatus())
+ .isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ /** Tests that when hide toggle is enabled dialog is displayed. */
+ @Test
+ public void setChecked_enabled_showsDialog() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(true);
+
+ ShadowAlertDialog shadowAlertDialog = getShadowAlertDialog();
+ assertThat(shadowAlertDialog).isNotNull();
+ assertThat(shadowAlertDialog.getTitle().toString())
+ .isEqualTo(mActivity.getString(R.string.private_space_hide_dialog_title));
+ assertThat(shadowAlertDialog.getMessage().toString())
+ .isEqualTo(mActivity.getString(R.string.private_space_hide_dialog_message));
+ }
+
+ /** Tests that when hide toggle is disabled dialog is not displayed. */
+ @Test
+ public void setChecked_disabled_NoDialogShown() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(false);
+
+ ShadowAlertDialog shadowAlertDialog = getShadowAlertDialog();
+ assertThat(shadowAlertDialog).isNull();
+ }
+
+ /** Tests that when hide toggle is enabled then isChecked returns true. */
+ @Test
+ public void setChecked_enabled_isCheckedIsTrue() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(true);
+ assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
+ }
+
+ /** Tests that when hide toggle is disabled then isChecked returns false. */
+ @Test
+ public void setChecked_disabled_isCheckedIsFalse() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(false);
+ assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
+ }
+
+ /** Tests that hide preference summary displays On when toggle is enabled. */
+ @Test
+ public void setChecked_enable_summaryShouldDisplayOn() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(true);
+
+ assertThat(mHidePrivateSpaceSummaryController.getSummary().toString()).isEqualTo("On");
+ }
+
+ /** Tests that hide preference summary displays Off when toggle is disabled. */
+ @Test
+ public void setChecked_disable_summaryShouldDisplayOff() {
+ mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
+ mHidePrivateSpaceController.setChecked(false);
+
+ assertThat(mHidePrivateSpaceSummaryController.getSummary().toString()).isEqualTo("Off");
+ }
+
+ private ShadowAlertDialog getShadowAlertDialog() {
+ ShadowApplication shadowApplication =
+ Shadow.extract(ApplicationProvider.getApplicationContext());
+ ShadowAlertDialog shadowAlertDialog = shadowApplication.getLatestAlertDialog();
+ return shadowAlertDialog;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
index 9b49434..d6f9abd 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionPreferenceUtilsTest.java
@@ -16,47 +16,73 @@
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
import static com.android.internal.R.string.config_defaultContentProtectionService;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.DeviceConfig;
import android.view.contentcapture.ContentCaptureManager;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.After;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
-@Config(
- shadows = {
- ShadowDeviceConfig.class,
- })
+@Config(shadows = {ShadowDeviceConfig.class})
public class ContentProtectionPreferenceUtilsTest {
+
private static final String PACKAGE_NAME = "com.test.package";
private static final ComponentName COMPONENT_NAME =
new ComponentName(PACKAGE_NAME, "TestClass");
- private String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
+ private static final UserHandle USER_HANDLE = UserHandle.of(111);
+
+ private static final int PROCESS_USER_ID = 222;
+
+ private final String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
+
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock private Context mMockContext;
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- }
+ @Mock private Context mMockUserContext;
+
+ @Mock private UserManager mMockUserManager;
+
+ @Mock private DevicePolicyManager mMockDevicePolicyManager;
+
+ @Mock private UserInfo mMockUserInfo;
@After
public void tearDown() {
@@ -134,7 +160,6 @@
assertThat(ContentProtectionPreferenceUtils.isAvailable(mMockContext)).isFalse();
}
-
@Test
public void isAvailable_bothDisabled_false() {
DeviceConfig.setProperty(
@@ -145,4 +170,113 @@
assertThat(ContentProtectionPreferenceUtils.isAvailable(mMockContext)).isFalse();
}
+
+ @Test
+ public void getManagedProfile_noProfiles() {
+ when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+ when(mMockUserManager.getUserProfiles()).thenReturn(List.of());
+
+ UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+ assertThat(actual).isNull();
+ }
+
+ @Test
+ public void getManagedProfile_notManaged() {
+ when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+ when(mMockUserManager.getUserProfiles()).thenReturn(List.of(USER_HANDLE));
+ when(mMockUserManager.getProcessUserId()).thenReturn(PROCESS_USER_ID);
+ when(mMockUserManager.getUserInfo(USER_HANDLE.getIdentifier())).thenReturn(mMockUserInfo);
+
+ UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+ assertThat(actual).isNull();
+ verify(mMockUserInfo).isManagedProfile();
+ }
+
+ @Test
+ public void getManagedProfile_managed() {
+ when(mMockContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
+ when(mMockUserManager.getUserProfiles()).thenReturn(List.of(USER_HANDLE));
+ when(mMockUserManager.getProcessUserId()).thenReturn(PROCESS_USER_ID);
+ when(mMockUserManager.getUserInfo(USER_HANDLE.getIdentifier())).thenReturn(mMockUserInfo);
+ when(mMockUserInfo.isManagedProfile()).thenReturn(true);
+
+ UserHandle actual = ContentProtectionPreferenceUtils.getManagedProfile(mMockContext);
+
+ assertThat(actual).isEqualTo(USER_HANDLE);
+ }
+
+ @Test
+ public void getContentProtectionPolicy_flagDisabled_managedProfileNull() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+
+ int actual =
+ ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+ mMockContext, /* managedProfile= */ null);
+
+ assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_DISABLED);
+ }
+
+ @Test
+ public void getContentProtectionPolicy_flagDisabled_managedProfileNotNull() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+
+ int actual =
+ ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+ mMockContext, USER_HANDLE);
+
+ assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_DISABLED);
+ }
+
+ @Test
+ public void getContentProtectionPolicy_flagEnabled_managedProfileNull() throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ when(mMockContext.getSystemService(DevicePolicyManager.class))
+ .thenReturn(mMockDevicePolicyManager);
+ when(mMockDevicePolicyManager.getContentProtectionPolicy(/* admin= */ null))
+ .thenReturn(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+
+ int actual =
+ ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+ mMockContext, /* managedProfile= */ null);
+
+ assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+ verify(mMockContext, never()).createPackageContextAsUser(anyString(), anyInt(), any());
+ }
+
+ @Test
+ public void getContentProtectionPolicy_flagEnabled_managedProfileNotNull() throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, /* flags= */ 0, USER_HANDLE))
+ .thenReturn(mMockUserContext);
+ when(mMockUserContext.getSystemService(DevicePolicyManager.class))
+ .thenReturn(mMockDevicePolicyManager);
+ when(mMockDevicePolicyManager.getContentProtectionPolicy(/* admin= */ null))
+ .thenReturn(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+
+ int actual =
+ ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+ mMockContext, USER_HANDLE);
+
+ assertThat(actual).isEqualTo(DevicePolicyManager.CONTENT_PROTECTION_ENABLED);
+ }
+
+ @Test
+ public void getContentProtectionPolicy_flagEnabled_managedProfileNotNull_nameNotFound()
+ throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
+ when(mMockContext.createPackageContextAsUser(PACKAGE_NAME, /* flags= */ 0, USER_HANDLE))
+ .thenThrow(new PackageManager.NameNotFoundException());
+
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ContentProtectionPreferenceUtils.getContentProtectionPolicy(
+ mMockContext, USER_HANDLE));
+
+ verify(mMockContext, never()).getSystemService(DevicePolicyManager.class);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
index 50e9a5c..075ac6c 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionTogglePreferenceControllerTest.java
@@ -15,20 +15,25 @@
*/
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.security.ContentProtectionTogglePreferenceController.KEY_CONTENT_PROTECTION_PREFERENCE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.os.UserHandle;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
+import androidx.annotation.Nullable;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
@@ -42,37 +47,40 @@
import org.junit.Test;
import org.junit.runner.RunWith;
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 = {
- ShadowUtils.class,
- })
+@Config(shadows = {ShadowUtils.class})
public class ContentProtectionTogglePreferenceControllerTest {
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
- @Mock private PreferenceScreen mMockScreen;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
- private RestrictedLockUtils.EnforcedAdmin mAdmin;
- private SettingsMainSwitchPreference mSwitchPreference;
private final Context mContext = ApplicationProvider.getApplicationContext();
- private ContentProtectionTogglePreferenceController mController;
+
+ @Mock private PreferenceScreen mMockPreferenceScreen;
+
+ @Mock private SettingsMainSwitchPreference mMockSwitchPreference;
+
+ @Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+ @DevicePolicyManager.ContentProtectionPolicy
+ private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
+ private TestContentProtectionTogglePreferenceController mController;
+
private int mSettingBackupValue;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
mController = new TestContentProtectionTogglePreferenceController();
- mSwitchPreference = new SettingsMainSwitchPreference(mContext);
- when(mMockScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mSwitchPreference);
+ SettingsMainSwitchPreference switchPreference = new SettingsMainSwitchPreference(mContext);
+ when(mMockPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(switchPreference);
mSettingBackupValue = getContentProtectionGlobalSetting();
Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 0);
}
@@ -87,89 +95,223 @@
}
@Test
- public void isAvailable_alwaysAvailable() {
+ public void constructor_flagDisabled_doesNotFetchData() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(0);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+ }
+
+ @Test
+ public void constructor_flagEnabled_fetchesData() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(1);
+ }
+
+ @Test
+ public void getAvailabilityStatus_available() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void displayPreference() {
- setUpFullyManagedMode();
- SettingsMainSwitchPreference mockSwitchPreference =
- mock(SettingsMainSwitchPreference.class);
- when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
- mController = new TestContentProtectionTogglePreferenceController();
- mController.displayPreference(mMockScreen);
-
- assertThat(mockSwitchPreference).isNotNull();
- }
-
- @Test
- public void updateState_notFullyManagedMode_enabled() {
- SettingsMainSwitchPreference mockSwitchPreference =
- mock(SettingsMainSwitchPreference.class);
- when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
- mController = new TestContentProtectionTogglePreferenceController();
- mController.displayPreference(mMockScreen);
- mController.updateState(mockSwitchPreference);
-
- verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
- }
-
- @Test
- public void updateState_fullyManagedMode_disabled() {
- setUpFullyManagedMode();
- SettingsMainSwitchPreference mockSwitchPreference =
- mock(SettingsMainSwitchPreference.class);
- when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
- mController = new TestContentProtectionTogglePreferenceController();
- mController.displayPreference(mMockScreen);
- mController.updateState(mockSwitchPreference);
-
- verify(mockSwitchPreference).setDisabledByAdmin(mAdmin);
- }
-
- @Test
- public void isChecked_settingTurnOn() {
+ public void isChecked_noEnforcedAdmin_readsSettingsTrue() {
Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
assertThat(mController.isChecked()).isTrue();
}
@Test
- public void isChecked_fullyManagedMode_settingTurnOff() {
- setUpFullyManagedMode();
- Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
- SettingsMainSwitchPreference mockSwitchPreference =
- mock(SettingsMainSwitchPreference.class);
- when(mMockScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
-
- mController = new TestContentProtectionTogglePreferenceController();
- mController.displayPreference(mMockScreen);
- mController.updateState(mockSwitchPreference);
-
- assertThat(mController.isChecked()).isFalse();
- }
-
- @Test
- public void isChecked_settingTurnOff() {
+ public void isChecked_noEnforcedAdmin_readsSettingsFalse() {
Settings.Global.putInt(
mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
assertThat(mController.isChecked()).isFalse();
- assertThat(getContentProtectionGlobalSetting()).isEqualTo(-1);
}
@Test
- public void isChecked_settingDefaultOn() {
+ public void isChecked_noEnforcedAdmin_readsSettingsDefaultTrue() {
assertThat(mController.isChecked()).isTrue();
- assertThat(getContentProtectionGlobalSetting()).isEqualTo(0);
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagDisabled_false() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+ setupForUpdateState();
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagEnabled_policyDisabled_false() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagEnabled_policyEnabled_true() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+ Settings.Global.putInt(
+ mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsTrue() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ Settings.Global.putInt(mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 1);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsFalse() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ Settings.Global.putInt(
+ mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, -1);
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_enforcedAdmin_flagEnabled_policyNotControlled_readsSettingsDefaultTrue() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ mController = new TestContentProtectionTogglePreferenceController();
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void displayPreference() {
+ setupForDisplayPreference();
+
+ mController.displayPreference(mMockPreferenceScreen);
+
+ verify(mMockSwitchPreference).addOnSwitchChangeListener(mController);
+ }
+
+ @Test
+ public void updateState_flagDisabled_noEnforcedAdmin() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_flagDisabled_enforcedAdmin() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ }
+
+ @Test
+ public void updateState_flagEnabled_noEnforcedAdmin_policyDisabled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_flagEnabled_noEnforcedAdmin_policyEnabled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_flagEnabled_noEnforcedAdmin_policyNotControlled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_flagEnabled_enforcedAdmin_policyDisabled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ }
+
+ @Test
+ public void updateState_flagEnabled_enforcedAdmin_policyEnabled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ }
+
+ @Test
+ public void updateState_flagEnabled_enforcedAdmin_policyNotControlled() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ setupForUpdateState();
+
+ mController.updateState(mMockSwitchPreference);
+
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
}
@Test
@@ -193,20 +335,49 @@
mContext.getContentResolver(), KEY_CONTENT_PROTECTION_PREFERENCE, 0);
}
- private void setUpFullyManagedMode() {
- mAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ private void setupForDisplayPreference() {
+ when(mMockPreferenceScreen.findPreference(any())).thenReturn(mMockSwitchPreference);
+ when(mMockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ mController = new TestContentProtectionTogglePreferenceController();
+ }
+
+ private void setupForUpdateState() {
+ setupForDisplayPreference();
+ mController.displayPreference(mMockPreferenceScreen);
}
private class TestContentProtectionTogglePreferenceController
extends ContentProtectionTogglePreferenceController {
+ public int mCounterGetManagedProfile;
+
+ public int mCounterGetEnforcedAdmin;
+
+ public int mCounterGetContentProtectionPolicy;
+
TestContentProtectionTogglePreferenceController() {
super(ContentProtectionTogglePreferenceControllerTest.this.mContext, "key");
}
@Override
+ @Nullable
+ protected UserHandle getManagedProfile() {
+ mCounterGetManagedProfile++;
+ return null;
+ }
+
+ @Override
+ @Nullable
protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin() {
- return mAdmin;
+ mCounterGetEnforcedAdmin++;
+ return mEnforcedAdmin;
+ }
+
+ @Override
+ @DevicePolicyManager.ContentProtectionPolicy
+ protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+ mCounterGetContentProtectionPolicy++;
+ return mContentProtectionPolicy;
}
}
}
diff --git a/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java b/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
index 8d35e4d..3d367de 100644
--- a/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/ContentProtectionWorkSwitchControllerTest.java
@@ -16,19 +16,22 @@
package com.android.settings.security;
+import static android.view.contentprotection.flags.Flags.FLAG_MANAGE_DEVICE_POLICY_ENABLED;
+
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -39,55 +42,169 @@
import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class ContentProtectionWorkSwitchControllerTest {
+
private static final UserHandle TEST_USER_HANDLE = UserHandle.of(10);
+ @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock private PreferenceScreen mMockPreferenceScreen;
- private ContentProtectionWorkSwitchController mController;
- private UserHandle mManagedProfileUserHandle;
- private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+ @Mock private RestrictedSwitchPreference mMockSwitchPreference;
+
+ @Nullable private UserHandle mManagedProfileUserHandle;
+
+ @Nullable private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+ @DevicePolicyManager.ContentProtectionPolicy
+ private int mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+
+ private TestContentProtectionWorkSwitchController mController;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
mController = new TestContentProtectionWorkSwitchController();
}
@Test
- public void isAvailable_managedProfile_available() {
+ public void constructor_flagDisabled_doesNotFetchData() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(0);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+ }
+
+ @Test
+ public void constructor_flagEnabled_fetchesManagedProfile() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(0);
+ }
+
+ @Test
+ public void constructor_flagEnabled_withManagedProfile_fetchesPolicy() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ assertThat(mController.mCounterGetContentProtectionPolicy).isEqualTo(1);
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagDisabled_managedProfile_available() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mController = new TestContentProtectionWorkSwitchController();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void isAvailable_noManagedProfile_notAvailable() {
- mManagedProfileUserHandle = null;
+ public void getAvailabilityStatus_flagDisabled_noManagedProfile_unavailable() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionWorkSwitchController();
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
assertThat(mController.isAvailable()).isFalse();
}
@Test
- public void isChecked_noManagedProfile_alwaysOff() {
- mManagedProfileUserHandle = null;
+ public void getAvailabilityStatus_flagEnabled_managedProfile_policyDisabled_available() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagEnabled_managedProfile_policyEnabled_available() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagEnabled_managedProfile_policyNotControlled_unavailable() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void getAvailabilityStatus_flagEnabled_noManagedProfile_unavailable() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isChecked_flagDisabled_false() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mController = new TestContentProtectionWorkSwitchController();
assertThat(mController.isChecked()).isFalse();
}
@Test
- public void isChecked_managedProfile_alwaysOff() {
+ public void isChecked_flagEnabled_policyEnabled_true() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_flagEnabled_policyDisabled_false() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
+ mController = new TestContentProtectionWorkSwitchController();
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_flagEnabled_policyNotControlled_false() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
+ mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY;
+ mController = new TestContentProtectionWorkSwitchController();
assertThat(mController.isChecked()).isFalse();
}
@@ -99,50 +216,72 @@
}
@Test
- public void displayPreference_managedProfile_disabled() {
+ public void displayPreference_flagDisabled_managedProfile_disabledByAdmin() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
mManagedProfileUserHandle = TEST_USER_HANDLE;
mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
- RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
- when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ setupForDisplayPreference();
mController.displayPreference(mMockPreferenceScreen);
- assertThat(mController.isAvailable()).isTrue();
- verify(mockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(3);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
}
@Test
- public void displayPreference_noManagedProfile_notDisabled() {
- mManagedProfileUserHandle = null;
+ public void displayPreference_flagDisabled_noManagedProfile_notDisabledByAdmin() {
+ mSetFlagsRule.disableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ setupForDisplayPreference();
+
+ mController.displayPreference(mMockPreferenceScreen);
+
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(3);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ }
+
+ @Test
+ public void displayPreference_flagEnabled_managedProfile_disabledByAdmin() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ mManagedProfileUserHandle = TEST_USER_HANDLE;
mEnforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
- RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
- when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ setupForDisplayPreference();
mController.displayPreference(mMockPreferenceScreen);
- assertThat(mController.isAvailable()).isFalse();
- verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
+ verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
}
@Test
- public void displayPreference_noEnforcedAdmin_notDisabled() {
- mManagedProfileUserHandle = null;
- mEnforcedAdmin = null;
- RestrictedSwitchPreference mockSwitchPreference = mock(RestrictedSwitchPreference.class);
- when(mMockPreferenceScreen.findPreference(any())).thenReturn(mockSwitchPreference);
- when(mockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ public void displayPreference_flagEnabled_noManagedProfile_notDisabledByAdmin() {
+ mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
+ setupForDisplayPreference();
mController.displayPreference(mMockPreferenceScreen);
- assertThat(mController.isAvailable()).isFalse();
- verify(mockSwitchPreference, never()).setDisabledByAdmin(any());
+ verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
+ assertThat(mController.mCounterGetManagedProfile).isEqualTo(1);
+ assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(0);
+ }
+
+ private void setupForDisplayPreference() {
+ when(mMockPreferenceScreen.findPreference(any())).thenReturn(mMockSwitchPreference);
+ when(mMockSwitchPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ mController = new TestContentProtectionWorkSwitchController();
}
private class TestContentProtectionWorkSwitchController
extends ContentProtectionWorkSwitchController {
+ public int mCounterGetManagedProfile;
+
+ public int mCounterGetEnforcedAdmin;
+
+ public int mCounterGetContentProtectionPolicy;
+
TestContentProtectionWorkSwitchController() {
super(ContentProtectionWorkSwitchControllerTest.this.mContext, "key");
}
@@ -150,14 +289,23 @@
@Override
@Nullable
protected UserHandle getManagedProfile() {
+ mCounterGetManagedProfile++;
return mManagedProfileUserHandle;
}
@Override
@Nullable
protected RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin(
- @NonNull UserHandle managedProfile) {
+ @NonNull UserHandle userHandle) {
+ mCounterGetEnforcedAdmin++;
return mEnforcedAdmin;
}
+
+ @Override
+ @DevicePolicyManager.ContentProtectionPolicy
+ protected int getContentProtectionPolicy(@Nullable UserHandle userHandle) {
+ mCounterGetContentProtectionPolicy++;
+ return mContentProtectionPolicy;
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
index 4fcc93d..7d96496 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java
@@ -16,6 +16,7 @@
package com.android.settings.wifi;
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE;
import static com.android.settings.wifi.WifiConfigController2.DEFAULT_ANONYMOUS_ID;
import static com.android.settings.wifi.WifiConfigController2.WIFI_EAP_METHOD_SIM;
@@ -56,6 +57,7 @@
import com.android.settings.R;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.utils.AndroidKeystoreAliasLoader;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2;
import com.android.wifitrackerlib.WifiEntry;
@@ -513,6 +515,42 @@
}
@Test
+ public void loadSavedDhcpValue_true() {
+ checkSavedDhcpValue(true);
+ }
+
+ @Test
+ public void loadSavedDhcpValue_false() {
+ checkSavedDhcpValue(false);
+ }
+
+ private void checkSavedDhcpValue(boolean dhcpValue) {
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class);
+ when(mockWifiConfig.getIpConfiguration()).thenReturn(mock(IpConfiguration.class));
+ when(mockWifiConfig.isSendDhcpHostnameEnabled()).thenReturn(dhcpValue);
+ when(mWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfig);
+ createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
+ final Spinner dhcpSetting = mView.findViewById(R.id.dhcp_settings);
+ final int expectedPrefValue =
+ WifiPrivacyPreferenceController.Companion
+ .translateSendDhcpHostnameEnabledToPrefValue(dhcpValue);
+
+ assertThat(dhcpSetting.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(dhcpSetting.getSelectedItemPosition()).isEqualTo(expectedPrefValue);
+ }
+
+ @Test
+ public void saveDhcpValue_changedToFalse() {
+ createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
+ final Spinner privacySetting = mView.findViewById(R.id.dhcp_settings);
+ privacySetting.setSelection(DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+
+ WifiConfiguration config = mController.getConfig();
+ assertThat(config.isSendDhcpHostnameEnabled()).isEqualTo(false);
+ }
+
+ @Test
public void replaceTtsString_whenTargetMatched_shouldSuccess() {
createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
final CharSequence[] display = {"PEAP", "AKA1", "AKA2'"};
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index 2ff4596..d80464d 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -18,6 +18,8 @@
import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_DEVICE_MAC;
import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC;
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE;
+import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE;
import static com.google.common.truth.Truth.assertThat;
@@ -451,6 +453,41 @@
}
@Test
+ public void loadSavedDhcpValue_true() {
+ checkSavedDhcpValue(true);
+ }
+
+ @Test
+ public void loadSavedDhcpValue_false() {
+ checkSavedDhcpValue(false);
+ }
+
+ private void checkSavedDhcpValue(boolean dhcpValue) {
+ when(mAccessPoint.isSaved()).thenReturn(true);
+ final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class);
+ when(mockWifiConfig.getIpConfiguration()).thenReturn(mock(IpConfiguration.class));
+ when(mockWifiConfig.isSendDhcpHostnameEnabled()).thenReturn(dhcpValue);
+ when(mAccessPoint.getConfig()).thenReturn(mockWifiConfig);
+ mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint,
+ WifiConfigUiBase.MODE_CONNECT);
+ final Spinner dhcpSetting = mView.findViewById(R.id.dhcp_settings);
+
+ assertThat(dhcpSetting.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(dhcpSetting.getSelectedItemPosition()).isEqualTo(
+ dhcpValue ? DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE :
+ DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+ }
+
+ @Test
+ public void saveDhcpValue_changedToFalse() {
+ final Spinner privacySetting = mView.findViewById(R.id.dhcp_settings);
+ privacySetting.setSelection(DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE);
+
+ WifiConfiguration config = mController.getConfig();
+ assertThat(config.isSendDhcpHostnameEnabled()).isEqualTo(false);
+ }
+
+ @Test
public void replaceTtsString_whenTargetMatched_shouldSuccess() {
final CharSequence[] display = {"PEAP", "AKA1", "AKA2'"};
final CharSequence[] target = {"AKA1", "AKA2'"};
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
index 3cd2002..9d97fbf 100644
--- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
@@ -50,7 +50,7 @@
import platform.test.screenshot.DeviceEmulationSpec
import platform.test.screenshot.DisplaySpec
import platform.test.screenshot.FragmentScreenshotTestRule
-import platform.test.screenshot.GoldenImagePathManager
+import platform.test.screenshot.GoldenPathManager
import platform.test.screenshot.matchers.PixelPerfectMatcher
class Injector(step: FingerprintNavigationStep.UiStep) {
@@ -154,7 +154,7 @@
fun BiometricFragmentScreenShotRule() =
FragmentScreenshotTestRule(
DeviceEmulationSpec.forDisplays(Phone).first(),
- GoldenImagePathManager(
+ GoldenPathManager(
InstrumentationRegistry.getInstrumentation().context,
InstrumentationRegistry.getInstrumentation().targetContext.filesDir.absolutePath +
screenshotPath,
diff --git a/tests/spa_unit/AndroidManifest.xml b/tests/spa_unit/AndroidManifest.xml
index 51ac1b7..d234b5d 100644
--- a/tests/spa_unit/AndroidManifest.xml
+++ b/tests/spa_unit/AndroidManifest.xml
@@ -19,11 +19,14 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.settings.tests.spa_unit">
+ <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+ <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
<uses-permission android:name="android.permission.MANAGE_APPOPS" />
+ <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+ <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
- <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
- <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
<application android:debuggable="true">
<provider android:name="com.android.settings.slices.SettingsSliceProvider"
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt
new file mode 100644
index 0000000..4137de4
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.AccessNetworkConstants
+import android.telephony.NetworkRegistrationInfo
+import android.telephony.ServiceState
+import android.telephony.TelephonyManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.network.telephony.scan.NetworkScanRepositoryTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class NetworkSelectRepositoryTest {
+
+ private val mockServiceState = mock<ServiceState> {
+ on {
+ getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ )
+ } doReturn NetworkRegistrationInfos
+ }
+
+ private val mockTelephonyManager = mock<TelephonyManager> {
+ on { createForSubscriptionId(SUB_ID) } doReturn mock
+ on { dataState } doReturn TelephonyManager.DATA_CONNECTED
+ on { serviceState } doReturn mockServiceState
+ }
+
+ private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+ on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+ }
+
+ private val repository = NetworkSelectRepository(context, SUB_ID)
+
+ @Test
+ fun getNetworkRegistrationInfo_notConnected_returnNull() {
+ mockTelephonyManager.stub {
+ on { dataState } doReturn TelephonyManager.DATA_DISCONNECTED
+ }
+
+ val info = repository.getNetworkRegistrationInfo()
+
+ assertThat(info).isNull()
+ }
+
+ @Test
+ fun getNetworkRegistrationInfo_nullServiceState_returnNull() {
+ mockTelephonyManager.stub {
+ on { serviceState } doReturn null
+ }
+
+ val info = repository.getNetworkRegistrationInfo()
+
+ assertThat(info).isNull()
+ }
+
+ @Test
+ fun getNetworkRegistrationInfo_emptyNetworkList_returnNull() {
+ mockServiceState.stub {
+ on {
+ getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ )
+ } doReturn emptyList()
+ }
+
+ val info = repository.getNetworkRegistrationInfo()
+
+ assertThat(info).isNull()
+ }
+
+ @Test
+ fun getNetworkRegistrationInfo_hasNetworkList_returnInfo() {
+ mockServiceState.stub {
+ on {
+ getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ )
+ } doReturn NetworkRegistrationInfos
+ }
+ mockTelephonyManager.stub {
+ on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN)
+ }
+
+ val info = repository.getNetworkRegistrationInfo()
+
+ assertThat(info).isEqualTo(
+ NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo(
+ networkList = NetworkRegistrationInfos,
+ forbiddenPlmns = listOf(FORBIDDEN_PLMN),
+ )
+ )
+ }
+
+ private companion object {
+ const val SUB_ID = 1
+ val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build())
+ const val FORBIDDEN_PLMN = "Forbidden PLMN"
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt
new file mode 100644
index 0000000..1499374
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/wifi/details2/CertificateDetailsPreferenceControllerTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.details2
+
+import android.content.Context
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import java.security.cert.X509Certificate
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class CertificateDetailsPreferenceControllerTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ private val mockCertX509 = mock<X509Certificate> {}
+
+ private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+ doNothing().whenever(mock).startActivity(any())
+ }
+
+ private val controller = CertificateDetailsPreferenceController(context, TEST_KEY)
+
+ @Before
+ fun setUp() {
+ controller.certificateAliases = MOCK_CA
+ controller.certX509 = mockCertX509
+ }
+
+ @Test
+ fun title_isDisplayed() {
+ composeTestRule.setContent {
+ CompositionLocalProvider(LocalContext provides context) {
+ controller.Content()
+ }
+ }
+
+ composeTestRule.onNodeWithText(context.getString(com.android.internal.R.string.ssl_certificate))
+ .assertIsDisplayed()
+ }
+
+ private companion object {
+ const val TEST_KEY = "test_key"
+ const val MOCK_CA = "mock_ca"
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt b/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
index 644095d..976096c 100644
--- a/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
+++ b/tests/unit/src/com/android/settings/conecteddevice/threadnetwork/ThreadNetworkPreferenceControllerTest.kt
@@ -33,13 +33,13 @@
import androidx.preference.SwitchPreference
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.net.thread.platform.flags.Flags
import com.android.settings.R
import com.android.settings.core.BasePreferenceController.AVAILABLE
import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
import com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING
import com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE
import com.android.settings.connecteddevice.threadnetwork.ThreadNetworkPreferenceController.BaseThreadNetworkController
+import com.android.settings.flags.Flags
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
@@ -68,7 +68,7 @@
@Before
fun setUp() {
- mSetFlagsRule.enableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
+ mSetFlagsRule.enableFlags(Flags.FLAG_THREAD_SETTINGS_ENABLED)
context = spy(ApplicationProvider.getApplicationContext<Context>())
executor = ContextCompat.getMainExecutor(context)
fakeThreadNetworkController = FakeThreadNetworkController(executor)
@@ -96,7 +96,7 @@
@Test
fun availabilityStatus_flagDisabled_returnsConditionallyUnavailable() {
- mSetFlagsRule.disableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
+ mSetFlagsRule.disableFlags(Flags.FLAG_THREAD_SETTINGS_ENABLED)
assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE)
}
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 3b9ac9d..6c946e5 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -65,6 +66,9 @@
private static final CharSequence CARRIER_1 = "carrier1";
private static final CharSequence CARRIER_1_SPACE = " carrier1 ";
private static final CharSequence CARRIER_2 = "carrier2";
+ private static final int RAC_CARRIER_ID = 1;
+ private static final int NO_RAC_CARRIER_ID = 2;
+ private static final int[] CARRIERS_THAT_USE_RAC = {RAC_CARRIER_ID};
private Context mContext;
private NetworkCapabilities mNetworkCapabilities;
@@ -81,6 +85,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getResources()).thenReturn(mResources);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubMgr);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelMgr);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
@@ -109,6 +114,40 @@
assertThat(subs).hasSize(1);
}
+ @Test
+ public void hasSubscriptionWithRacCarrier_containsRac_returnTrue() {
+ when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+ final SubscriptionInfo info = mock(SubscriptionInfo.class);
+ when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
+ when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+
+ assertTrue(SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext));
+ }
+
+ @Test
+ public void hasSubscriptionWithRacCarrier_doesNotContainsRac_returnFalse() {
+ when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+ final SubscriptionInfo info = mock(SubscriptionInfo.class);
+ when(info.getCarrierId()).thenReturn(NO_RAC_CARRIER_ID);
+ when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+
+ assertFalse(SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext));
+ }
+
+ @Test
+ public void isCarrierRac_returnTrue() {
+ when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+
+ assertTrue(SubscriptionUtil.isCarrierRac(mContext, RAC_CARRIER_ID));
+ }
+
+ @Test
+ public void isCarrierRac_returnFalse() {
+ when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+
+ assertFalse(SubscriptionUtil.isCarrierRac(mContext, NO_RAC_CARRIER_ID));
+ }
+
@Ignore
@Test
public void getAvailableSubscriptions_twoSubscriptions_twoResults() {
@@ -526,7 +565,6 @@
@Test
public void isSimHardwareVisible_configAsInvisible_returnFalse() {
- when(mContext.getResources()).thenReturn(mResources);
when(mResources.getBoolean(R.bool.config_show_sim_info))
.thenReturn(false);
@@ -535,7 +573,6 @@
@Test
public void isSimHardwareVisible_configAsVisible_returnTrue() {
- when(mContext.getResources()).thenReturn(mResources);
when(mResources.getBoolean(R.bool.config_show_sim_info))
.thenReturn(true);
@@ -599,17 +636,17 @@
}
@Test
- public void isConnectedToWifiOrDifferentSubId_hasWiFi_returnTrue() {
+ public void isConnectedToWifi_hasWiFi_returnTrue() {
addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- assertTrue(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+ assertTrue(SubscriptionUtil.isConnectedToWifi(mContext));
}
@Test
- public void isConnectedToWifiOrDifferentSubId_noData_and_noWiFi_returnFalse() {
+ public void isConnectedToWifi_noWiFi_returnFalse() {
addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
- assertFalse(SubscriptionUtil.isConnectedToWifiOrDifferentSubId(mContext, SUBID_1));
+ assertFalse(SubscriptionUtil.isConnectedToWifi(mContext));
}
private void addNetworkTransportType(int networkType) {
diff --git a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java b/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
deleted file mode 100644
index b71547b..0000000
--- a/tests/unit/src/com/android/settings/privatespace/HidePrivateSpaceControllerTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.privatespace;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.Flags;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.provider.Settings;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@RequiresFlagsEnabled({Flags.FLAG_ALLOW_PRIVATE_PROFILE,
- android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES})
-public class HidePrivateSpaceControllerTest {
- @Rule
- public final CheckFlagsRule mCheckFlagsRule =
- DeviceFlagsValueProvider.createCheckFlagsRule();
-
- private static final String KEY = "private_space_hidden";
- private static final String DETAIL_PAGE_KEY = "private_space_hidden_details";
- private Context mContext;
- private HidePrivateSpaceSummaryController mHidePrivateSpaceSummaryController;
- private HidePrivateSpaceController mHidePrivateSpaceController;
- private ContentResolver mContentResolver;
- private int mOriginalHiddenValue;
-
- /** Required setup before a test. */
- @Before
- public void setUp() {
- mContext = spy(ApplicationProvider.getApplicationContext());
- mContentResolver = mContext.getContentResolver();
- mHidePrivateSpaceSummaryController = new HidePrivateSpaceSummaryController(mContext, KEY);
- mHidePrivateSpaceController =
- new HidePrivateSpaceController(mContext, DETAIL_PAGE_KEY);
- mOriginalHiddenValue = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT, 0);
- }
-
- @After
- public void tearDown() {
- Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
- mOriginalHiddenValue);
- }
-
- /** Tests that the controller is always available. */
- @Test
- public void getAvailabilityStatus_returnsAvailable() {
- assertThat(mHidePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- }
-
- /** Tests that hide preference summary displays On when hide toggle is enabled.*/
- @Test
- public void setChecked_enable_shouldDisplayOn() {
- Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
- 0);
- assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
-
- mHidePrivateSpaceController.setChecked(true);
-
- assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
- .isEqualTo("On");
- assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
- }
-
- /** Tests that hide preference summary displays Off when toggle is disabled.*/
- @Test
- public void setChecked_disable_shouldDisplayOff() {
- Settings.Secure.putInt(mContentResolver, Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT,
- 1);
-
- assertThat(mHidePrivateSpaceController.isChecked()).isTrue();
-
- mHidePrivateSpaceController.setChecked(false);
-
- assertThat(mHidePrivateSpaceSummaryController.getSummary().toString())
- .isEqualTo("Off");
- assertThat(mHidePrivateSpaceController.isChecked()).isFalse();
- }
-}