Merge "Disable nfc foreground setting ui when the wallet role is enabled." into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c8f35ae..96b798a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3232,7 +3232,8 @@
<receiver
android:name=".fuelgauge.batteryusage.BootBroadcastReceiver"
- android:exported="true">
+ android:exported="true"
+ android:permission="com.android.settings.BATTERY_DATA">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="com.google.android.setupwizard.SETUP_WIZARD_FINISHED"/>
diff --git a/OWNERS b/OWNERS
index 6698752..12cd4ea 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,7 +11,6 @@
jiannan@google.com
millchen@google.com
sunnyshao@google.com
-yantingyang@google.com
# Android Settings extended
chaohuiw@google.com
diff --git a/aconfig/settings_connecteddevice_flag_declarations.aconfig b/aconfig/settings_connecteddevice_flag_declarations.aconfig
index 5ba2129..0fc164e 100644
--- a/aconfig/settings_connecteddevice_flag_declarations.aconfig
+++ b/aconfig/settings_connecteddevice_flag_declarations.aconfig
@@ -33,4 +33,11 @@
namespace: "pixel_cross_device_control"
description: "Order the saved bluetooth devices by most recently connected."
bug: "306160434"
+}
+
+flag {
+ name: "enable_hide_exclusively_managed_bluetooth_device"
+ namespace: "dck_framework"
+ description: "Hide exclusively managed Bluetooth devices in BT settings menu."
+ bug: "322285078"
}
\ No newline at end of file
diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig
index 56c4b32..36f104c 100644
--- a/aconfig/settings_flag_declarations.aconfig
+++ b/aconfig/settings_flag_declarations.aconfig
@@ -13,3 +13,10 @@
description: "Enabling will provide an explicit package name for Intent to update mainline modules"
bug: "278987474"
}
+
+flag {
+ name: "app_archiving"
+ namespace: "android_settings"
+ description: "Feature flag to enable the archiving feature."
+ bug: "323164382"
+}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 78900bc..965daf6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1219,15 +1219,15 @@
<string name="work_profile_category_header">Work profile</string>
<!-- Title for the Private Space page. [CHAR LIMIT=60] -->
- <string name="private_space_title">Private Space</string>
+ <string name="private_space_title">Private space</string>
<!-- Summary for the Private Space page. [CHAR LIMIT=NONE] -->
<string name="private_space_summary">Keep private apps locked and hidden</string>
<!-- Description for the Private Space page. [CHAR LIMIT=NONE] -->
<string name="private_space_description">Keep private apps in a separate space that you can hide or lock</string>
<!-- Title for the Private Space one lock preference. [CHAR LIMIT=60] -->
- <string name="private_space_lock_title">Private Space lock</string>
+ <string name="private_space_lock_title">Private space lock</string>
<!-- Description for the Private Space one lock preference page. [CHAR LIMIT=NONE] -->
- <string name="private_space_one_lock_summary">You can unlock Private Space the same way you unlock your device, or choose a different lock</string>
+ <string name="private_space_one_lock_summary">You can unlock your private space the same way you unlock your device, or choose a different lock</string>
<!-- Title for the Private Space one lock preference. [CHAR LIMIT=60] -->
<string name="private_space_screen_lock_title">Use device screen lock</string>
<!-- Title for the Face and Fingerprint preference. [CHAR LIMIT=60] -->
@@ -1239,15 +1239,15 @@
<!-- Summary for the Face and Fingerprint preference when no biometric is set. [CHAR LIMIT=60] -->
<string name="private_space_biometric_summary">Tap to set up</string>
<!-- Title for the Fingerprint unlock for private space preference. [CHAR LIMIT=60] -->
- <string name="private_space_fingerprint_unlock_title">Fingerprint Unlock for Private Space</string>
+ <string name="private_space_fingerprint_unlock_title">Fingerprint Unlock for private space</string>
<!-- Title for the Face unlock for private space preference. [CHAR LIMIT=60] -->
- <string name="private_space_face_unlock_title">Face Unlock for Private Space</string>
+ <string name="private_space_face_unlock_title">Face Unlock for private space</string>
<!-- Biometric category title - biometric options for unlocking the device. [CHAR LIMIT=50] -->
<string name="private_space_category_ways_to_unlock">Ways to unlock</string>
<!-- Summary for one lock when device screen lock is used as private profile lock. [CHAR LIMIT=40] -->
<string name="private_space_screen_lock_summary">Same as device screen lock</string>
<!-- Dialog message to choose a new lock for Private Space. [CHAR LIMIT=50] -->
- <string name="private_space_new_lock_title">Choose a new lock for Private Space?</string>
+ <string name="private_space_new_lock_title">Choose a new lock for private space?</string>
<!-- Title for the preference for auto lock private space. [CHAR LIMIT=40] -->
<string name="private_space_auto_lock_title">Lock automatically</string>
<!-- Title for private space auto lock settings page. [CHAR LIMIT=50] -->
@@ -1263,17 +1263,17 @@
<!-- Title for the preference to hide Private Space. [CHAR LIMIT=60] -->
<string name="private_space_hide_title">Hide when locked</string>
<!-- Title for the hide Private Space setting. [CHAR LIMIT=60] -->
- <string name="privatespace_hide_page_title">Hide Private Space when locked</string>
+ <string name="privatespace_hide_page_title">Hide private space when locked</string>
<!-- Description for hide Private Space settings page. [CHAR LIMIT=NONE] -->
- <string name="privatespace_hide_page_summary">To stop other people knowing Private Space is on your device, you can hide it from your apps list</string>
+ <string name="privatespace_hide_page_summary">To stop other people knowing you have a private space on your device, you can hide it from your apps list</string>
<!-- Header in hide Private Space settings page to access Private Space when hidden. [CHAR LIMIT=60] -->
- <string name="privatespace_access_header">Access Private Space when hidden</string>
+ <string name="privatespace_access_header">Access private space when hidden</string>
<!-- Text in hide Private Space settings page on how to search Private Space when hidden. [CHAR LIMIT=60] -->
- <string name="privatespace_search_description">Search for \'Private Space\' in the search bar</string>
+ <string name="privatespace_search_description">From your apps list, enter \'private space\' in the search bar</string>
<!-- Text in hide Private Space settings page to tap on Private Space tile. [CHAR LIMIT=60] -->
- <string name="privatespace_tap_tile_description">Tap the Private Space tile</string>
+ <string name="privatespace_tap_tile_description">Tap the private space tile</string>
<!-- Text in hide Private Space settings page to Unlock Private Space. [CHAR LIMIT=60] -->
- <string name="privatespace_unlock_description">Unlock your Private Space</string>
+ <string name="privatespace_unlock_description">Unlock your private space</string>
<!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
<string name="privatespace_hide_off_summary">Off</string>
<!-- Used to describe the off state of Private space hidden [CHAR LIMIT=30] -->
@@ -1295,9 +1295,9 @@
<!-- Description for private space delete confirmation page that mentions it will take a few moments. [CHAR LIMIT=40] -->
<string name="private_space_confirm_deletion_summary">This will take a few moments</string>
<!-- Toast to show when the private space was deleted. [CHAR LIMIT=NONE] -->
- <string name="private_space_deleted">Private Space successfully deleted</string>
+ <string name="private_space_deleted">Private space deleted</string>
<!-- Toast to show when the private space could not be deleted. [CHAR LIMIT=NONE] -->
- <string name="private_space_delete_failed">Private Space could not be deleted</string>
+ <string name="private_space_delete_failed">Private space could not be deleted</string>
<!-- Toast to show when the private space is unlocked from settings entry point. [CHAR LIMIT=40] -->
<string name="private_space_unlocked">Private space unlocked</string>
<!-- Title of the Alert Dialog when no screen lock is set [CHAR LIMIT=30] -->
@@ -1329,13 +1329,13 @@
<!-- Text shown at the bottom in private space auto advancing screens. [CHAR LIMIT=60] -->
<string name="private_space_setting_up_text">Setting up private space\u2026</string>
<!-- Title for private space setup in auto advancing screen informing private space notifications are hidden when locked. [CHAR LIMIT=NONE] -->
- <string name="private_space_notifications_hidden_title">Notifications from apps in private space are hidden when it\u2019s locked</string>
+ <string name="private_space_notifications_hidden_title">Notifications from private space apps are hidden when it\u2019s locked</string>
<!-- Title for private space setup in auto advancing screen informing photos/files from private space can be shared when unlocked. [CHAR LIMIT=NONE] -->
- <string name="private_space_share_photos_title">Unlock private space to share photos or files from private space apps</string>
+ <string name="private_space_share_photos_title">Unlock private space to share photos or files</string>
<!-- Title for private space setup in auto advancing screen informing some system apps are already installed in private space. [CHAR LIMIT=NONE] -->
<string name="private_space_apps_installed_title">Some apps are already installed in your private space</string>
<!-- Title for private space creation error screen. [CHAR LIMIT=60] -->
- <string name="private_space_error_screen_title">Couldn\u2019t set up private space</string>
+ <string name="private_space_error_screen_title">Couldn\u2019t set up a private space</string>
<!-- Label for button to retry creating private space again on creation error. [CHAR LIMIT=30] -->
<string name="private_space_tryagain_label">Try Again</string>
<!-- Title for private space lock setup screen. [CHAR LIMIT=90] -->
@@ -1349,7 +1349,7 @@
<!-- Title for private space setup success screen. [CHAR LIMIT=30] -->
<string name="private_space_success_title">All set!</string>
<!-- Summary for the private space setup success screen. [CHAR LIMIT=NONE] -->
- <string name="private_space_access_text">To access your private space, go to your apps list then scroll down</string>
+ <string name="private_space_access_text">To find your private space, go to your apps list then scroll down</string>
<!-- Label for private space done button to show a toast, finish setup and launch All apps [CHAR LIMIT=30] -->
<string name="private_space_done_label">Done</string>
<!-- Toast to show on private space setup completion informing user to scroll down All apps to access private space. [CHAR LIMIT=60] -->
@@ -1375,13 +1375,13 @@
<!-- TODO(b/309950257): Remove below strings once QSTIle fulfillment is complete. -->
<!-- Header in hide Private Space settings page to unhide Private Space. [CHAR LIMIT=90] -->
- <string name="privatespace_unhide_header">To show Private Space (Not final UX)</string>
+ <string name="privatespace_unhide_header">To show private space (Not final UX)</string>
<!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
<string name="privatespace_open_settings">Open the Settings App</string>
<!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
- <string name="privatespace_tap_settings">Tap on Security & privacy > Private Space > Hide Private Space when locked</string>
+ <string name="privatespace_tap_settings">Tap on Security & privacy > private space > Hide private space when locked</string>
<!-- Text in hide Private Space settings page to off hide toggle. [CHAR LIMIT=90] -->
- <string name="privatespace_turnoff_hide">Turn off \‘Hide Private Space when locked\’ toggle</string>
+ <string name="privatespace_turnoff_hide">Turn off \‘Hide private space when locked\’ toggle</string>
<!-- Note in hide Private Space settings page to inform that this is a development feature. [CHAR LIMIT=NONE] -->
<string name="privatespace_development_note">Note to Googlers: The development of this feature is still in progress</string>
@@ -7265,7 +7265,7 @@
<!-- Summary text describing signal strength to the user. [CHAR LIMIT=60] -->
<string name="sim_signal_strength"><xliff:g id="dbm">%1$d</xliff:g> dBm <xliff:g id="asu">%2$d</xliff:g> asu</string>
<!-- Title for SIM notification. [CHAR LIMIT=40] -->
- <string name="sim_notification_title">SIMs changed.</string>
+ <string name="sim_notification_title">Your SIMs changed</string>
<!-- Message under title informing the user to touch to go to SIM Cards in Settings. [CHAR LIMIT=40] -->
<string name="sim_notification_summary">Tap to set up</string>
@@ -9055,7 +9055,7 @@
<string name="screen_pinning_unlock_none">Lock device when unpinning</string>
<!-- [CHAR LIMIT=60] turn eSim deletion confirmation on/off -->
- <string name="confirm_sim_deletion_title">Confirm SIM deletion</string>
+ <string name="confirm_sim_deletion_title">Confirm you want to erase your eSIM</string>
<!-- [CHAR LIMIT=NONE] eSim deletion confirmation description -->
<string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing an eSIM</string>
@@ -11370,7 +11370,7 @@
the user that the way to disable this SIM is to physically remove it. This is in contrast
to eSIM's, which can disabled using an on/off toggle switch. [CHAR LIMIT=NONE] -->
<string name="mobile_network_disable_sim_explanation">
- To disable this SIM, remove the SIM card
+ To turn off this SIM, remove the SIM card
</string>
<!--Summary used when a physical SIM is disabled, indicating that tapping on the preference will
@@ -11378,7 +11378,7 @@
Network & internet page (if there are no other SIMs), or on the mobile network list page.
[CHAR LIMIT=50] -->
<string name="mobile_network_tap_to_activate">
- Tap to activate <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g>
+ Tap to activate your <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g> SIM
</string>
<!-- Mobile network details page. Label for an option that lets the user delete an eSIM from
@@ -11502,13 +11502,13 @@
<!-- Text of carrier list item in the mep confirmation dialog asking the user if they want to turn off the carrier. [CHAR_LIMIT=NONE] -->
<string name="sim_action_switch_sub_dialog_info_outline_for_turning_off">Turning off a SIM won\u2019t cancel your service</string>
<!-- Status message indicating the device is in the process of disconnecting from one mobile network and immediately connecting to another. [CHAR_LIMIT=NONE] -->
- <string name="sim_action_enabling_sim_without_carrier_name">Connecting to network…</string>
+ <string name="sim_action_enabling_sim_without_carrier_name">Activating your SIM…</string>
<!-- Text of progress dialog indicating the subscription switch is in progress. [CHAR_LIMIT=NONE] -->
- <string name="sim_action_switch_sub_dialog_progress">Switching to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g> for calls and messages…</string>
+ <string name="sim_action_switch_sub_dialog_progress">Switching to <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>…</string>
<!-- Title of error message indicating that the device could not disconnect from one mobile network and immediately connect to another. [CHAR_LIMIT=NONE] -->
- <string name="sim_action_enable_sim_fail_title">Can\u2019t switch carrier</string>
+ <string name="sim_action_enable_sim_fail_title">Can\u2019t switch SIMs</string>
<!-- Body text of error message indicating the device could not disconnect from one mobile network and immediately connect to another, due to an unspecified issue. [CHAR_LIMIT=NONE] -->
- <string name="sim_action_enable_sim_fail_text">The carrier can\u2019t be switched due to an error.</string>
+ <string name="sim_action_enable_sim_fail_text">Something went wrong. Can\u2019t switch SIMs.</string>
<!-- Title of confirmation dialog asking the user if they want to disable subscription. [CHAR_LIMIT=NONE] -->
<string name="privileged_action_disable_sub_dialog_title">Turn off <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>?</string>
<!-- Title of confirmation dialog asking the user if they want to disable subscription. [CHAR_LIMIT=NONE] -->
@@ -11516,9 +11516,9 @@
<!-- Disabling SIMs progress dialog message [CHAR LIMIT=NONE] -->
<string name="privileged_action_disable_sub_dialog_progress">Turning off SIM<xliff:g id="ellipsis" example="...">…</xliff:g></string>
<!-- Title of error messaging indicating the device could not disable the mobile network. [CHAR LIMIT=NONE] -->
- <string name="privileged_action_disable_fail_title">Can\u2019t disable carrier</string>
+ <string name="privileged_action_disable_fail_title">Can\u2019t turn off SIM</string>
<!-- Body text of error message indicating the device could not disable the mobile network, due to an unknown issue. [CHAR LIMIT=NONE] -->
- <string name="privileged_action_disable_fail_text">Something went wrong and your carrier could not be disabled.</string>
+ <string name="privileged_action_disable_fail_text">Something went wrong and your SIM could not be turned off.</string>
<!-- Title on a dialog asking the users whether they want to enable DSDS mode. [CHAR LIMIT=NONE] -->
<string name="sim_action_enable_dsds_title">Use 2 SIMs?</string>
<!-- Message in a dialog indicating the user can enable DSDS mode. [CHAR LIMIT=NONE] -->
@@ -11598,7 +11598,7 @@
<!-- Title on a push notification indicating that the user's device is in the middle of switching between mobile networks. [CHAR LIMIT=NONE] -->
<string name="sim_switch_channel_id">Carrier switching</string>
<!-- The title of post DSDS reboot notification. The title includes carrier's name. [CHAR LIMIT=NONE] -->
- <string name="post_dsds_reboot_notification_title_with_carrier"><xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g> is active</string>
+ <string name="post_dsds_reboot_notification_title_with_carrier">Your <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g> SIM is active</string>
<!-- The body text of post DSDS reboot notification. [CHAR LIMIT=NONE] -->
<string name="post_dsds_reboot_notification_text">Tap to update SIM settings</string>
<!-- Title on a push notification indicating that the user's device switched to a new mobile network. [CHAR LIMIT=NONE] -->
@@ -11614,17 +11614,17 @@
<!-- Strings for choose SIM activity -->
<!-- The title text of choose SIM activity. [CHAR LIMIT=NONE] -->
- <string name="choose_sim_title">Choose a number to use</string>
+ <string name="choose_sim_title">Choose a SIM to use</string>
<!-- The body text of choose SIM activity. [CHAR LIMIT=NONE] -->
<string name="choose_sim_text">{count, plural,
- =1 {1 number is available on this device, but only one can be used at a time}
- =2 {2 numbers are available on this device, but only one can be used at a time}
- other {# numbers are available on this device, but only one can be used at a time}
+ =1 {1 SIM is available on this device, but only one can be used at a time}
+ =2 {2 SIMs are available on this device, but only one can be used at a time}
+ other {# SIMs are available on this device, but only one can be used at a time}
}</string>
<!-- String indicating that we are activating the profile [CHAR LIMIT=NONE] -->
<string name="choose_sim_activating">Activating<xliff:g id="ellipsis" example="...">…</xliff:g></string>
<!-- String indicating that we failed to activate the selected profile [CHAR LIMIT=NONE] -->
- <string name="choose_sim_could_not_activate">Couldn\u2019t be activated right now</string>
+ <string name="choose_sim_could_not_activate">Couldn\u2019t activate this SIM right now</string>
<!-- Strings for switch SIM confirmation dialog. -->
<!-- The title text of switch SIM confirmation dialog. [CHAR LIMIT=NONE] -->
@@ -11979,6 +11979,11 @@
<!-- Developer settings: Summary for allowing mock modem service. [CHAR LIMIT=NONE]-->
<string name="allow_mock_modem_summary">Allow this device to run Mock Modem service for instrumentation testing. Do not enable this during normal usage of the phone</string>
+ <!-- Developer settings: Title for disable app and notification screen share protections [CHAR LIMIT=50] -->
+ <string name="disable_screen_share_protections_for_apps_and_notifications">Disable screen share protections</string>
+ <!-- Developer settings: Summary for disable app and notification screen share protections summary [CHAR LIMIT=150] -->
+ <string name="disable_screen_share_protections_for_apps_and_notifications_summary">Disables system applied app and notifications protections during screen sharing</string>
+
<!-- Title for media control settings [CHAR LIMIT=50]-->
<string name="media_controls_title">Media</string>
<!-- Title of toggle to enable or disable the media resumption feature in quick settings [CHAR LIMIT=50]-->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index fb5e280..c0b6560 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -705,6 +705,11 @@
android:title="@string/show_notification_channel_warnings"
android:summary="@string/show_notification_channel_warnings_summary" />
+ <SwitchPreferenceCompat
+ android:key="disable_screen_share_protections_for_apps_and_notifications"
+ android:title="@string/disable_screen_share_protections_for_apps_and_notifications"
+ android:summary="@string/disable_screen_share_protections_for_apps_and_notifications_summary" />
+
<Preference
android:key="asst_importance_reset"
android:title="@string/asst_importance_reset_title"
diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
index d536932..2b1e47e 100644
--- a/src/com/android/settings/applications/AppCounter.java
+++ b/src/com/android/settings/applications/AppCounter.java
@@ -22,12 +22,15 @@
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.UserInfo;
import android.os.AsyncTask;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import com.android.settings.flags.Flags;
+
import java.util.List;
public abstract class AppCounter extends AsyncTask<Void, Void, Integer> {
@@ -54,7 +57,7 @@
for (UserInfo user : mUm.getProfiles(UserHandle.myUserId())) {
long flags = PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
- | (mFf.archiving() ? PackageManager.MATCH_ARCHIVED_PACKAGES : 0)
+ | (isArchivingEnabled() ? PackageManager.MATCH_ARCHIVED_PACKAGES : 0)
| (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0);
ApplicationInfoFlags infoFlags = ApplicationInfoFlags.of(flags);
final List<ApplicationInfo> list =
@@ -68,6 +71,11 @@
return count;
}
+ private boolean isArchivingEnabled() {
+ return mFf.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false)
+ || Flags.appArchiving();
+ }
+
@Override
protected void onPostExecute(Integer count) {
onCountComplete(count);
diff --git a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
index 489c095..012220c 100644
--- a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
@@ -24,6 +24,8 @@
import androidx.preference.Preference;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
+import com.android.settings.flags.Flags;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
/**
@@ -95,6 +97,15 @@
cachedDevice.getName() + ", isFilterMatched : " + isFilterMatched);
}
}
+ if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+ if (BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
+ cachedDevice.getDevice())) {
+ if (DBG) {
+ Log.d(TAG, "isFilterMatched() hide BluetoothDevice with exclusive manager");
+ }
+ return false;
+ }
+ }
return isFilterMatched;
}
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
index bfd4221..1db90fa 100644
--- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
@@ -25,6 +25,8 @@
import androidx.preference.Preference;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
+import com.android.settings.flags.Flags;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -99,12 +101,22 @@
@Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
final BluetoothDevice device = cachedDevice.getDevice();
- Log.d(TAG, "isFilterMatched() device name : " + cachedDevice.getName() +
- ", is connected : " + device.isConnected() + ", is profile connected : "
- + cachedDevice.isConnected());
- return device.getBondState() == BluetoothDevice.BOND_BONDED
- && (mShowConnectedDevice || (!device.isConnected() && isDeviceInCachedDevicesList(
- cachedDevice)));
+ boolean isExclusivelyManaged = BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
+ cachedDevice.getDevice());
+ Log.d(TAG, "isFilterMatched() device name : " + cachedDevice.getName()
+ + ", is connected : " + device.isConnected() + ", is profile connected : "
+ + cachedDevice.isConnected() + ", is exclusively managed : "
+ + isExclusivelyManaged);
+ if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+ return device.getBondState() == BluetoothDevice.BOND_BONDED
+ && (mShowConnectedDevice || (!device.isConnected()
+ && isDeviceInCachedDevicesList(cachedDevice)))
+ && !isExclusivelyManaged;
+ } else {
+ return device.getBondState() == BluetoothDevice.BOND_BONDED
+ && (mShowConnectedDevice || (!device.isConnected()
+ && isDeviceInCachedDevicesList(cachedDevice)));
+ }
}
@Override
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 504eda8..6b38b28 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -763,6 +763,7 @@
context, context.getSystemService(UiModeManager.class)));
controllers.add(new ForceEnableNotesRolePreferenceController(context));
controllers.add(new GrammaticalGenderPreferenceController(context));
+ controllers.add(new SensitiveContentProtectionPreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/development/OWNERS b/src/com/android/settings/development/OWNERS
index 09a4914..92c8cfa 100644
--- a/src/com/android/settings/development/OWNERS
+++ b/src/com/android/settings/development/OWNERS
@@ -1,6 +1,9 @@
# GameDefaultFrameRatePreferenceController
per-file GameDefaultFrameRatePreferenceController.java=file:platform/frameworks/base:/GAME_MANAGER_OWNERS
+# SensitiveContentProtectionPreferenceController
+per-file SensitiveContentProtectionPreferenceController.kt=file:platform/frameworks/base:/core/java/android/permission/OWNERS
+
# ShowHdrSdrRatioPreferenceController
per-file ShowHdrSdrRatioPreferenceController.java=file:platform/frameworks/native:/services/surfaceflinger/OWNERS
diff --git a/src/com/android/settings/development/SensitiveContentProtectionPreferenceController.kt b/src/com/android/settings/development/SensitiveContentProtectionPreferenceController.kt
new file mode 100644
index 0000000..6fe56c8
--- /dev/null
+++ b/src/com/android/settings/development/SensitiveContentProtectionPreferenceController.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.content.Context
+import android.provider.Settings
+import androidx.annotation.VisibleForTesting
+import androidx.preference.Preference
+import androidx.preference.TwoStatePreference
+import com.android.server.notification.Flags.sensitiveNotificationAppProtection
+import com.android.server.notification.Flags.screenshareNotificationHiding
+import com.android.settings.core.PreferenceControllerMixin
+import com.android.settingslib.development.DeveloperOptionsPreferenceController
+
+class SensitiveContentProtectionPreferenceController(val context: Context) :
+ DeveloperOptionsPreferenceController(context),
+ Preference.OnPreferenceChangeListener,
+ PreferenceControllerMixin {
+
+ override fun getPreferenceKey(): String =
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS_KEY
+
+ override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
+ val isEnabled = newValue as Boolean
+ Settings.Global.putInt(
+ mContext.getContentResolver(),
+ Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ if (isEnabled) SETTING_VALUE_ON else SETTING_VALUE_OFF
+ )
+ return true
+ }
+
+ override fun updateState(preference: Preference?) {
+ val mode = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ 0)
+ (mPreference as TwoStatePreference).isChecked = mode != SETTING_VALUE_OFF
+ }
+
+ // Overriding as public, kotlin tests can not invoke a protected method
+ public override fun onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled()
+ Settings.Global.putInt(
+ mContext.getContentResolver(),
+ Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ SETTING_VALUE_OFF
+ )
+ (mPreference as TwoStatePreference).isChecked = false
+ }
+
+ override fun isAvailable(): Boolean {
+ return sensitiveNotificationAppProtection() || screenshareNotificationHiding()
+ }
+
+ companion object {
+ private const val DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS_KEY =
+ "disable_screen_share_protections_for_apps_and_notifications"
+
+ @VisibleForTesting
+ val SETTING_VALUE_ON = 1
+
+ @VisibleForTesting
+ val SETTING_VALUE_OFF = 0
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
index 45c1be0..6425833 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
@@ -41,7 +41,7 @@
public class BatterySaverScheduleRadioButtonsController {
private static final String TAG = "BatterySaverScheduleRadioButtonsController";
- public static final int TRIGGER_LEVEL_MIN = 10;
+ public static final int TRIGGER_LEVEL_MIN = 20;
private Context mContext;
private BatterySaverScheduleSeekBarController mSeekBarController;
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index c6b1bdb..c40212b 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -41,7 +41,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
-import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityGestureNavigationTutorial;
import com.android.settings.core.SubSettingLauncher;
@@ -354,7 +353,7 @@
private boolean isAnyServiceSupportAccessibilityButton() {
final AccessibilityManager ams = getContext().getSystemService(AccessibilityManager.class);
final List<String> targets = ams.getAccessibilityShortcutTargets(
- ShortcutConstants.UserShortcutType.SOFTWARE);
+ AccessibilityManager.ACCESSIBILITY_BUTTON);
return !targets.isEmpty();
}
diff --git a/src/com/android/settings/notification/PoliteNotifWorkProfileToggleController.java b/src/com/android/settings/notification/PoliteNotifWorkProfileToggleController.java
index 65b4fb8..99d0a69 100644
--- a/src/com/android/settings/notification/PoliteNotifWorkProfileToggleController.java
+++ b/src/com/android/settings/notification/PoliteNotifWorkProfileToggleController.java
@@ -62,7 +62,7 @@
@Override
public boolean isChecked() {
return Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.NOTIFICATION_COOLDOWN_ENABLED, OFF, mManagedProfileId) != OFF;
+ Settings.System.NOTIFICATION_COOLDOWN_ENABLED, ON, mManagedProfileId) != OFF;
}
@Override
diff --git a/src/com/android/settings/spa/app/appinfo/AppButtons.kt b/src/com/android/settings/spa/app/appinfo/AppButtons.kt
index dcce1d9..3d9c4b1 100644
--- a/src/com/android/settings/spa/app/appinfo/AppButtons.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppButtons.kt
@@ -17,8 +17,8 @@
package com.android.settings.spa.app.appinfo
import android.content.pm.ApplicationInfo
-import android.content.pm.FeatureFlags
-import android.content.pm.FeatureFlagsImpl
+import android.content.pm.FeatureFlags as PmFeatureFlags
+import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -34,7 +34,7 @@
fun AppButtons(
packageInfoPresenter: PackageInfoPresenter,
isHibernationSwitchEnabledStateFlow: MutableStateFlow<Boolean>,
- featureFlags: FeatureFlags = FeatureFlagsImpl()
+ featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
) {
if (remember(packageInfoPresenter) { packageInfoPresenter.isMainlineModule() }) return
val presenter = remember {
@@ -53,7 +53,7 @@
private class AppButtonsPresenter(
private val packageInfoPresenter: PackageInfoPresenter,
isHibernationSwitchEnabledStateFlow: MutableStateFlow<Boolean>,
- private val featureFlags: FeatureFlags
+ private val featureFlags: PmFeatureFlags
) {
private val appLaunchButton = AppLaunchButton(packageInfoPresenter)
private val appInstallButton = AppInstallButton(packageInfoPresenter)
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index dba6184..695e114 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -18,9 +18,8 @@
import android.app.settings.SettingsEnums
import android.content.pm.ApplicationInfo
-import android.content.pm.FeatureFlags
-import android.content.pm.FeatureFlagsImpl
import android.os.Bundle
+import android.os.SystemProperties
import android.os.UserHandle
import android.util.FeatureFlagUtils
import androidx.compose.runtime.Composable
@@ -51,6 +50,8 @@
import com.android.settingslib.spaprivileged.model.app.toRoute
import com.android.settingslib.spaprivileged.template.app.AppInfoProvider
import kotlinx.coroutines.flow.MutableStateFlow
+import android.content.pm.FeatureFlags as PmFeatureFlags
+import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl
private const val PACKAGE_NAME = "packageName"
private const val USER_ID = "userId"
@@ -121,7 +122,7 @@
@Composable
private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle()
- val featureFlags: FeatureFlags = FeatureFlagsImpl()
+ val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
RegularScaffold(
title = stringResource(R.string.application_info_label),
actions = {
@@ -177,5 +178,6 @@
}
}
-fun isArchivingEnabled(featureFlags: FeatureFlags) =
- featureFlags.archiving() || "true" == System.getProperty("pm.archiving.enabled")
+fun isArchivingEnabled(featureFlags: PmFeatureFlags) =
+ featureFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false)
+ || Flags.appArchiving()
\ No newline at end of file
diff --git a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
index 4f47266..86d7f44 100644
--- a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
@@ -22,8 +22,9 @@
import android.app.AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
import android.content.Context
import android.content.pm.ApplicationInfo
-import android.content.pm.Flags
+import android.content.pm.Flags as PmFlags
import android.os.Build
+import android.os.SystemProperties
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN
import android.provider.DeviceConfig
@@ -36,6 +37,7 @@
import com.android.settings.R
import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED
import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS
+import com.android.settings.flags.Flags
import com.android.settingslib.spa.framework.compose.OverridableFlow
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -91,7 +93,8 @@
}
private fun isArchivingEnabled() =
- Flags.archiving() || "true" == System.getProperty("pm.archiving.enabled")
+ PmFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false)
+ || Flags.appArchiving()
private class HibernationSwitchPresenter(context: Context, private val app: ApplicationInfo) {
private val appOpsManager = context.appOpsManager
diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
index 230ccb9..81abae5 100644
--- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
+++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
@@ -20,14 +20,16 @@
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import android.content.pm.FeatureFlags
-import android.content.pm.FeatureFlagsImpl
+import android.content.pm.FeatureFlags as PmFeatureFlags
+import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.UserHandle
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
+import com.android.settings.flags.FeatureFlags
+import com.android.settings.flags.FeatureFlagsImpl
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settings.spa.app.startUninstallActivity
import com.android.settingslib.spa.framework.compose.LocalNavController
@@ -60,7 +62,7 @@
val userId: Int,
private val coroutineScope: CoroutineScope,
private val packageManagers: IPackageManagers = PackageManagers,
- private val featureFlags: FeatureFlags = FeatureFlagsImpl(),
+ private val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl(),
) {
private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
private val userHandle = UserHandle.of(userId)
diff --git a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt
index 3e48aa5..2b8d12d 100644
--- a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt
+++ b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt
@@ -27,7 +27,8 @@
import androidx.compose.runtime.Composable
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settingslib.R
-import com.android.settingslib.spa.livedata.observeAsCallback
+import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
+import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.model.app.PackageManagers
@@ -47,7 +48,7 @@
override val app: ApplicationInfo,
val isTrumped: Boolean,
val isChangeable: Boolean,
- var controller: AlarmsAndRemindersController,
+ var controller: AppOpsController,
) : AppRecord
class AlarmsAndRemindersAppListModel(
@@ -82,7 +83,7 @@
@Composable
override fun isAllowed(record: AlarmsAndRemindersAppRecord): () -> Boolean? = when {
record.isTrumped -> ({ true })
- else -> record.controller.isAllowed.observeAsCallback()
+ else -> record.controller.isAllowed.collectAsCallbackWithLifecycle()
}
override fun isChangeable(record: AlarmsAndRemindersAppRecord) = record.isChangeable
@@ -112,7 +113,12 @@
app = app,
isTrumped = isTrumped,
isChangeable = hasRequestPermission && !isTrumped,
- controller = AlarmsAndRemindersController(context, app),
+ controller = AppOpsController(
+ context = context,
+ app = app,
+ op = AppOpsManager.OP_SCHEDULE_EXACT_ALARM,
+ setModeByUid = true,
+ ),
)
}
diff --git a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt
deleted file mode 100644
index bd40f45..0000000
--- a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersController.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 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.spa.app.specialaccess
-
-import android.app.AppOpsManager
-import android.app.AppOpsManager.MODE_ALLOWED
-import android.app.AppOpsManager.MODE_ERRORED
-import android.content.Context
-import android.content.pm.ApplicationInfo
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import com.android.settingslib.spaprivileged.framework.common.alarmManager
-import com.android.settingslib.spaprivileged.framework.common.appOpsManager
-import com.android.settingslib.spaprivileged.model.app.userId
-
-class AlarmsAndRemindersController(
- context: Context,
- private val app: ApplicationInfo,
-) {
- private val alarmManager = context.alarmManager
- private val appOpsManager = context.appOpsManager
-
- val isAllowed: LiveData<Boolean>
- get() = _allowed
-
- fun setAllowed(allowed: Boolean) {
- val mode = if (allowed) MODE_ALLOWED else MODE_ERRORED
- appOpsManager.setUidMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, app.uid, mode)
- _allowed.postValue(allowed)
- }
-
- private val _allowed = object : MutableLiveData<Boolean>() {
- override fun onActive() {
- postValue(alarmManager.hasScheduleExactAlarm(app.packageName, app.userId))
- }
- }
-}
diff --git a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
index dc98330..3e9058f 100644
--- a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
+++ b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
@@ -26,7 +26,7 @@
import android.os.UserManager
import androidx.compose.runtime.Composable
import com.android.settings.R
-import com.android.settingslib.spa.livedata.observeAsCallback
+import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.userId
@@ -81,7 +81,7 @@
@Composable
override fun isAllowed(record: InstallUnknownAppsRecord) =
- record.appOpsController.isAllowed.observeAsCallback()
+ record.appOpsController.isAllowed.collectAsCallbackWithLifecycle()
override fun isChangeable(record: InstallUnknownAppsRecord) =
isChangeable(record, getPotentialPackageNames(record.app.userId))
diff --git a/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt b/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt
index fe8f103..7885b86 100644
--- a/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt
+++ b/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt
@@ -27,7 +27,7 @@
import android.util.Log
import androidx.compose.runtime.Composable
import com.android.settings.R
-import com.android.settingslib.spa.livedata.observeAsCallback
+import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.installed
@@ -92,7 +92,7 @@
@Composable
override fun isAllowed(record: PictureInPictureRecord) =
- record.appOpsController.isAllowed.observeAsCallback()
+ record.appOpsController.isAllowed.collectAsCallbackWithLifecycle()
override fun isChangeable(record: PictureInPictureRecord) = record.isSupport
diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java
index c10ee27..446891a 100644
--- a/src/com/android/settings/wifi/WifiScanModeActivity.java
+++ b/src/com/android/settings/wifi/WifiScanModeActivity.java
@@ -39,26 +39,24 @@
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.wifi.WifiPermissionChecker;
-/**
- * This activity requests users permission to allow scanning even when Wi-Fi is turned off
- */
+/** This activity requests users permission to allow scanning even when Wi-Fi is turned off */
public class WifiScanModeActivity extends FragmentActivity {
private static final String TAG = "WifiScanModeActivity";
private DialogFragment mDialog;
- @VisibleForTesting
- String mApp;
- @VisibleForTesting
- WifiPermissionChecker mWifiPermissionChecker;
+ @VisibleForTesting String mApp;
+ @VisibleForTesting WifiPermissionChecker mWifiPermissionChecker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- getWindow().addSystemFlags(
- WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ getWindow()
+ .addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
Intent intent = getIntent();
if (savedInstanceState == null) {
- if (intent != null && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
- .equals(intent.getAction())) {
+ if (intent != null
+ && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.equals(
+ intent.getAction())) {
refreshAppLabel();
} else {
finish();
@@ -92,6 +90,12 @@
return;
}
+ if (!isWifiScanModeConfigAllowed(getApplicationContext())) {
+ Log.e(TAG, "This user is not allowed to configure Wi-Fi Scan Mode!");
+ finish();
+ return;
+ }
+
if (mDialog == null) {
mDialog = AlertDialogFragment.newInstance(mApp);
mDialog.show(getSupportFragmentManager(), "dialog");
@@ -140,6 +144,7 @@
}
private final String mApp;
+
public AlertDialogFragment(String app) {
super();
mApp = app;
@@ -158,25 +163,27 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
- .setMessage(TextUtils.isEmpty(mApp) ?
- getString(R.string.wifi_scan_always_turn_on_message_unknown) :
- getString(R.string.wifi_scan_always_turnon_message, mApp))
- .setPositiveButton(R.string.wifi_scan_always_confirm_allow,
+ .setMessage(
+ TextUtils.isEmpty(mApp)
+ ? getString(R.string.wifi_scan_always_turn_on_message_unknown)
+ : getString(R.string.wifi_scan_always_turnon_message, mApp))
+ .setPositiveButton(
+ R.string.wifi_scan_always_confirm_allow,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((WifiScanModeActivity) getActivity()).doPositiveClick();
}
- }
- )
- .setNegativeButton(R.string.wifi_scan_always_confirm_deny,
+ })
+ .setNegativeButton(
+ R.string.wifi_scan_always_confirm_deny,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((WifiScanModeActivity) getActivity()).doNegativeClick();
}
- }
- )
+ })
.create();
}
+
@Override
public void onCancel(DialogInterface dialog) {
((WifiScanModeActivity) getActivity()).doNegativeClick();
@@ -184,9 +191,14 @@
}
private static boolean isGuestUser(Context context) {
- if (context == null) return false;
final UserManager userManager = context.getSystemService(UserManager.class);
if (userManager == null) return false;
return userManager.isGuestUser();
}
+
+ private static boolean isWifiScanModeConfigAllowed(Context context) {
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ if (userManager == null) return true;
+ return !userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_LOCATION);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
index 00115d7..cd48bf1 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
@@ -20,6 +20,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -28,18 +30,26 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.Pair;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAudioManager;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowCachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -58,6 +68,10 @@
public class ConnectedBluetoothDeviceUpdaterTest {
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+ private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private DashboardFragment mDashboardFragment;
@@ -69,6 +83,8 @@
private BluetoothDevice mBluetoothDevice;
@Mock
private Drawable mDrawable;
+ @Mock
+ private PackageManager mPackageManager;
private Context mContext;
private ConnectedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -82,7 +98,7 @@
MockitoAnnotations.initMocks(this);
Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mAudioManager = mContext.getSystemService(AudioManager.class);
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
@@ -92,6 +108,7 @@
mCachedDevices = new ArrayList<>();
mCachedDevices.add(mCachedBluetoothDevice);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs);
@@ -320,4 +337,97 @@
assertThat(btPreference.shouldHideSecondTarget()).isTrue();
}
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_notExclusiveManagedDevice_addDevice() {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mBluetoothDeviceUpdater
+ .isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ null);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_notAllowedExclusiveManagedDevice_addDevice() {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mBluetoothDeviceUpdater
+ .isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
+ throws Exception {
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mBluetoothDeviceUpdater
+ .isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+ doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+ verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
+ throws Exception {
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mBluetoothDeviceUpdater
+ .isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+ doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+ verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
+ throws Exception {
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mBluetoothDeviceUpdater
+ .isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+ doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
+ exclusiveManagerName, 0);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
index c229449..349391d 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
@@ -18,6 +18,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -28,17 +29,26 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+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.util.Pair;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -56,6 +66,10 @@
public class SavedBluetoothDeviceUpdaterTest {
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+ private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private DashboardFragment mDashboardFragment;
@@ -73,6 +87,8 @@
private LocalBluetoothManager mBluetoothManager;
@Mock
private Drawable mDrawable;
+ @Mock
+ private PackageManager mPackageManager;
private Context mContext;
private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -84,12 +100,13 @@
MockitoAnnotations.initMocks(this);
Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device");
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
doReturn(mContext).when(mDashboardFragment).getContext();
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext,
mDevicePreferenceCallback, false, /* metricsCategory= */ 0));
@@ -103,10 +120,10 @@
mCachedDevices.add(mCachedBluetoothDevice);
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
-
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
public void update_filterMatch_addPreference() {
doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
doReturn(false).when(mBluetoothDevice).isConnected();
@@ -118,6 +135,7 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
public void update_filterNotMatch_removePreference() {
doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState();
doReturn(true).when(mBluetoothDevice).isConnected();
@@ -298,4 +316,125 @@
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
}
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_notExclusivelyManagedDevice_addDevice() {
+ final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
+ cachedDevices.add(mCachedBluetoothDevice);
+
+ when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ null);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
+ BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_notAllowedExclusivelyManagedDevice_addDevice() {
+ final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
+ cachedDevices.add(mCachedBluetoothDevice);
+
+ when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
+ BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
+ throws Exception {
+ final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+
+ when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+
+ doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
+ mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+ verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
+ BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
+ throws Exception {
+ final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+ cachedDevices.add(mCachedBluetoothDevice);
+
+ when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+
+ doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+ verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice,
+ BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
+ public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
+ throws Exception {
+ final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
+ final String exclusiveManagerName =
+ BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
+ FAKE_EXCLUSIVE_MANAGER_NAME);
+ cachedDevices.add(mCachedBluetoothDevice);
+
+ when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
+ when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ exclusiveManagerName.getBytes());
+
+ doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
+ exclusiveManagerName, 0);
+
+ mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+ verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
+ BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java
index aa10517..4cdd364 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceControllerTest.java
@@ -171,6 +171,7 @@
mShadowBluetoothAdapter.setEnabled(false);
mController.displayPreference(mScreen);
mController.updateVisibility();
+ shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse();
}
@@ -180,6 +181,7 @@
mShadowBluetoothAdapter.setEnabled(false);
mController.displayPreference(mScreen);
mController.updateVisibility();
+ shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse();
}
@@ -188,6 +190,7 @@
when(mBroadcast.isEnabled(any())).thenReturn(false);
mController.displayPreference(mScreen);
mController.updateVisibility();
+ shadowOf(Looper.getMainLooper()).idle();
assertThat(mPreference.isVisible()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
index eeedccc..c05d9ed 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
@@ -20,30 +20,29 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Bundle;
-import android.text.format.DateUtils;
import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settings.SettingsActivity;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
-import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.CardPreference;
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.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
@@ -53,8 +52,8 @@
private static final String KEY_PREF = "battery_tip";
private static final String KEY_TIP = "key_battery_tip";
- private static final long AVERAGE_TIME_MS = DateUtils.HOUR_IN_MILLIS;
+ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private BatteryTipPreferenceController.BatteryTipListener mBatteryTipListener;
@Mock private PreferenceScreen mPreferenceScreen;
@Mock private BatteryTip mBatteryTip;
@@ -64,21 +63,16 @@
private Context mContext;
private CardPreference mCardPreference;
private BatteryTipPreferenceController mBatteryTipPreferenceController;
- private List<BatteryTip> mOldBatteryTips;
private List<BatteryTip> mNewBatteryTips;
- private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
+ mContext = ApplicationProvider.getApplicationContext();
- mCardPreference = spy(new CardPreference(mContext));
+ mCardPreference = new CardPreference(mContext);
when(mPreferenceScreen.getContext()).thenReturn(mContext);
doReturn(mCardPreference).when(mPreferenceScreen).findPreference(KEY_PREF);
- mFeatureFactory = FakeFeatureFactory.setupForTest();
- mOldBatteryTips = new ArrayList<>();
mNewBatteryTips = new ArrayList<>();
mBatteryTipPreferenceController = buildBatteryTipPreferenceController();
@@ -87,32 +81,32 @@
}
@Test
- public void testDisplayPreference_isInvisible() {
+ public void displayPreference_isInvisible() {
mBatteryTipPreferenceController.displayPreference(mPreferenceScreen);
assertThat(mCardPreference.isVisible()).isFalse();
}
@Test
- public void testUpdateBatteryTips_tipsStateInvisible_isInvisible() {
+ public void updateBatteryTips_tipsStateInvisible_isInvisible() {
mBatteryTipPreferenceController.updateBatteryTips(mNewBatteryTips);
assertThat(mCardPreference.isVisible()).isFalse();
}
@Test
- public void testGetCurrentBatteryTip_noTips_isNull() {
+ public void getCurrentBatteryTip_noTips_isNull() {
assertThat(mBatteryTipPreferenceController.getCurrentBatteryTip()).isNull();
}
@Test
- public void testGetCurrentBatteryTip_tipsInvisible_isNull() {
+ public void getCurrentBatteryTip_tipsInvisible_isNull() {
mBatteryTipPreferenceController.updateBatteryTips(mNewBatteryTips);
assertThat(mBatteryTipPreferenceController.getCurrentBatteryTip()).isNull();
}
@Test
- public void testRestoreFromNull_shouldNotCrash() {
+ public void restoreFromNull_shouldNotCrash() {
final Bundle bundle = new Bundle();
// Battery tip list is null at this time
mBatteryTipPreferenceController.saveInstanceState(bundle);
@@ -124,7 +118,7 @@
}
@Test
- public void testHandlePreferenceTreeClick_noDialog_invokeCallback() {
+ public void handlePreferenceTreeClick_noDialog_invokeCallback() {
when(mBatteryTip.getType()).thenReturn(SMART_BATTERY_MANAGER);
List<BatteryTip> batteryTips = new ArrayList<>();
batteryTips.add(mBatteryTip);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
index 3f89f9b..4efd850 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
@@ -17,8 +17,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +25,7 @@
import android.util.Log;
import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -34,12 +33,13 @@
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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.RuntimeEnvironment;
import org.robolectric.shadows.ShadowLog;
@RunWith(RobolectricTestRunner.class)
@@ -49,23 +49,22 @@
private FakeFeatureFactory mFeatureFactory;
private BatteryDefenderTip mBatteryDefenderTip;
private MetricsFeatureProvider mMetricsFeatureProvider;
+ private CardPreference mCardPreference;
+ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private BatteryTip mBatteryTip;
@Mock private Preference mPreference;
- @Mock private CardPreference mCardPreference;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
-
+ mContext = ApplicationProvider.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
- mContext = RuntimeEnvironment.application;
mBatteryDefenderTip =
- new BatteryDefenderTip(BatteryTip.StateType.NEW, false /* isPluggedIn */);
+ new BatteryDefenderTip(BatteryTip.StateType.NEW, /* isPluggedIn= */ false);
+ mCardPreference = new CardPreference(mContext);
when(mPreference.getContext()).thenReturn(mContext);
- when(mCardPreference.getContext()).thenReturn(mContext);
}
@Test
@@ -87,7 +86,7 @@
}
@Test
- public void testLog_logMetric() {
+ public void log_logMetric() {
mBatteryDefenderTip.updateState(mBatteryTip);
mBatteryDefenderTip.log(mContext, mMetricsFeatureProvider);
@@ -108,7 +107,7 @@
mBatteryDefenderTip.updatePreference(mCardPreference);
- verify(mCardPreference).setPrimaryButtonText(expectedText);
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo(expectedText);
}
@Test
@@ -117,46 +116,31 @@
mBatteryDefenderTip.updatePreference(mCardPreference);
- verify(mCardPreference).setSecondaryButtonText(expected);
+ assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo(expected);
}
@Test
public void updatePreference_shouldSetPrimaryButtonVisible() {
mBatteryDefenderTip.updatePreference(mCardPreference);
- verify(mCardPreference).setPrimaryButtonVisibility(true);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
}
@Test
public void updatePreference_whenCharging_setPrimaryButtonVisibleToBeTrue() {
mBatteryDefenderTip =
- new BatteryDefenderTip(BatteryTip.StateType.NEW, true /* isPluggedIn */);
+ new BatteryDefenderTip(BatteryTip.StateType.NEW, /* isPluggedIn= */ true);
mBatteryDefenderTip.updatePreference(mCardPreference);
- verify(mCardPreference).setPrimaryButtonVisibility(true);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
}
@Test
public void updatePreference_whenNotCharging_setSecondaryButtonVisibleToBeFalse() {
mBatteryDefenderTip.updatePreference(mCardPreference);
- verify(mCardPreference).setSecondaryButtonVisibility(false);
- }
-
- @Test
- public void updatePreference_whenGetChargingStatusFailed_setSecondaryButtonVisibleToBeFalse() {
- fakeGetChargingStatusFailed();
-
- mBatteryDefenderTip.updatePreference(mCardPreference);
-
- verify(mCardPreference).setSecondaryButtonVisibility(false);
- }
-
- private void fakeGetChargingStatusFailed() {
- Context mockContext = mock(Context.class);
- when(mockContext.getString(anyInt())).thenReturn("fake_string");
- when(mCardPreference.getContext()).thenReturn(mockContext);
+ assertThat(mCardPreference.getSecondaryButtonVisibility()).isFalse();
}
private String getLastErrorLog() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
index ea72ff6..097f484 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
@@ -20,11 +20,10 @@
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.View;
import androidx.annotation.DrawableRes;
import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.widget.CardPreference;
@@ -32,10 +31,12 @@
import com.android.settingslib.testutils.DrawableTestHelper;
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.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
@@ -47,13 +48,15 @@
private static final String SUMMARY = "summary";
@DrawableRes private static final int ICON_ID = R.drawable.ic_fingerprint;
+ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
private Context mContext;
private TestBatteryTip mBatteryTip;
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
mBatteryTip = new TestBatteryTip();
+ mContext = ApplicationProvider.getApplicationContext();
}
@Test
@@ -84,19 +87,14 @@
@Test
public void updatePreference_resetLayoutState() {
- mContext.setTheme(R.style.Theme_Settings);
- PreferenceViewHolder holder =
- PreferenceViewHolder.createInstanceForTests(
- View.inflate(
- mContext, R.layout.card_preference_layout, /* parent= */ null));
CardPreference cardPreference = new CardPreference(mContext);
- cardPreference.onBindViewHolder(holder);
cardPreference.setPrimaryButtonVisibility(true);
+ cardPreference.setSecondaryButtonVisibility(true);
mBatteryTip.updatePreference(cardPreference);
- View view = holder.findViewById(R.id.card_preference_buttons);
- assertThat(view.getVisibility()).isEqualTo(View.GONE);
+ assertThat(cardPreference.getPrimaryButtonVisibility()).isFalse();
+ assertThat(cardPreference.getSecondaryButtonVisibility()).isFalse();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
index c66cf37..7a23332 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
@@ -25,6 +25,7 @@
import android.util.Log;
import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -32,12 +33,13 @@
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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.RuntimeEnvironment;
import org.robolectric.shadows.ShadowLog;
@RunWith(RobolectricTestRunner.class)
@@ -47,22 +49,21 @@
private FakeFeatureFactory mFeatureFactory;
private IncompatibleChargerTip mIncompatibleChargerTip;
private MetricsFeatureProvider mMetricsFeatureProvider;
+ private CardPreference mCardPreference;
+ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private BatteryTip mBatteryTip;
@Mock private Preference mPreference;
- @Mock private CardPreference mCardPreference;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
-
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
- mContext = RuntimeEnvironment.application;
+ mContext = ApplicationProvider.getApplicationContext();
mIncompatibleChargerTip = new IncompatibleChargerTip(BatteryTip.StateType.NEW);
+ mCardPreference = new CardPreference(mContext);
when(mPreference.getContext()).thenReturn(mContext);
- when(mCardPreference.getContext()).thenReturn(mContext);
}
@Test
@@ -107,13 +108,13 @@
mIncompatibleChargerTip.updatePreference(mCardPreference);
- verify(mCardPreference).setPrimaryButtonText(expected);
+ assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo(expected);
}
@Test
public void updatePreference_shouldSetSecondaryButtonVisible() {
mIncompatibleChargerTip.updatePreference(mCardPreference);
- verify(mCardPreference).setPrimaryButtonVisibility(true);
+ assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
}
private String getLastErrorLog() {
diff --git a/tests/spa_unit/src/com/android/settings/development/SensitiveContentProtectionPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/development/SensitiveContentProtectionPreferenceControllerTest.kt
new file mode 100644
index 0000000..bb30619
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/development/SensitiveContentProtectionPreferenceControllerTest.kt
@@ -0,0 +1,151 @@
+/*
+ * 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.content.Context
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.provider.Settings
+import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import androidx.preference.SwitchPreference
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING
+import com.android.server.notification.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION
+import com.android.settings.development.SensitiveContentProtectionPreferenceController.Companion.SETTING_VALUE_OFF
+import com.android.settings.development.SensitiveContentProtectionPreferenceController.Companion.SETTING_VALUE_ON
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class SensitiveContentProtectionPreferenceControllerTest {
+ @get:Rule
+ val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
+ @get:Rule
+ val mocks = MockitoJUnit.rule()
+
+ @Mock
+ private lateinit var preference: SwitchPreference
+
+ @Mock
+ private lateinit var screen: PreferenceScreen
+
+ private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
+ private lateinit var controller: SensitiveContentProtectionPreferenceController
+
+ @Before
+ fun setUp() {
+ controller = SensitiveContentProtectionPreferenceController(context)
+ whenever(screen.findPreference<Preference>(controller.getPreferenceKey()))
+ .thenReturn(preference)
+ controller.displayPreference(screen)
+ }
+
+ @Test
+ fun onPreferenceChange_settingEnabled_shouldDisableSensitiveContentProtection() {
+ controller.onPreferenceChange(preference, true /* new value */)
+ val mode = Settings.Global.getInt(
+ context.contentResolver,
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ -1 /* default */
+ )
+
+ assertEquals(mode, SETTING_VALUE_ON)
+ }
+
+ @Test
+ fun onPreferenceChange_settingDisabled_shouldEnableSensitiveContentProtection() {
+ controller.onPreferenceChange(preference, false /* new value */)
+ val mode = Settings.Global.getInt(
+ context.contentResolver,
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ -1 /* default */
+ )
+
+ assertEquals(mode, SETTING_VALUE_OFF)
+ }
+
+ @Test
+ fun updateState_settingEnabled_preferenceShouldBeChecked() {
+ Settings.Global.putInt(
+ context.contentResolver,
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ SETTING_VALUE_ON
+ )
+ controller.updateState(preference)
+
+ verify(preference).isChecked = true
+ }
+
+ @Test
+ fun updateState_settingDisabled_preferenceShouldNotBeChecked() {
+ Settings.Global.putInt(
+ context.contentResolver,
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ SETTING_VALUE_OFF
+ )
+ controller.updateState(preference)
+
+ verify(preference).isChecked = false
+ }
+
+ @Test
+ fun onDeveloperOptionsSwitchDisabled_preferenceShouldBeDisabled() {
+ controller.onDeveloperOptionsSwitchDisabled()
+ val mode = Settings.Global.getInt(
+ context.contentResolver,
+ DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+ -1 /* default */
+ )
+
+ assertEquals(mode, SETTING_VALUE_OFF)
+ verify(preference).isChecked = false
+ verify(preference).isEnabled = false
+ }
+
+ @Test
+ @RequiresFlagsDisabled(
+ FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION,
+ FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun isAvailable_flagsDisabled_returnFalse() {
+ assertFalse(controller.isAvailable)
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
+ fun isAvailable_sensitiveNotificationAppProtectionEnabled_returnTrue() {
+ assertTrue(controller.isAvailable)
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun isAvailable_screenshareNotificationHidingEnabled_returnTrue() {
+ assertTrue(controller.isAvailable)
+ }
+}
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt
index 74aa861..537764a 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt
@@ -21,7 +21,6 @@
import android.content.Context
import android.content.pm.ApplicationInfo
import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.lifecycle.MutableLiveData
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
@@ -270,7 +269,7 @@
private class FakeAppOpsController(private val fakeMode: Int) : IAppOpsController {
var setAllowedCalledWith: Boolean? = null
- override val mode = MutableLiveData(fakeMode)
+ override val mode = flowOf(fakeMode)
override fun setAllowed(allowed: Boolean) {
setAllowedCalledWith = allowed
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt
index cc2c1e1..b61e3a9 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt
@@ -24,8 +24,9 @@
import android.apphibernation.AppHibernationManager
import android.content.Context
import android.content.pm.ApplicationInfo
-import android.content.pm.Flags
+import android.content.pm.Flags as PmFlags
import android.os.Build
+import android.os.SystemProperties
import android.permission.PermissionControllerManager
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_ELIGIBLE
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
@@ -48,6 +49,7 @@
import com.android.settings.R
import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED
import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS
+import com.android.settings.flags.Flags
import com.android.settings.testutils.TestDeviceConfig
import com.android.settings.testutils.mockAsUser
import com.android.settingslib.spaprivileged.framework.common.appHibernationManager
@@ -161,8 +163,8 @@
}
private fun isArchivingEnabled() =
- Flags.archiving() || "true" == System.getProperty("pm.archiving.enabled")
-
+ PmFlags.archiving() || SystemProperties.getBoolean("pm.archiving.enabled", false)
+ || Flags.appArchiving()
@Test
fun `An app targets Q with ops mode default when hibernation targets pre S - not exempted`() {
mockOpsMode(MODE_DEFAULT)
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/MediaRoutingControlTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/MediaRoutingControlTest.kt
index 2f4740e..990ec5c 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/MediaRoutingControlTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/specialaccess/MediaRoutingControlTest.kt
@@ -24,7 +24,6 @@
import android.content.Context
import android.content.pm.ApplicationInfo
import android.platform.test.flag.junit.SetFlagsRule
-import androidx.lifecycle.MutableLiveData
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.media.flags.Flags
@@ -33,6 +32,7 @@
import com.android.settingslib.spaprivileged.model.app.IAppOpsController
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -223,16 +223,13 @@
private class FakeAppOpsController(fakeMode: Int) : IAppOpsController {
- override val mode = MutableLiveData(fakeMode)
+ override val mode = MutableStateFlow(fakeMode)
override fun setAllowed(allowed: Boolean) {
- if (allowed)
- mode.postValue(AppOpsManager.MODE_ALLOWED)
- else
- mode.postValue(AppOpsManager.MODE_ERRORED)
+ mode.value = if (allowed) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
}
- override fun getMode(): Int = mode.value!!
+ override fun getMode(): Int = mode.value
}
companion object {
diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
index f6356bc..71d419e 100644
--- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
@@ -114,7 +114,7 @@
@Test
public void setSafetySourceData_whenSafetyCenterIsEnabled_withoutBiometrics_setsNullData() {
- when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false);
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
when(mFaceManager.isHardwareDetected()).thenReturn(false);
diff --git a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
index 3538727..e528c4e 100644
--- a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
@@ -413,6 +413,8 @@
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mScreenLockPreferenceDetailsUtils.isPasswordQualityManaged(anyInt(), any()))
.thenReturn(false);
+ when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(true);
+ when(mScreenLockPreferenceDetailsUtils.shouldShowGearMenu()).thenReturn(true);
LockScreenSafetySource.setSafetySourceData(
mApplicationContext, mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED);
diff --git a/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java b/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java
index 9851a1a..31f7878 100644
--- a/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java
+++ b/tests/unit/src/com/android/settings/security/SecurityAdvancedSettingsTest.java
@@ -107,7 +107,7 @@
@Test
public void whenSafetyCenterIsEnabled_pageIndexExcluded() throws Exception {
- when(mSafetyCenterManagerWrapper.isEnabled(any())).thenReturn(false);
+ when(mSafetyCenterManagerWrapper.isEnabled(any())).thenReturn(true);
BaseSearchIndexProvider indexProvider = SecurityAdvancedSettings.SEARCH_INDEX_DATA_PROVIDER;
List<String> allXmlKeys = TestUtils.getAllXmlKeys(mContext, indexProvider);