Merge "Adding configuration to timeout for "Android is starting message""
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a654bcb..bf64ebe 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,10 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="com.android.settings"
- coreApp="true"
- android:sharedUserId="android.uid.system">
+ package="com.android.settings"
+ coreApp="true"
+ android:sharedUserId="android.uid.system">
- <original-package android:name="com.android.settings" />
+ <original-package android:name="com.android.settings"/>
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
@@ -115,6 +114,7 @@
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
<uses-permission android:name="android.permission.QUERY_ADMIN_POLICY" />
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
+ <uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
<uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" />
<application
@@ -2920,6 +2920,24 @@
android:value="true" />
</activity>
+ <activity android:name=".dream.DreamSetupActivity"
+ android:exported="true"
+ android:immersive="true"
+ android:theme="@style/SudThemeGlif.DayNight"
+ android:icon="@drawable/ic_settings_display">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.settings.suggested.category.SCREEN_SAVER"/>
+ </intent-filter>
+ <meta-data android:name="com.android.settings.is_supported"
+ android:resource="@bool/dream_setup_supported"/>
+ <meta-data android:name="com.android.settings.title"
+ android:resource="@string/dream_setup_title"/>
+ <meta-data android:name="com.android.settings.summary"
+ android:resource="@string/dream_setup_description"/>
+ <meta-data android:name="com.android.settings.icon_tintable" android:value="true"/>
+ </activity>
+
<activity
android:name="Settings$UserSettingsActivity"
android:label="@string/user_settings_title"
diff --git a/res/color/dream_card_color_state_list.xml b/res/color/dream_card_color_state_list.xml
index 8cd5bc9..b5de7b4 100644
--- a/res/color/dream_card_color_state_list.xml
+++ b/res/color/dream_card_color_state_list.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:state_activated="true" android:color="?androidprv:attr/colorSurfaceVariant"/>
+ <item android:state_selected="true" android:color="?androidprv:attr/colorSurfaceVariant"/>
<item android:color="?androidprv:attr/colorSurfaceHighlight"/>
</selector>
\ No newline at end of file
diff --git a/res/layout/add_supervised_user.xml b/res/layout/add_supervised_user.xml
index b95e0f7..33032bd 100644
--- a/res/layout/add_supervised_user.xml
+++ b/res/layout/add_supervised_user.xml
@@ -15,12 +15,18 @@
~ limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp"
+ android:orientation="vertical">
<Button
android:id="@+id/createSupervisedUser"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@*android:string/supervised_user_creation_label" />
-</FrameLayout>
\ No newline at end of file
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/placeholder_activity" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/dream_setup_layout.xml b/res/layout/dream_setup_layout.xml
new file mode 100644
index 0000000..31a0fb1
--- /dev/null
+++ b/res/layout/dream_setup_layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<com.google.android.setupdesign.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/setup_wizard_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:icon="@drawable/ic_settings_display"
+ app:sucHeaderText="@string/dream_setup_title"
+ app:sudDescriptionText="@string/dream_setup_description">
+
+ <RelativeLayout
+ android:id="@+id/dream_container"
+ style="@style/SudContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/dream_setup_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </RelativeLayout>
+
+</com.google.android.setupdesign.GlifLayout>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0e39d6d..a3e53f5 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1619,4 +1619,22 @@
<item>0</item>
<item>1</item>
</string-array>
+
+ <!-- Setting entries for timing out to user 0 when docked. -->
+ <string-array name="switch_to_user_zero_when_docked_timeout_entries">
+ <item>Never</item>
+ <item>After 1 minute</item>
+ <item>After 5 minutes</item>
+ </string-array>
+
+ <!-- Setting values for timing out to user 0 when docked. [DO NOT TRANSLATE] -->
+ <string-array name="switch_to_user_zero_when_docked_timeout_values" translatable="false">
+ <!-- Never -->
+ <item>0</item>
+ <!-- 1 minute -->
+ <item>60000</item>
+ <!-- 5 minutes -->
+ <item>300000</item>
+ </string-array>
+
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 9069340..6a7c15b 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -590,4 +590,7 @@
Take the "Unrestricted data" page as the example, the visible app icons could be 15
on 6.4 inches screen size whether the font size and display size are both small. -->
<integer name="config_num_visible_app_icons">20</integer>
+
+ <!-- Whether the dream setup activity should be enabled as part of setupwizard -->
+ <bool name="dream_setup_supported">false</bool>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7f26c8d..a50c51a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5846,6 +5846,8 @@
<string name="fast_pair_settings_summary">Nearby detection of Fast Pair bluetooth devices.</string>
<!-- Title for Fast Pair main switch preferences. [CHAR LIMIT=50] -->
<string name="fast_pair_main_switch_title">Scan for nearby devices</string>
+ <!-- Title for Fast Pair saved devices preferences. [CHAR LIMIT=50] -->
+ <string name="fast_pair_saved_devices_title">Saved devices</string>
<!-- Printing settings -->
<skip />
@@ -7543,6 +7545,9 @@
<string name="user_lockscreen_settings">Lock screen settings</string>
<!-- User settings item to allow creating new users from locks screen [CHAR LIMIT=50] -->
<string name="user_add_on_lockscreen_menu">Add users from lock screen</string>
+ <!-- User settings item to allow the system to automatically switch back to the admin user when
+ the device is docked. [CHAR LIMIT=50] -->
+ <string name="switch_to_user_zero_when_docked">Switch to admin user when docked</string>
<!-- User (self) removal confirmation title [CHAR LIMIT=30] -->
<string name="user_confirm_remove_self_title">Delete yourself?</string>
@@ -13847,6 +13852,10 @@
<string name="dream_complications_picker_category">Choose more options</string>
<!-- The title of the category to show for the screensaver miscellaneous settings [CHAR LIMIT=none] -->
<string name="dream_more_settings_category">More settings</string>
+ <!-- The title of the screen saver setup page [CHAR LIMIT=none] -->
+ <string name="dream_setup_title">Customize your screen saver</string>
+ <!-- The description of the screen saver setup page [CHAR LIMIT=none] -->
+ <string name="dream_setup_description">Choose what you’ll see on your screen when your device is not in use.</string>
<!-- Button to customize the screensaver [CHAR LIMIT=20] -->
<string name="customize_button_title">Customize</string>
@@ -13863,4 +13872,7 @@
<string name="reboot_dialog_reboot_now">Reboot now</string>
<!-- Text on the dialog button to reboot the device later [CHAR LIMIT=50] -->
<string name="reboot_dialog_reboot_later">Reboot later</string>
+
+ <!-- Text to explain an activity is a temporary placeholder [CHAR LIMIT=none] -->
+ <string name="placeholder_activity" translatable="false">*This is a temporary placeholder fallback activity.</string>
</resources>
diff --git a/res/xml/fast_pair_settings.xml b/res/xml/fast_pair_settings.xml
index 3fd306f..95662fc 100644
--- a/res/xml/fast_pair_settings.xml
+++ b/res/xml/fast_pair_settings.xml
@@ -25,4 +25,8 @@
android:key="fast_pair_scan_switch"
android:title="@string/fast_pair_main_switch_title" />
+ <Preference
+ android:key="saved_devices"
+ android:title="@string/fast_pair_saved_devices_title" />
+
</PreferenceScreen>
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index b3dc2ea..d5e61d0 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -56,4 +56,11 @@
android:order="105"
settings:allowDividerAbove="true"/>
+ <com.android.settingslib.RestrictedPreference
+ android:key="timeout_to_user_zero_preference"
+ android:title="@string/switch_to_user_zero_when_docked"
+ android:order="106"
+ android:fragment="com.android.settings.users.TimeoutToUserZeroSettings"
+ settings:controller="com.android.settings.users.TimeoutToUserZeroPreferenceController"/>
+
</PreferenceScreen>
diff --git a/res/xml/user_timeout_to_user_zero_settings.xml b/res/xml/user_timeout_to_user_zero_settings.xml
new file mode 100644
index 0000000..54121a3
--- /dev/null
+++ b/res/xml/user_timeout_to_user_zero_settings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/switch_to_user_zero_when_docked"/>
diff --git a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
index aee360e..164cfd9 100644
--- a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
+++ b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
@@ -18,6 +18,7 @@
import static com.android.settings.widget.EntityHeaderController.ActionType;
import android.app.Activity;
+import android.app.LocaleConfig;
import android.app.LocaleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -289,12 +290,18 @@
@VisibleForTesting
void handleSupportedLocales() {
- //TODO Waiting for PackageManager api
- String[] languages = getAssetSystemLocales();
-
- for (String language : languages) {
- mSupportedLocales.add(Locale.forLanguageTag(language));
+ LocaleList localeList = getPackageLocales();
+ if (localeList == null) {
+ String[] languages = getAssetSystemLocales();
+ for (String language : languages) {
+ mSupportedLocales.add(Locale.forLanguageTag(language));
+ }
+ } else {
+ for (int i = 0; i < localeList.size(); i++) {
+ mSupportedLocales.add(localeList.get(i));
+ }
}
+
if (mSuggestedLocales != null || !mSuggestedLocales.isEmpty()) {
mSupportedLocales.removeAll(mSuggestedLocales);
}
@@ -349,9 +356,23 @@
packageManager.getPackageInfo(mPackageName, PackageManager.MATCH_ALL)
.applicationInfo).getAssets().getNonSystemLocales();
} catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Can not found the package name : " + e);
+ Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
}
return new String[0];
}
+
+ @VisibleForTesting
+ LocaleList getPackageLocales() {
+ try {
+ LocaleConfig localeConfig =
+ new LocaleConfig(mContext.createPackageContext(mPackageName, 0));
+ if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
+ return localeConfig.getSupportedLocales();
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
+ }
+ return null;
+ }
}
}
diff --git a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
index d922867..f0b3329 100644
--- a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
@@ -20,6 +20,8 @@
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED;
+import static android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM;
+import static android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED;
@@ -29,6 +31,7 @@
import android.apphibernation.AppHibernationManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.permission.PermissionControllerManager;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.Slog;
@@ -51,7 +54,10 @@
private static final String TAG = "HibernationSwitchPrefController";
private String mPackageName;
private final AppOpsManager mAppOpsManager;
+ private final PermissionControllerManager mPermissionControllerManager;
private int mPackageUid;
+ private boolean mHibernationEligibilityLoaded;
+ private int mHibernationEligibility = HIBERNATION_ELIGIBILITY_UNKNOWN;
@VisibleForTesting
boolean mIsPackageSet;
private boolean mIsPackageExemptByDefault;
@@ -60,6 +66,7 @@
String preferenceKey) {
super(context, preferenceKey);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mPermissionControllerManager = context.getSystemService(PermissionControllerManager.class);
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -109,10 +116,27 @@
}
}
+ private boolean isAppEligibleForHibernation() {
+ return mHibernationEligibilityLoaded
+ && mHibernationEligibility != HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
+ && mHibernationEligibility != HIBERNATION_ELIGIBILITY_UNKNOWN;
+ }
+
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- ((SwitchPreference) preference).setChecked(!isPackageHibernationExemptByUser());
+ ((SwitchPreference) preference).setChecked(isAppEligibleForHibernation()
+ && !isPackageHibernationExemptByUser());
+ preference.setEnabled(isAppEligibleForHibernation());
+ if (!mHibernationEligibilityLoaded) {
+ mPermissionControllerManager.getHibernationEligibility(mPackageName,
+ mContext.getMainExecutor(),
+ eligibility -> {
+ mHibernationEligibility = eligibility;
+ mHibernationEligibilityLoaded = true;
+ updateState(preference);
+ });
+ }
}
@VisibleForTesting
diff --git a/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java b/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
index 88dda29..7514577 100644
--- a/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
+++ b/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
@@ -17,9 +17,12 @@
package com.android.settings.development;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
@@ -34,6 +37,8 @@
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+import java.util.List;
+
public abstract class AbstractBluetoothA2dpPreferenceController extends
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
PreferenceControllerMixin, BluetoothServiceConnectionListener, LifecycleObserver,
@@ -48,11 +53,15 @@
private final String[] mListValues;
private final String[] mListSummaries;
+ @VisibleForTesting
+ BluetoothAdapter mBluetoothAdapter;
+
public AbstractBluetoothA2dpPreferenceController(Context context, Lifecycle lifecycle,
BluetoothA2dpConfigStore store) {
super(context);
mBluetoothA2dpConfigStore = store;
+ mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter();
mListValues = getListValues();
mListSummaries = getListSummaries();
@@ -82,13 +91,11 @@
final BluetoothCodecConfig codecConfig = mBluetoothA2dpConfigStore.createCodecConfig();
synchronized (mBluetoothA2dpConfigStore) {
- if (mBluetoothA2dp != null) {
- BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
- if (activeDevice == null) {
- return false;
- }
- setCodecConfigPreference(activeDevice, codecConfig);
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
+ if (activeDevice == null) {
+ return false;
}
+ setCodecConfigPreference(activeDevice, codecConfig);
}
// Because the setting is not persisted into permanent storage, we cannot call update state
// here to update the preference.
@@ -106,7 +113,7 @@
@Override
public void updateState(Preference preference) {
- BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null || getCodecConfig(activeDevice) == null || mPreference == null) {
return;
}
@@ -184,7 +191,7 @@
void setCodecConfigPreference(BluetoothDevice device,
BluetoothCodecConfig config) {
BluetoothDevice bluetoothDevice =
- (device != null) ? device : mBluetoothA2dp.getActiveDevice();
+ (device != null) ? device : getA2dpActiveDevice();
if (bluetoothDevice == null) {
return;
}
@@ -195,7 +202,7 @@
BluetoothCodecConfig getCodecConfig(BluetoothDevice device) {
if (mBluetoothA2dp != null) {
BluetoothDevice bluetoothDevice =
- (device != null) ? device : mBluetoothA2dp.getActiveDevice();
+ (device != null) ? device : getA2dpActiveDevice();
if (bluetoothDevice == null) {
return null;
}
@@ -206,4 +213,13 @@
}
return null;
}
+
+ private BluetoothDevice getA2dpActiveDevice() {
+ if (mBluetoothAdapter == null) {
+ return null;
+ }
+ List<BluetoothDevice> activeDevices =
+ mBluetoothAdapter.getActiveDevices(BluetoothProfile.A2DP);
+ return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
+ }
}
diff --git a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
index fb75695..bd8169a 100644
--- a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
@@ -16,8 +16,9 @@
package com.android.settings.development;
-import android.bluetooth.BluetoothManager;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.SystemProperties;
import androidx.annotation.VisibleForTesting;
@@ -39,13 +40,20 @@
static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY =
"persist.bluetooth.maxconnectedaudiodevices";
- private final int mDefaultMaxConnectedAudioDevices;
+ private int mDefaultMaxConnectedAudioDevices = 0;
public BluetoothMaxConnectedAudioDevicesPreferenceController(Context context) {
super(context);
- BluetoothManager mBluetoothManager = context.getSystemService(BluetoothManager.class);
- mDefaultMaxConnectedAudioDevices = mBluetoothManager.getAdapter()
- .getMaxConnectedAudioDevices();
+
+ try {
+ Resources res = context.getPackageManager().getResourcesForApplication(
+ "com.android.bluetooth");
+ mDefaultMaxConnectedAudioDevices = res.getInteger(res.getIdentifier(
+ "config_bluetooth_max_connected_audio_devices",
+ "integer", "com.android.bluetooth"));
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
}
@Override
diff --git a/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceController.java b/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceController.java
index 1af6e96..62bcffb 100644
--- a/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceController.java
+++ b/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceController.java
@@ -84,7 +84,7 @@
}
writeConfigurationValues(index);
final BluetoothCodecConfig codecConfig = mBluetoothA2dpConfigStore.createCodecConfig();
- BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice != null) {
bluetoothA2dp.setCodecConfigPreference(activeDevice, codecConfig);
}
@@ -153,7 +153,7 @@
if (bluetoothA2dp == null) {
return null;
}
- BluetoothDevice activeDevice = bluetoothA2dp.getActiveDevice();
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null) {
Log.d(TAG, "Unable to get current codec config. No active device.");
return null;
@@ -178,7 +178,7 @@
return null;
}
BluetoothDevice bluetoothDevice =
- (device != null) ? device : bluetoothA2dp.getActiveDevice();
+ (device != null) ? device : getA2dpActiveDevice();
if (bluetoothDevice == null) {
return null;
}
@@ -195,7 +195,7 @@
* @return {@link BluetoothCodecConfig}.
*/
protected BluetoothCodecConfig getSelectableByCodecType(int codecTypeValue) {
- BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null) {
Log.d(TAG, "Unable to get selectable config. No active device.");
return null;
diff --git a/src/com/android/settings/development/bluetooth/AbstractBluetoothPreferenceController.java b/src/com/android/settings/development/bluetooth/AbstractBluetoothPreferenceController.java
index 6735115..d3fab67 100644
--- a/src/com/android/settings/development/bluetooth/AbstractBluetoothPreferenceController.java
+++ b/src/com/android/settings/development/bluetooth/AbstractBluetoothPreferenceController.java
@@ -17,8 +17,14 @@
package com.android.settings.development.bluetooth;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.development.BluetoothA2dpConfigStore;
import com.android.settings.development.BluetoothServiceConnectionListener;
@@ -27,6 +33,8 @@
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+import java.util.List;
+
/**
* Abstract class for Bluetooth A2DP config controller in developer option.
*/
@@ -36,12 +44,16 @@
protected volatile BluetoothA2dp mBluetoothA2dp;
+ @VisibleForTesting
+ BluetoothAdapter mBluetoothAdapter;
+
public AbstractBluetoothPreferenceController(Context context, Lifecycle lifecycle,
BluetoothA2dpConfigStore store) {
super(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
+ mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter();
}
@Override
@@ -82,4 +94,13 @@
*/
void onBluetoothHDAudioEnabled(boolean enabled);
}
+
+ protected BluetoothDevice getA2dpActiveDevice() {
+ if (mBluetoothAdapter == null) {
+ return null;
+ }
+ List<BluetoothDevice> activeDevices =
+ mBluetoothAdapter.getActiveDevices(BluetoothProfile.A2DP);
+ return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
+ }
}
diff --git a/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceController.java b/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceController.java
index 5f916f3..a65a1ba 100644
--- a/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceController.java
+++ b/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceController.java
@@ -69,7 +69,7 @@
if (bluetoothA2dp == null) {
return index;
}
- final BluetoothDevice activeDevice = bluetoothA2dp.getActiveDevice();
+ final BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null) {
Log.d(TAG, "Unable to get selectable index. No Active Bluetooth device");
return index;
@@ -93,7 +93,7 @@
int codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
switch (index) {
case 0:
- final BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
+ final BluetoothDevice activeDevice = getA2dpActiveDevice();
codecTypeValue = getHighestCodec(mBluetoothA2dp, activeDevice,
getSelectableConfigs(activeDevice));
codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
diff --git a/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceController.java b/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceController.java
index d4ca4e5..8092194 100644
--- a/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceController.java
+++ b/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceController.java
@@ -52,7 +52,7 @@
mPreference.setEnabled(false);
return;
}
- final BluetoothDevice activeDevice = bluetoothA2dp.getActiveDevice();
+ final BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null) {
Log.e(TAG, "Active device is null. To disable HD audio button");
mPreference.setEnabled(false);
@@ -84,7 +84,7 @@
final int prefValue = enabled
? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
: BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
- BluetoothDevice activeDevice = bluetoothA2dp.getActiveDevice();
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
if (activeDevice == null) {
mPreference.setEnabled(false);
return true;
diff --git a/src/com/android/settings/display/darkmode/BedtimeSettings.java b/src/com/android/settings/display/darkmode/BedtimeSettings.java
index 9714afa..d9a458c 100644
--- a/src/com/android/settings/display/darkmode/BedtimeSettings.java
+++ b/src/com/android/settings/display/darkmode/BedtimeSettings.java
@@ -16,19 +16,17 @@
package com.android.settings.display.darkmode;
+import static android.provider.Settings.ACTION_BEDTIME_SETTINGS;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
/** Manages Digital Wellbeing bedtime settings' intents. */
public final class BedtimeSettings {
- @VisibleForTesting
- public static final String ACTION_BEDTIME_SETTINGS = "android.settings.BEDTIME_SETTINGS";
-
private final Context mContext;
private final PackageManager mPackageManager;
private final String mWellbeingPackage;
diff --git a/src/com/android/settings/dream/DreamAdapter.java b/src/com/android/settings/dream/DreamAdapter.java
index 8727733..e674546 100644
--- a/src/com/android/settings/dream/DreamAdapter.java
+++ b/src/com/android/settings/dream/DreamAdapter.java
@@ -39,11 +39,12 @@
*/
class DreamAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<IDreamItem> mItemList;
+ private int mLastSelectedPos = -1;
/**
* View holder for each {@link IDreamItem}.
*/
- private static class DreamViewHolder extends RecyclerView.ViewHolder {
+ private class DreamViewHolder extends RecyclerView.ViewHolder {
private final ImageView mIconView;
private final TextView mTitleView;
private final ImageView mPreviewView;
@@ -62,7 +63,7 @@
/**
* Bind the view at the given position, populating the view with the provided data.
*/
- public void bindView(IDreamItem item) {
+ public void bindView(IDreamItem item, int position) {
mTitleView.setText(item.getTitle());
final Drawable previewImage = item.getPreviewImage();
@@ -73,20 +74,32 @@
mPreviewView.setVisibility(View.GONE);
}
- final Drawable icon = item.getIcon();
+ final Drawable icon = item.isActive()
+ ? mContext.getDrawable(R.drawable.ic_dream_check_circle)
+ : item.getIcon();
if (icon instanceof VectorDrawable) {
icon.setTint(Utils.getColorAttrDefaultColor(mContext,
com.android.internal.R.attr.colorAccentPrimaryVariant));
}
mIconView.setImageDrawable(icon);
- if (item.allowCustomization()) {
- mCustomizeButton.setVisibility(View.VISIBLE);
- mCustomizeButton.setOnClickListener(v -> item.onCustomizeClicked());
+
+ if (item.isActive()) {
+ mLastSelectedPos = position;
+ itemView.setSelected(true);
} else {
- mCustomizeButton.setVisibility(View.GONE);
+ itemView.setSelected(false);
}
- itemView.setOnClickListener(v -> item.onItemClicked());
- itemView.setActivated(item.isActive());
+
+ mCustomizeButton.setOnClickListener(v -> item.onCustomizeClicked());
+ mCustomizeButton.setVisibility(item.allowCustomization() ? View.VISIBLE : View.GONE);
+
+ itemView.setOnClickListener(v -> {
+ item.onItemClicked();
+ if (mLastSelectedPos > -1 && mLastSelectedPos != position) {
+ notifyItemChanged(mLastSelectedPos);
+ }
+ notifyItemChanged(position);
+ });
}
}
@@ -104,7 +117,7 @@
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
- ((DreamViewHolder) viewHolder).bindView(mItemList.get(i));
+ ((DreamViewHolder) viewHolder).bindView(mItemList.get(i), i);
}
@Override
diff --git a/src/com/android/settings/dream/DreamComplicationPickerController.java b/src/com/android/settings/dream/DreamComplicationPickerController.java
index d4dcc5e..09ed8da 100644
--- a/src/com/android/settings/dream/DreamComplicationPickerController.java
+++ b/src/com/android/settings/dream/DreamComplicationPickerController.java
@@ -37,9 +37,7 @@
private static final String KEY = "dream_complication_picker";
private final DreamBackend mBackend;
- private final Drawable mEnabledDrawable;
private final Set<Integer> mSupportedComplications;
- private DreamAdapter mAdapter;
private class ComplicationItem implements IDreamItem {
private final int mComplicationType;
@@ -58,14 +56,13 @@
@Override
public Drawable getIcon() {
// TODO(b/215703483): add icon for each complication
- return mEnabled ? mEnabledDrawable : null;
+ return null;
}
@Override
public void onItemClicked() {
mEnabled = !mEnabled;
mBackend.setComplicationEnabled(mComplicationType, mEnabled);
- mAdapter.notifyDataSetChanged();
}
@Override
@@ -84,7 +81,6 @@
super(context, KEY);
mBackend = DreamBackend.getInstance(context);
mSupportedComplications = mBackend.getSupportedComplications();
- mEnabledDrawable = context.getDrawable(R.drawable.ic_dream_check_circle);
}
@Override
@@ -102,7 +98,7 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mAdapter = new DreamAdapter(mSupportedComplications.stream()
+ DreamAdapter adapter = new DreamAdapter(mSupportedComplications.stream()
.map(ComplicationItem::new)
.collect(Collectors.toList()));
@@ -110,7 +106,8 @@
if (pref != null) {
final RecyclerView recyclerView = pref.findViewById(R.id.dream_list);
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
- recyclerView.setAdapter(mAdapter);
+ recyclerView.setHasFixedSize(true);
+ recyclerView.setAdapter(adapter);
}
}
}
diff --git a/src/com/android/settings/dream/DreamPickerController.java b/src/com/android/settings/dream/DreamPickerController.java
index 60e2a34..e4081ac 100644
--- a/src/com/android/settings/dream/DreamPickerController.java
+++ b/src/com/android/settings/dream/DreamPickerController.java
@@ -31,6 +31,7 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.dream.DreamBackend;
+import com.android.settingslib.dream.DreamBackend.DreamInfo;
import com.android.settingslib.widget.LayoutPreference;
import java.util.List;
@@ -44,11 +45,10 @@
private final DreamBackend mBackend;
private final MetricsFeatureProvider mMetricsFeatureProvider;
- private final List<DreamBackend.DreamInfo> mDreamInfos;
- private final Drawable mActiveDrawable;
+ private final List<DreamInfo> mDreamInfos;
private Button mPreviewButton;
@Nullable
- private DreamBackend.DreamInfo mActiveDream;
+ private DreamInfo mActiveDream;
private DreamAdapter mAdapter;
public DreamPickerController(Context context) {
@@ -59,7 +59,7 @@
super(context, KEY);
mBackend = backend;
mDreamInfos = mBackend.getDreamInfos();
- mActiveDrawable = context.getDrawable(R.drawable.ic_dream_check_circle);
+ mActiveDream = getActiveDreamInfo(mDreamInfos);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@@ -77,8 +77,6 @@
public void updateState(Preference preference) {
super.updateState(preference);
- mActiveDream = getActiveDreamInfo();
-
mAdapter = new DreamAdapter(mDreamInfos.stream()
.map(DreamItem::new)
.collect(Collectors.toList()));
@@ -86,6 +84,7 @@
final RecyclerView recyclerView =
((LayoutPreference) preference).findViewById(R.id.dream_list);
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
+ recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(mAdapter);
mPreviewButton = ((LayoutPreference) preference).findViewById(R.id.preview_button);
@@ -101,8 +100,8 @@
}
@Nullable
- private DreamBackend.DreamInfo getActiveDreamInfo() {
- return mDreamInfos
+ private static DreamInfo getActiveDreamInfo(List<DreamInfo> dreamInfos) {
+ return dreamInfos
.stream()
.filter(d -> d.isActive)
.findFirst()
@@ -110,9 +109,9 @@
}
private class DreamItem implements IDreamItem {
- DreamBackend.DreamInfo mDreamInfo;
+ DreamInfo mDreamInfo;
- DreamItem(DreamBackend.DreamInfo dreamInfo) {
+ DreamItem(DreamInfo dreamInfo) {
mDreamInfo = dreamInfo;
}
@@ -123,14 +122,13 @@
@Override
public Drawable getIcon() {
- return isActive() ? mActiveDrawable : mDreamInfo.icon;
+ return mDreamInfo.icon;
}
@Override
public void onItemClicked() {
mActiveDream = mDreamInfo;
mBackend.setActiveDream(mDreamInfo.componentName);
- mAdapter.notifyDataSetChanged();
updatePreviewButtonState();
mMetricsFeatureProvider.action(
mContext,
diff --git a/src/com/android/settings/dream/DreamSetupActivity.java b/src/com/android/settings/dream/DreamSetupActivity.java
new file mode 100644
index 0000000..6a12671
--- /dev/null
+++ b/src/com/android/settings/dream/DreamSetupActivity.java
@@ -0,0 +1,177 @@
+/*
+ * 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.dream;
+
+import android.app.settings.SettingsEnums;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settingslib.dream.DreamBackend;
+
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+import com.google.android.setupdesign.GlifLayout;
+import com.google.android.setupdesign.util.ThemeHelper;
+import com.google.android.setupdesign.util.ThemeResolver;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * The setup activity for dreams which is displayed during setup wizard.
+ */
+public class DreamSetupActivity extends SettingsActivity {
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, DreamSetupFragment.class.getName());
+ return modIntent;
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ return DreamSetupFragment.class.getName().equals(fragmentName);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstance) {
+ setTheme(ThemeResolver.getDefault().resolve(getIntent()));
+ ThemeHelper.trySetDynamicColor(this);
+ super.onCreate(savedInstance);
+ }
+
+ @Override
+ protected boolean isToolbarEnabled() {
+ return false;
+ }
+
+ /**
+ * Fragment used to control the active dream.
+ */
+ public static class DreamSetupFragment extends SettingsPreferenceFragment {
+ private DreamBackend mBackend;
+ private DreamBackend.DreamInfo mActiveDream;
+ private FooterButton mFooterButton;
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DREAM;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.dream_setup_layout, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mBackend = DreamBackend.getInstance(getContext());
+ final List<DreamBackend.DreamInfo> dreamInfos = mBackend.getDreamInfos();
+ mActiveDream = dreamInfos.stream().filter(d -> d.isActive).findFirst().orElse(null);
+ DreamAdapter dreamAdapter = new DreamAdapter(dreamInfos.stream()
+ .map(DreamItem::new)
+ .collect(Collectors.toList()));
+
+ final RecyclerView recyclerView = view.findViewById(R.id.dream_setup_list);
+ recyclerView.setLayoutManager(new AutoFitGridLayoutManager(getContext()));
+ recyclerView.setHasFixedSize(true);
+ recyclerView.setAdapter(dreamAdapter);
+
+ final GlifLayout layout = view.findViewById(R.id.setup_wizard_layout);
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+ mFooterButton = new FooterButton.Builder(getContext())
+ .setListener(this::onPrimaryButtonClicked)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+ updateFooterButtonText();
+ mixin.setPrimaryButton(mFooterButton);
+ }
+
+ private void updateFooterButtonText() {
+ final int res = canCustomizeDream() ? R.string.wizard_next : R.string.wizard_finish;
+ mFooterButton.setText(getContext().getString(res));
+ }
+
+ private boolean canCustomizeDream() {
+ return mActiveDream != null && mActiveDream.settingsComponentName != null;
+ }
+
+ private void onPrimaryButtonClicked(View view) {
+ if (canCustomizeDream()) {
+ final Intent intent = new Intent().setComponent(mActiveDream.settingsComponentName);
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ startActivity(intent);
+ }
+
+ // Use RESULT_CANCELED here so that the user may go back and change this if they wish.
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ private class DreamItem implements IDreamItem {
+ private final DreamBackend.DreamInfo mDreamInfo;
+
+ private DreamItem(DreamBackend.DreamInfo dreamInfo) {
+ mDreamInfo = dreamInfo;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mDreamInfo.caption;
+ }
+
+ @Override
+ public Drawable getIcon() {
+ return mDreamInfo.icon;
+ }
+
+ @Override
+ public void onItemClicked() {
+ mActiveDream = mDreamInfo;
+ mBackend.setActiveDream(mDreamInfo.componentName);
+ updateFooterButtonText();
+ }
+
+ @Override
+ public Drawable getPreviewImage() {
+ return mDreamInfo.previewImage;
+ }
+
+ @Override
+ public boolean isActive() {
+ if (mActiveDream == null) {
+ return false;
+ }
+ return mDreamInfo.componentName.equals(mActiveDream.componentName);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
index e7c93dc..62f2780 100644
--- a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
+++ b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
@@ -18,13 +18,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.SystemClock;
import android.util.Log;
-import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.fuelgauge.EstimateKt;
@@ -37,11 +35,8 @@
public class DebugEstimatesLoader extends AsyncLoaderCompat<List<BatteryInfo>> {
private static final String TAG = "DebugEstimatesLoader";
- private BatteryStatsHelper mStatsHelper;
-
- public DebugEstimatesLoader(Context context, BatteryStatsHelper statsHelper) {
+ public DebugEstimatesLoader(Context context) {
super(context);
- mStatsHelper = statsHelper;
}
@Override
@@ -60,7 +55,6 @@
SystemClock.elapsedRealtime());
Intent batteryBroadcast = getContext().registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- BatteryStats stats = mStatsHelper.getStats();
BatteryUsageStats batteryUsageStats;
try {
batteryUsageStats = context.getSystemService(BatteryStatsManager.class)
diff --git a/src/com/android/settings/nearby/FastPairSettingsFragment.java b/src/com/android/settings/nearby/FastPairSettingsFragment.java
index 7657bc3..f605cf1 100644
--- a/src/com/android/settings/nearby/FastPairSettingsFragment.java
+++ b/src/com/android/settings/nearby/FastPairSettingsFragment.java
@@ -17,8 +17,17 @@
package com.android.settings.nearby;
import android.app.settings.SettingsEnums;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -34,7 +43,10 @@
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class FastPairSettingsFragment extends SettingsPreferenceFragment {
+ private static final String TAG = "FastPairSettingsFrag";
+
private static final String SCAN_SWITCH_KEY = "fast_pair_scan_switch";
+ private static final String SAVED_DEVICES_PREF_KEY = "saved_devices";
@Override
public void onCreate(Bundle icicle) {
@@ -47,6 +59,16 @@
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.FAST_PAIR_SCAN_ENABLED, isChecked ? 1 : 0));
mainSwitchPreference.setChecked(isFastPairScanAvailable());
+
+ Preference savedDevicePref = Objects.requireNonNull(
+ findPreference(SAVED_DEVICES_PREF_KEY));
+ savedDevicePref.setOnPreferenceClickListener(preference -> {
+ Intent savedDevicesIntent = getSavedDevicesIntent();
+ if (savedDevicesIntent != null && getActivity() != null) {
+ getActivity().startActivity(savedDevicesIntent);
+ }
+ return true;
+ });
}
@Override
@@ -71,4 +93,42 @@
return Settings.Secure.getInt(getContentResolver(),
Settings.Secure.FAST_PAIR_SCAN_ENABLED, 1) != 0;
}
+
+ @Nullable
+ private ComponentName getSavedDevicesComponent() {
+ String savedDevicesComponent = Settings.Secure.getString(
+ getContentResolver(),
+ Settings.Secure.NEARBY_FAST_PAIR_SETTINGS_DEVICES_COMPONENT);
+ if (TextUtils.isEmpty(savedDevicesComponent)) {
+ savedDevicesComponent = getString(
+ com.android.internal.R.string.config_defaultNearbyFastPairSettingsDevicesComponent);
+ }
+
+ if (TextUtils.isEmpty(savedDevicesComponent)) {
+ return null;
+ }
+
+ return ComponentName.unflattenFromString(savedDevicesComponent);
+ }
+
+ @Nullable
+ private Intent getSavedDevicesIntent() {
+ ComponentName componentName = getSavedDevicesComponent();
+ if (componentName == null) {
+ return null;
+ }
+
+ PackageManager pm = getPackageManager();
+ Intent intent = getIntent();
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setComponent(componentName);
+
+ final ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.GET_META_DATA);
+ if (resolveInfo == null || resolveInfo.activityInfo == null) {
+ Log.e(TAG, "Device-specified fast pair component (" + componentName
+ + ") not available");
+ return null;
+ }
+ return intent;
+ }
}
diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
index d9d8737..15f47cf 100644
--- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
+++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
@@ -16,7 +16,7 @@
package com.android.settings.sound;
-import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID;
+import static android.bluetooth.BluetoothHearingAid.HI_SYNC_ID_INVALID;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
diff --git a/src/com/android/settings/users/AddSupervisedUserActivity.java b/src/com/android/settings/users/AddSupervisedUserActivity.java
index f3c5867..8a3221d 100644
--- a/src/com/android/settings/users/AddSupervisedUserActivity.java
+++ b/src/com/android/settings/users/AddSupervisedUserActivity.java
@@ -65,7 +65,9 @@
}
private void createUser() {
- final NewUserRequest request = new NewUserRequest.Builder().build();
+ final NewUserRequest request = new NewUserRequest.Builder()
+ .setName(getString(R.string.user_new_user_name))
+ .build();
final AlertDialog pleaseWaitDialog = new AlertDialog.Builder(this)
.setMessage(getString(R.string.creating_new_user_dialog_message))
diff --git a/src/com/android/settings/users/TimeoutToUserZeroPreferenceController.java b/src/com/android/settings/users/TimeoutToUserZeroPreferenceController.java
new file mode 100644
index 0000000..c332726
--- /dev/null
+++ b/src/com/android/settings/users/TimeoutToUserZeroPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * 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.users;
+
+import static android.provider.Settings.Secure.TIMEOUT_TO_USER_ZERO;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+
+import java.util.Arrays;
+
+/**
+ * Controls the preference which launches a settings screen for user to configure whether to
+ * automatically switch to the admin user when the device is docked.
+ */
+public class TimeoutToUserZeroPreferenceController extends BasePreferenceController {
+ private final String[] mEntries;
+ private final String[] mValues;
+
+ public TimeoutToUserZeroPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+
+ mEntries = mContext.getResources().getStringArray(
+ com.android.settings.R.array.switch_to_user_zero_when_docked_timeout_entries);
+ mValues = mContext.getResources().getStringArray(
+ com.android.settings.R.array.switch_to_user_zero_when_docked_timeout_values);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+
+ updateState(screen.findPreference(getPreferenceKey()));
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ // Feature not available on device.
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableTimeoutToUserZeroWhenDocked)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
+ // Multi-user feature disabled by user.
+ if (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.USER_SWITCHER_ENABLED, 0) != 1) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+
+ // Is currently user zero. Only non user zero can have this setting.
+ if (UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
+ return DISABLED_FOR_USER;
+ }
+
+ return AVAILABLE;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ final String key = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ TIMEOUT_TO_USER_ZERO, UserHandle.myUserId());
+ final int index = Arrays.asList(mValues).indexOf(key != null ? key :
+ mValues[TimeoutToUserZeroSettings.DEFAULT_TIMEOUT_SETTING_VALUE_INDEX]);
+
+ return mEntries[index];
+ }
+}
diff --git a/src/com/android/settings/users/TimeoutToUserZeroSettings.java b/src/com/android/settings/users/TimeoutToUserZeroSettings.java
new file mode 100644
index 0000000..7621ce5
--- /dev/null
+++ b/src/com/android/settings/users/TimeoutToUserZeroSettings.java
@@ -0,0 +1,122 @@
+/*
+ * 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.users;
+
+import static android.provider.Settings.Secure.TIMEOUT_TO_USER_ZERO;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.widget.RadioButtonPickerFragment;
+import com.android.settingslib.widget.CandidateInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Setting screen that lists options for users to configure whether to automatically switch to the
+ * admin user when the device is docked, and if so duration of the timeout.
+ */
+public class TimeoutToUserZeroSettings extends RadioButtonPickerFragment {
+ // Index of the default key of the timeout setting if it hasn't been changed by the user.
+ public static final int DEFAULT_TIMEOUT_SETTING_VALUE_INDEX = 0;
+
+ // Labels of the options, for example, "never", "after 5 minutes".
+ private String[] mEntries;
+
+ // Values and keys of the options.
+ private String[] mValues;
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.TIMEOUT_TO_USER_ZERO;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.user_timeout_to_user_zero_settings;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+
+ mEntries = getContext().getResources().getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_entries);
+ mValues = getContext().getResources().getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_values);
+ }
+
+ @Override
+ protected List<? extends CandidateInfo> getCandidates() {
+ final List<CandidateInfo> candidates = new ArrayList<>();
+
+ if (mEntries == null || mValues == null) {
+ return candidates;
+ }
+
+ for (int i = 0; i < mValues.length; i++) {
+ candidates.add(new TimeoutCandidateInfo(mEntries[i], mValues[i], true));
+ }
+
+ return candidates;
+ }
+
+ @Override
+ protected String getDefaultKey() {
+ final String defaultKey = Settings.Secure.getStringForUser(
+ getContext().getContentResolver(), TIMEOUT_TO_USER_ZERO, UserHandle.myUserId());
+ return defaultKey != null ? defaultKey : mValues[DEFAULT_TIMEOUT_SETTING_VALUE_INDEX];
+ }
+
+ @Override
+ protected boolean setDefaultKey(String key) {
+ Settings.Secure.putStringForUser(getContext().getContentResolver(), TIMEOUT_TO_USER_ZERO,
+ key, UserHandle.myUserId());
+ return true;
+ }
+
+ private static class TimeoutCandidateInfo extends CandidateInfo {
+ private final CharSequence mLabel;
+ private final String mKey;
+
+ TimeoutCandidateInfo(CharSequence label, String key, boolean enabled) {
+ super(enabled);
+ mLabel = label;
+ mKey = key;
+ }
+
+ @Override
+ public CharSequence loadLabel() {
+ return mLabel;
+ }
+
+ @Override
+ public Drawable loadIcon() {
+ return null;
+ }
+
+ @Override
+ public String getKey() {
+ return mKey;
+ }
+ }
+}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 9398d20..3ea1502 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -118,6 +118,7 @@
private static final String KEY_ADD_SUPERVISED_USER = "supervised_user_add";
private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
private static final String KEY_MULTIUSER_TOP_INTRO = "multiuser_top_intro";
+ private static final String KEY_TIMEOUT_TO_USER_ZERO = "timeout_to_user_zero_preference";
private static final int MENU_REMOVE_USER = Menu.FIRST;
@@ -185,6 +186,7 @@
new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY);
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController;
+ private TimeoutToUserZeroPreferenceController mTimeoutToUserZeroPreferenceController;
private UserCreatingDialog mUserCreatingDialog;
private final AtomicBoolean mGuestCreationScheduled = new AtomicBoolean();
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@@ -264,9 +266,13 @@
mMultiUserTopIntroPreferenceController = new MultiUserTopIntroPreferenceController(activity,
KEY_MULTIUSER_TOP_INTRO);
+ mTimeoutToUserZeroPreferenceController = new TimeoutToUserZeroPreferenceController(activity,
+ KEY_TIMEOUT_TO_USER_ZERO);
+
final PreferenceScreen screen = getPreferenceScreen();
mAddUserWhenLockedPreferenceController.displayPreference(screen);
mMultiUserTopIntroPreferenceController.displayPreference(screen);
+ mTimeoutToUserZeroPreferenceController.displayPreference(screen);
screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey())
.setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);
@@ -327,6 +333,8 @@
mAddUserWhenLockedPreferenceController.updateState(screen.findPreference(
mAddUserWhenLockedPreferenceController.getPreferenceKey()));
+ mTimeoutToUserZeroPreferenceController.updateState(screen.findPreference(
+ mTimeoutToUserZeroPreferenceController.getPreferenceKey()));
if (mShouldUpdateUserList) {
updateUI();
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 68a8a86..09c5734 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -439,7 +439,6 @@
assertThat(mFragment.mTemplate.getMatchRule())
.isEqualTo(NetworkTemplate.MATCH_WIFI);
assertTrue(mFragment.mTemplate.getSubscriberIds().isEmpty());
- assertThat(mFragment.mTemplate.getNetworkId())
- .isEqualTo(NetworkTemplate.WIFI_NETWORKID_ALL);
+ assertTrue(mFragment.mTemplate.getWifiNetworkKeys().isEmpty());
}
}
diff --git a/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
index 8d994d0..70a1a38 100644
--- a/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
@@ -81,8 +81,8 @@
when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false);
final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
}
@Test
@@ -94,8 +94,8 @@
.thenReturn(new String[] {SUBSCRIBER_ID});
final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
}
@Test
@@ -107,7 +107,7 @@
.thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+ assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
index 4276407..783c2ed 100644
--- a/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
@@ -73,6 +73,7 @@
mLifecycle = new Lifecycle(mLifecycleOwner);
mController = spy(new AbstractBluetoothA2dpPreferenceControllerImpl(mContext, mLifecycle,
mBluetoothA2dpConfigStore));
+ mController.mBluetoothAdapter = null;
doReturn(mBluetoothCodecConfig).when(mController).getCodecConfig(null);
doNothing().when(mController).setCodecConfigPreference(any(), any());
when(mBluetoothA2dpConfigStore.createCodecConfig()).thenReturn(mBluetoothCodecConfig);
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
index e5fbd65..72477b9 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
@@ -24,9 +24,10 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+
import android.os.SystemProperties;
import androidx.preference.ListPreference;
@@ -46,17 +47,12 @@
@RunWith(RobolectricTestRunner.class)
public class BluetoothMaxConnectedAudioDevicesPreferenceControllerTest {
- private static final int TEST_MAX_CONNECTED_AUDIO_DEVICES = 3;
+ private static int TEST_MAX_CONNECTED_AUDIO_DEVICES = 5;
@Mock
private PreferenceScreen mPreferenceScreen;
@Spy
private Context mSpyContext = RuntimeEnvironment.application;
- @Spy
- private BluetoothManager mBluetoothManager =
- mSpyContext.getSystemService(BluetoothManager.class);
- @Spy
- private BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
private ListPreference mPreference;
private BluetoothMaxConnectedAudioDevicesPreferenceController mController;
@@ -67,16 +63,19 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- doReturn(mBluetoothManager).when(mSpyContext).getSystemService(BluetoothManager.class);
- doReturn(mBluetoothAdapter).when(mBluetoothManager).getAdapter();
// Get XML values without mock
// Setup test list preference using XML values
mPreference = new ListPreference(mSpyContext);
mPreference.setEntries(R.array.bluetooth_max_connected_audio_devices);
mPreference.setEntryValues(R.array.bluetooth_max_connected_audio_devices_values);
- // Stub default max connected audio devices to a test controlled value
- doReturn(TEST_MAX_CONNECTED_AUDIO_DEVICES).when(mBluetoothAdapter)
- .getMaxConnectedAudioDevices();
+ // Retrieve default max connected audio devices to a test controlled value
+ try {
+ Resources res = mSpyContext.getPackageManager().getResourcesForApplication("com.android.bluetooth");
+ TEST_MAX_CONNECTED_AUDIO_DEVICES = res.getInteger(res.getIdentifier("config_bluetooth_max_connected_audio_devices", "integer", "com.android.bluetooth"));
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+
// Init the actual controller
mController = new BluetoothMaxConnectedAudioDevicesPreferenceController(mSpyContext);
// Construct preference in the controller via a mocked preference screen object
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
index c1648bf..d16a507 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -30,6 +31,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -59,6 +61,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
private AbstractBluetoothDialogPreferenceController mController;
@@ -84,6 +88,7 @@
mActiveDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
mController = spy(new AbstractBluetoothDialogPreferenceControllerImpl(mContext, mLifecycle,
mBluetoothA2dpConfigStore));
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = spy(new BaseBluetoothDialogPreferenceImpl(mContext));
mCodecConfigAAC = new BluetoothCodecConfig.Builder()
@@ -99,7 +104,8 @@
mController.displayPreference(mScreen);
mCurrentConfig = mController.getCurrentConfigIndex();
when(mPreference.generateSummary(mCurrentConfig)).thenReturn(SUMMARY);
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
index a042ebe..5a24c8e 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -55,6 +57,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
private BluetoothBitPerSampleDialogPreferenceController mController;
@@ -81,6 +85,7 @@
mPreference = new BluetoothBitPerSampleDialogPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mCodecConfigAAC = new BluetoothCodecConfig.Builder()
.setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC)
.setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_16
@@ -90,7 +95,8 @@
.setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC)
.setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_24)
.build();
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
index 75d8fc4..3d94e2a 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -55,6 +57,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
private BluetoothChannelModeDialogPreferenceController mController;
@@ -78,6 +82,7 @@
mActiveDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
mController = new BluetoothChannelModeDialogPreferenceController(mContext, mLifecycle,
mBluetoothA2dpConfigStore);
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = new BluetoothChannelModeDialogPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -90,7 +95,8 @@
.setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_MONO
| BluetoothCodecConfig.CHANNEL_MODE_STEREO)
.build();
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
index 3a34aa0..21111cd 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
@@ -29,6 +29,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -56,6 +57,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
@Mock
private AbstractBluetoothPreferenceController.Callback mCallback;
@@ -85,6 +88,7 @@
mActiveDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
mController = new BluetoothCodecDialogPreferenceController(mContext, mLifecycle,
mBluetoothA2dpConfigStore, mCallback);
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = new BluetoothCodecDialogPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -115,7 +119,8 @@
mCodecConfigLDAC = new BluetoothCodecConfig.Builder()
.setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC)
.build();
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceControllerTest.java
index 60476de..72ceddf 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothHDAudioPreferenceControllerTest.java
@@ -18,12 +18,15 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -43,6 +46,9 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowBluetoothDevice;
+import java.util.Arrays;
+import java.util.Collections;
+
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothDevice.class})
public class BluetoothHDAudioPreferenceControllerTest {
@@ -52,6 +58,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
@Mock
private AbstractBluetoothPreferenceController.Callback mCallback;
@@ -73,6 +81,7 @@
mBluetoothA2dpConfigStore = spy(new BluetoothA2dpConfigStore());
mController = new BluetoothHDAudioPreferenceController(mContext, mLifecycle,
mBluetoothA2dpConfigStore, mCallback);
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = new SwitchPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -81,7 +90,8 @@
@Test
public void updateState_noActiveDevice_setDisable() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(null);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Collections.emptyList());
mController.onBluetoothServiceConnected(mBluetoothA2dp);
mController.updateState(mPreference);
@@ -90,7 +100,8 @@
@Test
public void updateState_codecSupported_setEnable() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
when(mBluetoothA2dp.isOptionalCodecsSupported(mActiveDevice)).thenReturn(
mBluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -101,7 +112,8 @@
@Test
public void updateState_codecNotSupported_setDisable() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
when(mBluetoothA2dp.isOptionalCodecsSupported(mActiveDevice)).thenReturn(
mBluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -112,7 +124,8 @@
@Test
public void updateState_codecSupportedAndEnabled_checked() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
when(mBluetoothA2dp.isOptionalCodecsSupported(mActiveDevice)).thenReturn(
mBluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn(
@@ -125,7 +138,8 @@
@Test
public void updateState_codecSupportedAndDisabled_notChecked() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
when(mBluetoothA2dp.isOptionalCodecsSupported(mActiveDevice)).thenReturn(
mBluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn(
@@ -138,7 +152,8 @@
@Test
public void onPreferenceChange_disable_verifyFlow() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
mController.onBluetoothServiceConnected(mBluetoothA2dp);
final boolean enabled = false;
mController.onPreferenceChange(mPreference, enabled);
@@ -151,7 +166,8 @@
@Test
public void onPreferenceChange_enable_verifyFlow() {
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
mController.onBluetoothServiceConnected(mBluetoothA2dp);
final boolean enabled = true;
mController.onPreferenceChange(mPreference, enabled);
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
index e50b716..1bd83f7 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -53,6 +55,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
private BluetoothQualityDialogPreferenceController mController;
@@ -76,6 +80,7 @@
mActiveDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
mController = new BluetoothQualityDialogPreferenceController(mContext, mLifecycle,
mBluetoothA2dpConfigStore);
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = new BluetoothQualityDialogPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -89,7 +94,8 @@
.setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_96000)
.setCodecSpecific1(1001)
.build();
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
index fca154d..f7d010c 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
@@ -55,6 +57,8 @@
@Mock
private BluetoothA2dp mBluetoothA2dp;
@Mock
+ private BluetoothAdapter mBluetoothAdapter;
+ @Mock
private PreferenceScreen mScreen;
private BluetoothSampleRateDialogPreferenceController mController;
@@ -79,6 +83,7 @@
mActiveDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
mController = spy(new BluetoothSampleRateDialogPreferenceController(mContext, mLifecycle,
mBluetoothA2dpConfigStore));
+ mController.mBluetoothAdapter = mBluetoothAdapter;
mPreference = new BluetoothSampleRateDialogPreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
@@ -91,7 +96,8 @@
.setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC)
.setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_96000)
.build();
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mActiveDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mActiveDevice));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java b/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
index 6c1d3c2..59c501b 100644
--- a/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
@@ -16,7 +16,7 @@
package com.android.settings.testutils;
-import static com.android.settings.display.darkmode.BedtimeSettings.ACTION_BEDTIME_SETTINGS;
+import static android.provider.Settings.ACTION_BEDTIME_SETTINGS;
import static org.robolectric.Shadows.shadowOf;
diff --git a/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroPreferenceControllerTest.java
new file mode 100644
index 0000000..e284d90
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroPreferenceControllerTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.users;
+
+import static android.provider.Settings.Secure.TIMEOUT_TO_USER_ZERO;
+
+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.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.fuelgauge.BatteryBackupHelperTest.ShadowUserHandle;
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowSecureSettings.class, ShadowUserHandle.class})
+public class TimeoutToUserZeroPreferenceControllerTest {
+ private Context mContext;
+ private Resources mResources;
+ private TimeoutToUserZeroPreferenceController mController;
+
+ private static final String FAKE_PREFERENCE_KEY = "timeout_to_user_zero_preference";
+
+ private String[] mEntries;
+ private String[] mValues;
+
+ @Before
+ public void setUp() {
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mResources = spy(mContext.getResources());
+ doReturn(mResources).when(mContext).getResources();
+
+ mEntries = mResources.getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_entries);
+ mValues = mResources.getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_values);
+
+ mController = new TimeoutToUserZeroPreferenceController(mContext, FAKE_PREFERENCE_KEY);
+
+ // Feature enabled.
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_enableTimeoutToUserZeroWhenDocked)).thenReturn(
+ true);
+
+ // Multi-user feature enabled.
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.USER_SWITCHER_ENABLED,
+ 1);
+
+ // Set to user 1;
+ ShadowUserHandle.setUid(1);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUserHandle.reset();
+ }
+
+ @Test
+ public void getAvailabilityStatus_featureFlagDisabled_returnUnsupportedOnDevice() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_enableTimeoutToUserZeroWhenDocked)).thenReturn(
+ false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_multiUserDisabled_returnConditionallyUnavailable() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.USER_SWITCHER_ENABLED,
+ 0);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isCurrentlyUserZero_returnDisabledForUser() {
+ ShadowUserHandle.setUid(UserHandle.USER_SYSTEM);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_featureAndMultiUserEnabledAndNonUserZero_returnAvailable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getSummary_settingNotSet() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(), TIMEOUT_TO_USER_ZERO,
+ null, UserHandle.myUserId());
+
+ assertThat(mController.getSummary().toString()).isEqualTo(mEntries[0]);
+ }
+
+ @Test
+ public void getSummary_setToNever() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(), TIMEOUT_TO_USER_ZERO,
+ mValues[0], UserHandle.myUserId());
+
+ assertThat(mController.getSummary().toString()).isEqualTo(mEntries[0]);
+ }
+
+ @Test
+ public void getSummary_setToOneMinute() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(), TIMEOUT_TO_USER_ZERO,
+ mValues[1], UserHandle.myUserId());
+
+ assertThat(mController.getSummary().toString()).isEqualTo(mEntries[1]);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroSettingsTest.java b/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroSettingsTest.java
new file mode 100644
index 0000000..0bd5b60
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/users/TimeoutToUserZeroSettingsTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settingslib.widget.CandidateInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowFragment.class})
+public class TimeoutToUserZeroSettingsTest {
+ @Mock
+ private FragmentActivity mActivity;
+
+ private TimeoutToUserZeroSettings mSettings;
+
+ private String[] mEntries;
+ private String[] mValues;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ final Context context = spy(ApplicationProvider.getApplicationContext());
+ mEntries = context.getResources().getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_entries);
+ mValues = context.getResources().getStringArray(
+ R.array.switch_to_user_zero_when_docked_timeout_values);
+ mSettings = spy(new TimeoutToUserZeroSettings());
+
+ doReturn(context).when(mSettings).getContext();
+ doReturn(mActivity).when(mSettings).getActivity();
+
+ mSettings.onAttach(context);
+ }
+
+ @Test
+ public void getCandidates_returnsACandidateForEachEntry() {
+ final List<? extends CandidateInfo> candidates = mSettings.getCandidates();
+
+ for (int i = 0; i < mEntries.length; i++) {
+ assertThat(candidates.get(i).loadLabel().toString()).isEqualTo(mEntries[i]);
+ }
+ }
+
+ @Test
+ public void defaultKey_settingNotSet_shouldReturnFirstValueAsDefault() {
+ assertThat(mSettings.getDefaultKey()).isEqualTo(mValues[0]);
+ }
+
+ @Test
+ public void defaultKey_setToFirstValue_shouldSaveToSettings() {
+ final String expectedKey = mValues[0];
+ mSettings.setDefaultKey(expectedKey);
+ assertThat(mSettings.getDefaultKey()).isEqualTo(expectedKey);
+ }
+
+ @Test
+ public void defaultKey_setToSecondValue_shouldSaveToSettings() {
+ final String expectedKey = mValues[1];
+ mSettings.setDefaultKey(expectedKey);
+ assertThat(mSettings.getDefaultKey()).isEqualTo(expectedKey);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
index 01564fb..6b2c076 100644
--- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
@@ -62,7 +62,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -89,6 +88,7 @@
private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user";
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
+ private static final String KEY_APP_COPYING = "app_copying";
private static final int DIALOG_CONFIRM_REMOVE = 1;
@@ -105,6 +105,8 @@
private Preference mRemoveUserPref;
@Mock
private Preference mAppAndContentAccessPref;
+ @Mock
+ private Preference mAppCopyingPref;
private FragmentActivity mActivity;
private Context mContext;
@@ -145,6 +147,7 @@
doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER);
doReturn(mAppAndContentAccessPref)
.when(mFragment).findPreference(KEY_APP_AND_CONTENT_ACCESS);
+ doReturn(mAppCopyingPref).when(mFragment).findPreference(KEY_APP_COPYING);
}
@After
@@ -163,7 +166,6 @@
}
@Test
- @Ignore
public void initialize_userSelected_shouldSetupSwitchPref() {
setupSelectedUser();
doReturn("Switch to " + mUserInfo.name)
@@ -179,7 +181,6 @@
}
@Test
- @Ignore
public void initialize_guestSelected_shouldSetupSwitchPref() {
setupSelectedGuest();
doReturn("Switch to " + mUserInfo.name)
@@ -195,7 +196,6 @@
}
@Test
- @Ignore
public void initialize_userSelected_shouldNotShowAppAndContentPref() {
setupSelectedUser();
@@ -205,7 +205,6 @@
}
@Test
- @Ignore
public void initialize_guestSelected_shouldNotShowAppAndContentPref() {
setupSelectedGuest();
@@ -259,7 +258,6 @@
}
@Test
- @Ignore
public void initialize_adminWithTelephony_shouldShowPhonePreference() {
setupSelectedUser();
doReturn(true).when(mTelephonyManager).isVoiceCapable();
@@ -272,7 +270,6 @@
}
@Test
- @Ignore
public void initialize_adminNoTelephony_shouldNotShowPhonePreference() {
setupSelectedUser();
doReturn(false).when(mTelephonyManager).isVoiceCapable();
@@ -306,7 +303,6 @@
}
@Test
- @Ignore
public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() {
setupSelectedUser();
mUserManager.setIsAdminUser(true);
@@ -319,7 +315,6 @@
}
@Test
- @Ignore
public void initialize_adminSelectsNewRestrictedUser_shouldOpenAppContentScreen() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
@@ -342,7 +337,6 @@
}
@Test
- @Ignore
public void initialize_adminSelectsRestrictedUser_shouldSetupPreferences() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
@@ -361,7 +355,6 @@
}
@Test
- @Ignore
public void initialize_adminSelectsExistingRestrictedUser_shouldNotStartAppAndContentAccess() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
@@ -373,7 +366,6 @@
}
@Test
- @Ignore
public void initialize_adminSelectsGuest_shouldShowRemovePreference() {
setupSelectedGuest();
mUserManager.setIsAdminUser(true);
@@ -396,7 +388,6 @@
}
@Test
- @Ignore
public void initialize_disallowRemoveUserRestriction_shouldNotShowRemovePreference() {
setupSelectedUser();
mUserManager.setIsAdminUser(true);
@@ -408,7 +399,6 @@
}
@Test
- @Ignore
public void initialize_userHasCallRestriction_shouldSetPhoneSwitchUnChecked() {
setupSelectedUser();
mUserManager.setIsAdminUser(true);
@@ -421,7 +411,6 @@
}
@Test
- @Ignore
public void initialize_noCallRestriction_shouldSetPhoneSwitchChecked() {
setupSelectedUser();
mUserManager.setIsAdminUser(true);
@@ -432,7 +421,6 @@
}
@Test
- @Ignore
public void initialize_guestSelected_noCallRestriction_shouldSetPhonePreference() {
setupSelectedGuest();
mUserManager.setIsAdminUser(true);
@@ -444,7 +432,6 @@
}
@Test
- @Ignore
public void initialize_guestSelected_callRestriction_shouldSetPhonePreference() {
setupSelectedGuest();
mUserManager.setIsAdminUser(true);
@@ -457,7 +444,6 @@
}
@Test
- @Ignore
public void initialize_switchUserDisallowed_shouldSetAdminDisabledOnSwitchPreference() {
setupSelectedUser();
mUserCapabilities.mDisallowSwitchUser = true;
@@ -473,7 +459,6 @@
}
@Test
- @Ignore
public void initialize_switchUserAllowed_shouldSetSwitchPreferenceEnabled() {
setupSelectedUser();
mUserCapabilities.mDisallowSwitchUser = false;
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
index 1042a6a..ed4c127 100644
--- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
+++ b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
@@ -55,6 +55,7 @@
private LocaleList mSystemLocales;
private LocaleList mAppLocale;
private String[] mAssetLocales;
+ private LocaleList mPackageLocales;
@Before
@UiThreadTest
@@ -67,11 +68,13 @@
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(LocaleManager.class)).thenReturn(mLocaleManager);
- setupInitialLocales("en",
- "tw",
- "jp",
- "en, uk, jp, ne",
- new String[]{"en", "ne", "ms", "pa"});
+ setupInitialLocales(
+ /* appLocale= */ "en",
+ /* simCountry= */ "tw",
+ /* networkCountry= */ "jp",
+ /* systemLocales= */ "en, uk, jp, ne",
+ /* packageLocales= */ "pa, cn, tw, en",
+ /* assetLocales= */ new String[]{"en", "ne", "ms", "pa"});
}
@Test
@@ -105,11 +108,13 @@
@UiThreadTest
public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsSimCountryLocale() {
Locale simCountryLocale = new Locale("zh", "TW");
- setupInitialLocales("",
- "tw",
- "",
- "en, uk, jp, ne",
- new String[]{"en", "ne", "ms", "pa"});
+ setupInitialLocales(
+ /* appLocale= */ "",
+ /* simCountry= */ "tw",
+ /* networkCountry= */ "",
+ /* systemLocales= */ "en, uk, jp, ne",
+ /* packageLocales= */ "",
+ /* assetLocales= */ new String[]{});
DummyAppLocaleDetailsHelper helper =
new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
@@ -124,11 +129,13 @@
@UiThreadTest
public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsNetworkCountryLocale() {
Locale networkCountryLocale = new Locale("en", "GB");
- setupInitialLocales("",
- "",
- "gb",
- "en, uk, jp, ne",
- new String[]{"en", "ne", "ms", "pa"});
+ setupInitialLocales(
+ /* appLocale= */ "",
+ /* simCountry= */ "",
+ /* networkCountry= */ "gb",
+ /* systemLocales= */ "en, uk, jp, ne",
+ /* packageLocales= */ "",
+ /* assetLocales= */ new String[]{});
DummyAppLocaleDetailsHelper helper =
new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
@@ -142,11 +149,32 @@
@Test
@UiThreadTest
public void handleAllLocalesData_noAppAndSimNetworkLocale_1stLocaleIsFirstOneInSystemLocales() {
- setupInitialLocales("",
- "",
- "",
- "en, uk, jp, ne",
- new String[]{"en", "ne", "ms", "pa"});
+ setupInitialLocales(
+ /* appLocale= */ "",
+ /* simCountry= */ "",
+ /* networkCountry= */ "",
+ /* systemLocales= */ "en, uk, jp, ne",
+ /* packageLocales= */ "",
+ /* assetLocales= */ new String[]{});
+ DummyAppLocaleDetailsHelper helper =
+ new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
+
+ helper.handleAllLocalesData();
+
+ Locale locale = Iterables.get(helper.getSuggestedLocales(), 0);
+ assertTrue(locale.equals(mSystemLocales.get(0)));
+ }
+
+ @Test
+ @UiThreadTest
+ public void handleAllLocalesData_hasPackageAndSystemLocales_1stLocaleIs1stOneInSystemLocales() {
+ setupInitialLocales(
+ /* appLocale= */ "",
+ /* simCountry= */ "",
+ /* networkCountry= */ "",
+ /* systemLocales= */ "en, uk, jp, ne",
+ /* packageLocales= */ "pa, cn, tw, en",
+ /* assetLocales= */ new String[]{});
DummyAppLocaleDetailsHelper helper =
new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
@@ -204,6 +232,11 @@
*
* @param systemLocales System locales, a locale list by a multiple language tags with comma.
* example: "en, uk, jp"
+ *
+ * @param packageLocales PackageManager locales, a locale list by a multiple language tags with
+ * comma.
+ * example: "en, uk, jp"
+ *
* @param assetLocales Asset locales, a locale list by a multiple language tags with String
* array.
* example: new String[] {"en", "ne", "ms", "pa"}
@@ -212,10 +245,12 @@
String simCountry,
String networkCountry,
String systemLocales,
+ String packageLocales,
String[] assetLocales) {
mAppLocale = LocaleList.forLanguageTags(appLocale);
mSystemLocales = LocaleList.forLanguageTags(systemLocales);
mAssetLocales = assetLocales;
+ mPackageLocales = LocaleList.forLanguageTags(packageLocales);
when(mTelephonyManager.getSimCountryIso()).thenReturn(simCountry);
when(mTelephonyManager.getNetworkCountryIso()).thenReturn(networkCountry);
when(mLocaleManager.getApplicationLocales(anyString())).thenReturn(mAppLocale);
@@ -237,6 +272,10 @@
LocaleList getCurrentSystemLocales() {
return mSystemLocales;
}
- }
+ @Override
+ LocaleList getPackageLocales() {
+ return mPackageLocales;
+ }
+ }
}
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
index 567594c..825a9b6 100644
--- a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
@@ -43,6 +45,7 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -68,6 +71,7 @@
private HibernationSwitchPreferenceController mController;
private Context mContext;
+ private String mOriginalPreSFlagValue;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
@@ -89,6 +93,16 @@
"true", true /* makeDefault */);
mController = new HibernationSwitchPreferenceController(mContext, KEY);
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+
+ mOriginalPreSFlagValue = DeviceConfig.getProperty(NAMESPACE_APP_HIBERNATION,
+ PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS);
+ }
+
+ @After
+ public void cleanUp() {
+ // Restore original device config values.
+ DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS,
+ mOriginalPreSFlagValue, true /* makeDefault */);
}
@Test
@@ -124,43 +138,37 @@
}
@Test
- public void updateState_exemptedByDefaultPackage_shouldNotCheck() {
+ public void isPackageHibernationExemptByUser_preSAppShouldBeExemptByDefault() {
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_DEFAULT);
mController.setPackage(EXEMPTED_PACKAGE_NAME);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(false);
+ assertTrue(mController.isPackageHibernationExemptByUser());
}
@Test
- public void updateState_exemptedPackageOverrideByUser_shouldCheck() {
+ public void isPackageHibernationExemptByUser_preSAppShouldNotBeExemptWithUserSetting() {
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_ALLOWED);
mController.setPackage(EXEMPTED_PACKAGE_NAME);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(true);
+ assertFalse(mController.isPackageHibernationExemptByUser());
}
@Test
- public void updateState_unexemptedPackageOverrideByUser_shouldNotCheck() {
+ public void isPackageHibernationExemptByUser_SAppShouldBeExemptWithUserSetting() {
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(UNEXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_IGNORED);
mController.setPackage(UNEXEMPTED_PACKAGE_NAME);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(false);
+ assertTrue(mController.isPackageHibernationExemptByUser());
}
@Test
- public void updateState_exemptedByDefaultPackageOverriddenByPreSFlag_shouldCheck() {
+ public void isPackageHibernationExemptByUser_preSAppShouldNotBeExemptByDefaultWithPreSFlag() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS,
"true", true /* makeDefault */);
when(mAppOpsManager.unsafeCheckOpNoThrow(
@@ -168,8 +176,6 @@
.thenReturn(MODE_DEFAULT);
mController.setPackage(EXEMPTED_PACKAGE_NAME);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(true);
+ assertFalse(mController.isPackageHibernationExemptByUser());
}
}