Merge "Hide "Long Background Tasks" page from Settings." into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5904282..ff4096f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3717,7 +3717,7 @@
<!-- Show channel-level notification settings (channel passed in as extras) -->
<activity android:name=".notification.app.ChannelPanelActivity"
android:label="@string/notification_channel_title"
- android:theme="@style/Theme.Panel"
+ android:theme="@style/Theme.Panel.Material"
android:excludeFromRecents="true"
android:configChanges="keyboardHidden|screenSize"
android:exported="true">
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 836806c..4e85cb8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,6 +2,20 @@
"presubmit": [
{
"name": "SettingsSpaUnitTests"
+ },
+ {
+ "name": "SettingsUnitTests",
+ "options": [
+ {
+ "include-filter": "com.android.settings.password"
+ },
+ {
+ "include-filter": "com.android.settings.biometrics"
+ },
+ {
+ "include-filter": "com.android.settings.biometrics2"
+ }
+ ]
}
],
"postsubmit": [
diff --git a/res/drawable/button_border_selected.xml b/res/drawable/button_border_selected.xml
index 0cd4aa5..1402380 100644
--- a/res/drawable/button_border_selected.xml
+++ b/res/drawable/button_border_selected.xml
@@ -15,10 +15,7 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
- <solid
- android:color="?androidprv:attr/materialColorSurfaceContainer" />
<stroke
android:width="2dp"
android:color="?android:attr/colorAccent"/>
diff --git a/res/drawable/button_border_unselected.xml b/res/drawable/button_border_unselected.xml
index 2c2ef3d..d0ce75b 100644
--- a/res/drawable/button_border_unselected.xml
+++ b/res/drawable/button_border_unselected.xml
@@ -18,7 +18,7 @@
android:shape="rectangle">
<stroke
android:width="1dp"
- android:color="@color/notification_importance_button_unselected"/>
+ android:color="?android:attr/colorAccent"/>
<corners android:radius="@dimen/rect_button_radius" />
</shape>
diff --git a/res/drawable/checkbox_circle_shape.xml b/res/drawable/checkbox_circle_shape.xml
index 68c5a2e..51a567c 100644
--- a/res/drawable/checkbox_circle_shape.xml
+++ b/res/drawable/checkbox_circle_shape.xml
@@ -1,24 +1,31 @@
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
+ Copyright (C) 2023 The Android Open Source Project
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
- android:state_checked="true"
- android:drawable="@drawable/ic_check_circle_filled_24dp" />
- <item
- android:state_checked="false"
- android:drawable="@drawable/ic_circle_outline_24dp" />
-</selector>
\ No newline at end of file
+ android:bottom="12dp"
+ android:left="12dp"
+ android:right="12dp"
+ android:top="12dp">
+ <selector>
+ <item
+ android:state_checked="true"
+ android:drawable="@drawable/ic_check_circle_filled_24dp" />
+ <item
+ android:state_checked="false"
+ android:drawable="@drawable/ic_circle_outline_24dp" />
+ </selector>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index b748f94..5819774 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -74,7 +74,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
- android:paddingLeft="14dp"
android:text="@string/auto_pin_confirm_user_message"
android:textSize="16sp"
android:button="@drawable/checkbox_circle_shape"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 405960b..bad0dcc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4243,7 +4243,7 @@
<string name="accessibility_screen_magnification_follow_typing_title">Magnify typing</string>
<!-- Summary for accessibility follow typing preference for magnification. [CHAR LIMIT=none] -->
<string name="accessibility_screen_magnification_follow_typing_summary">Magnifier follows text as you type</string>
- <!-- Title for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=35] -->
+ <!-- Title for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=60] -->
<string name="accessibility_screen_magnification_always_on_title">Keep on while switching apps</string>
<!-- Summary for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=none] -->
<string name="accessibility_screen_magnification_always_on_summary">Magnifier stays on and zooms out when you switch apps</string>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index eeba1c7..8f13279 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -227,6 +227,9 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style>
+ <style name="Theme.Panel.Material" parent="Theme.Panel" >
+ <item name="android:switchStyle">@style/Switch.SettingsLib</item>
+ </style>
<!-- Material theme for the pages containing TabLayout and ViewPager -->
<style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/edge_effect_device_default_light</item>
diff --git a/src/com/android/settings/applications/ClonedAppsPreferenceController.java b/src/com/android/settings/applications/ClonedAppsPreferenceController.java
index a8a79f4..332df18 100644
--- a/src/com/android/settings/applications/ClonedAppsPreferenceController.java
+++ b/src/com/android/settings/applications/ClonedAppsPreferenceController.java
@@ -75,6 +75,9 @@
}
private void updatePreferenceSummary() {
+ if (!isAvailable()) {
+ return;
+ }
new AsyncTask<Void, Void, Integer[]>() {
@Override
diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
index 1bb3b4d..66ffc90 100644
--- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
+++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
@@ -25,17 +25,20 @@
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.os.Build;
import android.os.IDeviceIdleController;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import java.io.IOException;
@@ -49,13 +52,22 @@
public final class BatteryBackupHelper implements BackupHelper {
/** An inditifier for {@link BackupHelper}. */
public static final String TAG = "BatteryBackupHelper";
+ // Definition for the device build information.
+ public static final String KEY_BUILD_BRAND = "device_build_brand";
+ public static final String KEY_BUILD_PRODUCT = "device_build_product";
+ public static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture";
+ public static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint";
+ // Customized fields for device extra information.
+ public static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1";
+ public static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2";
+
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME =
"battery_optimize_backup_historical_logs";
+ private static final int DEVICE_BUILD_INFO_SIZE = 6;
static final String DELIMITER = ",";
static final String DELIMITER_MODE = ":";
- static final String KEY_FULL_POWER_LIST = "full_power_list";
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
@VisibleForTesting
@@ -70,7 +82,13 @@
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils;
+ private byte[] mOptimizationModeBytes;
+ private boolean mVerifyMigrateConfiguration = false;
+
private final Context mContext;
+ // Device information map from the restoreEntity() method.
+ private final ArrayMap<String, String> mDeviceBuildInfoMap =
+ new ArrayMap<>(DEVICE_BUILD_INFO_SIZE);
public BatteryBackupHelper(Context context) {
mContext = context.getApplicationContext();
@@ -83,41 +101,58 @@
Log.w(TAG, "ignore performBackup() for non-owner or empty data");
return;
}
- final List<String> allowlistedApps = backupFullPowerList(data);
- if (allowlistedApps != null) {
- backupOptimizationMode(data, allowlistedApps);
+ final List<String> allowlistedApps = getFullPowerList();
+ if (allowlistedApps == null) {
+ return;
}
+
+ writeBackupData(data, KEY_BUILD_BRAND, Build.BRAND);
+ writeBackupData(data, KEY_BUILD_PRODUCT, Build.PRODUCT);
+ writeBackupData(data, KEY_BUILD_MANUFACTURER, Build.MANUFACTURER);
+ writeBackupData(data, KEY_BUILD_FINGERPRINT, Build.FINGERPRINT);
+ // Add customized device build metadata fields.
+ final PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext)
+ .getPowerUsageFeatureProvider(mContext);
+ writeBackupData(data, KEY_BUILD_METADATA_1, provider.getBuildMetadata1(mContext));
+ writeBackupData(data, KEY_BUILD_METADATA_2, provider.getBuildMetadata2(mContext));
+
+ backupOptimizationMode(data, allowlistedApps);
}
@Override
public void restoreEntity(BackupDataInputStream data) {
- BatterySettingsMigrateChecker.verifySaverConfiguration(mContext);
+ // Ensure we only verify the migrate configuration one time.
+ if (!mVerifyMigrateConfiguration) {
+ mVerifyMigrateConfiguration = true;
+ BatterySettingsMigrateChecker.verifySaverConfiguration(mContext);
+ }
if (!isOwner() || data == null || data.size() == 0) {
Log.w(TAG, "ignore restoreEntity() for non-owner or empty data");
return;
}
-
- if (KEY_OPTIMIZATION_LIST.equals(data.getKey())) {
- final int dataSize = data.size();
- final byte[] dataBytes = new byte[dataSize];
- try {
- data.read(dataBytes, 0 /*offset*/, dataSize);
- } catch (IOException e) {
- Log.e(TAG, "failed to load BackupDataInputStream", e);
- return;
- }
- final int restoreCount = restoreOptimizationMode(dataBytes);
- if (restoreCount > 0) {
- BatterySettingsMigrateChecker.verifyOptimizationModes(mContext);
- }
+ final String dataKey = data.getKey();
+ switch (dataKey) {
+ case KEY_BUILD_BRAND:
+ case KEY_BUILD_PRODUCT:
+ case KEY_BUILD_MANUFACTURER:
+ case KEY_BUILD_FINGERPRINT:
+ case KEY_BUILD_METADATA_1:
+ case KEY_BUILD_METADATA_2:
+ restoreBackupData(dataKey, data);
+ break;
+ case KEY_OPTIMIZATION_LIST:
+ // Hold the optimization mode data until all conditions are matched.
+ mOptimizationModeBytes = getBackupData(dataKey, data);
+ break;
}
+ performRestoreIfNeeded();
}
@Override
public void writeNewStateDescription(ParcelFileDescriptor newState) {
}
- private List<String> backupFullPowerList(BackupDataOutput data) {
+ private List<String> getFullPowerList() {
final long timestamp = System.currentTimeMillis();
String[] allowlistedApps;
try {
@@ -131,10 +166,7 @@
Log.w(TAG, "no data found in the getFullPowerList()");
return new ArrayList<>();
}
-
- final String allowedApps = String.join(DELIMITER, allowlistedApps);
- writeBackupData(data, KEY_FULL_POWER_LIST, allowedApps);
- Log.d(TAG, String.format("backup getFullPowerList() size=%d in %d/ms",
+ Log.d(TAG, String.format("getFullPowerList() size=%d in %d/ms",
allowlistedApps.length, (System.currentTimeMillis() - timestamp)));
return Arrays.asList(allowlistedApps);
}
@@ -224,6 +256,23 @@
return restoreCount;
}
+ private void performRestoreIfNeeded() {
+ if (mOptimizationModeBytes == null || mOptimizationModeBytes.length == 0) {
+ return;
+ }
+ final PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext)
+ .getPowerUsageFeatureProvider(mContext);
+ if (!provider.isValidToRestoreOptimizationMode(mDeviceBuildInfoMap)) {
+ return;
+ }
+ // Start to restore the app optimization mode data.
+ final int restoreCount = restoreOptimizationMode(mOptimizationModeBytes);
+ if (restoreCount > 0) {
+ BatterySettingsMigrateChecker.verifyOptimizationModes(mContext);
+ }
+ mOptimizationModeBytes = null; // clear data
+ }
+
/** Dump the app optimization mode backup history data. */
public static void dumpHistoricalData(Context context, PrintWriter writer) {
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(
@@ -303,8 +352,33 @@
return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager());
}
+ private void restoreBackupData(String dataKey, BackupDataInputStream data) {
+ final byte[] dataBytes = getBackupData(dataKey, data);
+ if (dataBytes == null || dataBytes.length == 0) {
+ return;
+ }
+ final String dataContent = new String(dataBytes, StandardCharsets.UTF_8);
+ mDeviceBuildInfoMap.put(dataKey, dataContent);
+ Log.d(TAG, String.format("restore:%s:%s", dataKey, dataContent));
+ }
+
+ private static byte[] getBackupData(String dataKey, BackupDataInputStream data) {
+ final int dataSize = data.size();
+ final byte[] dataBytes = new byte[dataSize];
+ try {
+ data.read(dataBytes, 0 /*offset*/, dataSize);
+ } catch (IOException e) {
+ Log.e(TAG, "failed to getBackupData() " + dataKey, e);
+ return null;
+ }
+ return dataBytes;
+ }
+
private static void writeBackupData(
BackupDataOutput data, String dataKey, String dataContent) {
+ if (dataContent == null || dataContent.isEmpty()) {
+ return;
+ }
final byte[] dataContentBytes = dataContent.getBytes();
try {
data.writeEntityHeader(dataKey, dataContentBytes.length);
@@ -312,5 +386,6 @@
} catch (IOException e) {
Log.e(TAG, "writeBackupData() is failed for " + dataKey, e);
}
+ Log.d(TAG, String.format("backup:%s:%s", dataKey, dataContent));
}
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 9f30473..0b0e243 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
+import android.util.ArrayMap;
import android.util.SparseIntArray;
import com.android.settingslib.fuelgauge.Estimate;
@@ -166,4 +167,19 @@
* Returns {@link Set} for ignoring task root class names for screen on time
*/
Set<String> getIgnoreScreenOnTimeTaskRootSet();
+
+ /**
+ * Returns the customized device build information for data backup
+ */
+ String getBuildMetadata1(Context context);
+
+ /**
+ * Returns the customized device build information for data backup
+ */
+ String getBuildMetadata2(Context context);
+
+ /**
+ * Whether the app optimization mode is valid to restore
+ */
+ boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap);
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index d65c212..1d0ba18 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Process;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseIntArray;
@@ -188,4 +189,19 @@
public Set<String> getIgnoreScreenOnTimeTaskRootSet() {
return new ArraySet<>();
}
+
+ @Override
+ public String getBuildMetadata1(Context context) {
+ return null;
+ }
+
+ @Override
+ public String getBuildMetadata2(Context context) {
+ return null;
+ }
+
+ @Override
+ public boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap) {
+ return false;
+ }
}
diff --git a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
index 1ebd166..574e62f 100644
--- a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
+++ b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.provider.Settings;
+import androidx.core.text.util.LocalePreferences;
+
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
diff --git a/src/com/android/settings/regionalpreferences/LocalePreferences.java b/src/com/android/settings/regionalpreferences/LocalePreferences.java
deleted file mode 100644
index 2006221..0000000
--- a/src/com/android/settings/regionalpreferences/LocalePreferences.java
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.regionalpreferences;
-import android.icu.number.LocalizedNumberFormatter;
-import android.icu.number.NumberFormatter;
-import android.icu.text.DateFormat;
-import android.icu.text.DateTimePatternGenerator;
-import android.icu.util.MeasureUnit;
-import android.os.Build.VERSION;
-
-import androidx.annotation.DoNotInline;
-import androidx.annotation.NonNull;
-import androidx.annotation.OptIn;
-import androidx.annotation.RestrictTo;
-import androidx.annotation.StringDef;
-import androidx.core.os.BuildCompat;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Locale;
-import java.util.Locale.Category;
-
-/**
- * TODO(b/263861083) This is a temp file and will replace it to Androidx version.
- * Provides friendly APIs to get the user's locale preferences. The data can refer to
- * external/cldr/common/main/en.xml.
- */
-public final class LocalePreferences {
- private static final String TAG = LocalePreferences.class.getSimpleName();
-
- /** APIs to get the user's preference of the hour cycle. */
- public static class HourCycle {
- private static final String U_EXTENSION_OF_HOUR_CYCLE = "hc";
-
- /** 12 Hour System (0-11) */
- public static final String H11 = "h11";
- /** 12 Hour System (1-12) */
- public static final String H12 = "h12";
- /** 24 Hour System (0-23) */
- public static final String H23 = "h23";
- /** 24 Hour System (1-24) */
- public static final String H24 = "h24";
- /** Default hour cycle for the locale */
- public static final String DEFAULT = "";
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @StringDef({
- H11,
- H12,
- H23,
- H24,
- DEFAULT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface HourCycleTypes {
- }
-
- private HourCycle() {
- }
- }
-
- /**
- * Return the user's preference of the hour cycle which is from
- * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and
- * bases on the {@code Locale#getDefault(Locale.Category)}. E.g. "h23"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @HourCycle.HourCycleTypes
- public static String getHourCycle() {
- return getHourCycle(true);
- }
-
- /**
- * Return the hour cycle setting of the inputted {@link Locale}. The returned result is resolved
- * and bases on the inputted {@code Locale}.
- * E.g. "h23"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @HourCycle.HourCycleTypes
- public static String getHourCycle(@NonNull Locale locale) {
- return getHourCycle(locale, true);
- }
-
- /**
- * Return the user's preference of the hour cycle which is from
- * {@link Locale#getDefault(Locale.Category)}. E.g. "h23"
- *
- * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains hour cycle subtag,
- * this argument is ignored. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
- * and the resolved argument is true, this function tries to find the default
- * hour cycle for the {@code Locale#getDefault(Locale.Category)}. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
- * and the resolved argument is false, this function returns empty string
- * i.e. HourCycle.Default.
- * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
- * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
- * i.e. HourCycle.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @HourCycle.HourCycleTypes
- public static String getHourCycle(
- boolean resolved) {
- return getHourCycle(Api33Impl.getDefaultLocale(), resolved);
- }
-
- /**
- * Return the hour cycle setting of the inputted {@link Locale}. E.g. "en-US-u-hc-h23".
- *
- * @param locale The {@code Locale} to get the hour cycle.
- * @param resolved If the given {@code Locale} contains hour cycle subtag, this argument is
- * ignored. If the given {@code Locale} doesn't contain hour cycle subtag and
- * the resolved argument is true, this function tries to find the default
- * hour cycle for the given {@code Locale}. If the given {@code Locale} doesn't
- * contain hour cycle subtag and the resolved argument is false, this function
- * return empty string i.e. HourCycle.Default.
- * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
- * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
- * i.e. HourCycle.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @HourCycle.HourCycleTypes
- public static String getHourCycle(@NonNull Locale locale, boolean resolved) {
- if (!BuildCompat.isAtLeastT()) {
- throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
- }
- return Api33Impl.getHourCycle(locale, resolved);
- }
-
- /** APIs to get the user's preference of Calendar. */
- public static class CalendarType {
- private static final String U_EXTENSION_OF_CALENDAR = "ca";
- /** Chinese Calendar */
- public static final String CHINESE = "chinese";
- /** Dangi Calendar (Korea Calendar) */
- public static final String DANGI = "dangi";
- /** Gregorian Calendar */
- public static final String GREGORIAN = "gregorian";
- /** Hebrew Calendar */
- public static final String HEBREW = "hebrew";
- /** Indian National Calendar */
- public static final String INDIAN = "indian";
- /** Islamic Calendar */
- public static final String ISLAMIC = "islamic";
- /** Islamic Calendar (tabular, civil epoch) */
- public static final String ISLAMIC_CIVIL = "islamic-civil";
- /** Islamic Calendar (Saudi Arabia, sighting) */
- public static final String ISLAMIC_RGSA = "islamic-rgsa";
- /** Islamic Calendar (tabular, astronomical epoch) */
- public static final String ISLAMIC_TBLA = "islamic-tbla";
- /** Islamic Calendar (Umm al-Qura) */
- public static final String ISLAMIC_UMALQURA = "islamic-umalqura";
- /** Persian Calendar */
- public static final String PERSIAN = "persian";
- /** Default calendar for the locale */
- public static final String DEFAULT = "";
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @StringDef({
- CHINESE,
- DANGI,
- GREGORIAN,
- HEBREW,
- INDIAN,
- ISLAMIC,
- ISLAMIC_CIVIL,
- ISLAMIC_RGSA,
- ISLAMIC_TBLA,
- ISLAMIC_UMALQURA,
- PERSIAN,
- DEFAULT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CalendarTypes {
- }
-
- private CalendarType() {
- }
- }
-
- /**
- * Return the user's preference of the calendar type which is from {@link
- * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on
- * the {@code Locale#getDefault(Locale.Category)} settings. E.g. "chinese"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @CalendarType.CalendarTypes
- public static String getCalendarType() {
- return getCalendarType(true);
- }
-
- /**
- * Return the calendar type of the inputted {@link Locale}. The returned result is resolved and
- * bases on the inputted {@link Locale} settings.
- * E.g. "chinese"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @CalendarType.CalendarTypes
- public static String getCalendarType(@NonNull Locale locale) {
- return getCalendarType(locale, true);
- }
-
- /**
- * Return the user's preference of the calendar type which is from {@link
- * Locale#getDefault(Locale.Category)}. E.g. "chinese"
- *
- * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains calendar type
- * subtag, this argument is ignored. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
- * subtag and the resolved argument is true, this function tries to find
- * the default calendar type for the
- * {@code Locale#getDefault(Locale.Category)}. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
- * subtag and the resolved argument is false, this function returns empty string
- * i.e. CalendarTypes.Default.
- * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
- * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
- * empty string i.e. CalendarTypes.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @CalendarType.CalendarTypes
- public static String getCalendarType(boolean resolved) {
- return getCalendarType(Api33Impl.getDefaultLocale(), resolved);
- }
-
- /**
- * Return the calendar type of the inputted {@link Locale}. E.g. "chinese"
- *
- * @param locale The {@link Locale} to get the calendar type.
- * @param resolved If the given {@code Locale} contains calendar type subtag, this argument is
- * ignored. If the given {@code Locale} doesn't contain calendar type subtag and
- * the resolved argument is true, this function tries to find the default
- * calendar type for the given {@code Locale}. If the given {@code Locale}
- * doesn't contain calendar type subtag and the resolved argument is false, this
- * function return empty string i.e. CalendarTypes.Default.
- * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
- * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
- * empty string i.e. CalendarTypes.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @CalendarType.CalendarTypes
- public static String getCalendarType(@NonNull Locale locale, boolean resolved) {
- if (!BuildCompat.isAtLeastT()) {
- throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
- }
- return Api33Impl.getCalendarType(locale, resolved);
- }
-
- /** APIs to get the user's preference of temperature unit. */
- public static class TemperatureUnit {
- private static final String U_EXTENSION_OF_TEMPERATURE_UNIT = "mu";
- /** Celsius */
- public static final String CELSIUS = "celsius";
- /** Fahrenheit */
- public static final String FAHRENHEIT = "fahrenhe";
- /** Kelvin */
- public static final String KELVIN = "kelvin";
- /** Default Temperature for the locale */
- public static final String DEFAULT = "";
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @StringDef({
- CELSIUS,
- FAHRENHEIT,
- KELVIN,
- DEFAULT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TemperatureUnits {
- }
-
- private TemperatureUnit() {
- }
- }
-
- /**
- * Return the user's preference of the temperature unit which is from {@link
- * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
- * {@code Locale#getDefault(Locale.Category)} settings. E.g. "fahrenhe"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @TemperatureUnit.TemperatureUnits
- public static String getTemperatureUnit() {
- return getTemperatureUnit(true);
- }
-
- /**
- * Return the temperature unit of the inputted {@link Locale}. The returned result is resolved
- * and bases on the inputted {@code Locale} settings. E.g. "fahrenhe"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @TemperatureUnit.TemperatureUnits
- public static String getTemperatureUnit(
- @NonNull Locale locale) {
- return getTemperatureUnit(locale, true);
- }
-
- /**
- * Return the user's preference of the temperature unit which is from {@link
- * Locale#getDefault(Locale.Category)}. E.g. "fahrenhe"
- *
- * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains temperature unit
- * subtag, this argument is ignored. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
- * subtag and the resolved argument is true, this function tries to find
- * the default temperature unit for the
- * {@code Locale#getDefault(Locale.Category)}. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
- * subtag and the resolved argument is false, this function returns empty string
- * i.e. TemperatureUnits.Default.
- * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
- * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
- * empty string i.e. TemperatureUnits.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @TemperatureUnit.TemperatureUnits
- public static String getTemperatureUnit(boolean resolved) {
- return getTemperatureUnit(Api33Impl.getDefaultLocale(), resolved);
- }
-
- /**
- * Return the temperature unit of the inputted {@link Locale}. E.g. "fahrenheit"
- *
- * @param locale The {@link Locale} to get the temperature unit.
- * @param resolved If the given {@code Locale} contains temperature unit subtag, this argument
- * is ignored. If the given {@code Locale} doesn't contain temperature unit
- * subtag and the resolved argument is true, this function tries to find
- * the default temperature unit for the given {@code Locale}. If the given
- * {@code Locale} doesn't contain temperature unit subtag and the resolved
- * argument is false, this function return empty string
- * i.e. TemperatureUnits.Default.
- * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
- * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
- * empty string i.e. TemperatureUnits.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @TemperatureUnit.TemperatureUnits
- public static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
- if (!BuildCompat.isAtLeastT()) {
- throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
- }
- return Api33Impl.getTemperatureUnit(locale, resolved);
- }
-
- /** APIs to get the user's preference of the first day of week. */
- public static class FirstDayOfWeek {
- private static final String U_EXTENSION_OF_FIRST_DAY_OF_WEEK = "fw";
- /** Sunday */
- public static final String SUNDAY = "sun";
- /** Monday */
- public static final String MONDAY = "mon";
- /** Tuesday */
- public static final String TUESDAY = "tue";
- /** Wednesday */
- public static final String WEDNESDAY = "wed";
- /** Thursday */
- public static final String THURSDAY = "thu";
- /** Friday */
- public static final String FRIDAY = "fri";
- /** Saturday */
- public static final String SATURDAY = "sat";
- /** Default first day of week for the locale */
- public static final String DEFAULT = "";
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @StringDef({
- SUNDAY,
- MONDAY,
- TUESDAY,
- WEDNESDAY,
- THURSDAY,
- FRIDAY,
- SATURDAY,
- DEFAULT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Days {
- }
-
- private FirstDayOfWeek() {
- }
- }
-
- /**
- * Return the user's preference of the first day of week which is from
- * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
- * {@code Locale#getDefault(Locale.Category)} settings. E.g. "sun"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @FirstDayOfWeek.Days
- public static String getFirstDayOfWeek() {
- return getFirstDayOfWeek(true);
- }
-
- /**
- * Return the first day of week of the inputted {@link Locale}. The returned result is resolved
- * and bases on the inputted {@code Locale} settings.
- * E.g. "sun"
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- public static @FirstDayOfWeek.Days String getFirstDayOfWeek(@NonNull Locale locale) {
- return getFirstDayOfWeek(locale, true);
- }
-
- /**
- * Return the user's preference of the first day of week which is from {@link
- * Locale#getDefault(Locale.Category)}. E.g. "sun"
- *
- * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains first day of week
- * subtag, this argument is ignored. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
- * subtag and the resolved argument is true, this function tries to find
- * the default first day of week for the
- * {@code Locale#getDefault(Locale.Category)}. If the
- * {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
- * subtag and the resolved argument is false, this function returns empty string
- * i.e. Days.Default.
- * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was specified
- * in the first day of week subtag, e.g. en-US-u-fw-days, this function returns empty string
- * i.e. Days.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @FirstDayOfWeek.Days
- public static String getFirstDayOfWeek(boolean resolved) {
- return getFirstDayOfWeek(Api33Impl.getDefaultLocale(), resolved);
- }
-
- /**
- * Return the first day of week of the inputted {@link Locale}. E.g. "sun"
- *
- * @param locale The {@link Locale} to get the first day of week.
- * @param resolved If the given {@code Locale} contains first day of week subtag, this argument
- * is ignored. If the given {@code Locale} doesn't contain first day of week
- * subtag and the resolved argument is true, this function tries to find
- * the default first day of week for the given {@code Locale}. If the given
- * {@code Locale} doesn't contain first day of week subtag and the resolved
- * argument is false, this function return empty string i.e. Days.Default.
- * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was
- * specified in the first day of week subtag, e.g. en-US-u-fw-days, this function returns
- * empty string i.e. Days.Default.
- */
- @NonNull
- @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
- @FirstDayOfWeek.Days
- public static String getFirstDayOfWeek(
- @NonNull Locale locale, boolean resolved) {
- if (!BuildCompat.isAtLeastT()) {
- throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
- }
-
- return Api33Impl.getFirstDayOfWeek(locale, resolved);
- }
-
- private static class Api33Impl {
- @DoNotInline
- @HourCycle.HourCycleTypes
- static String getHourCycle(@NonNull Locale locale,
- boolean resolved) {
- String hc = locale.getUnicodeLocaleType(HourCycle.U_EXTENSION_OF_HOUR_CYCLE);
- if (hc != null) {
- return hc;
- }
- if (!resolved) {
- return HourCycle.DEFAULT;
- }
-
- return getHourCycleType(
- DateTimePatternGenerator.getInstance(locale).getDefaultHourCycle());
-
- }
-
- @DoNotInline
- @CalendarType.CalendarTypes
- static String getCalendarType(@NonNull Locale locale, boolean resolved) {
- String ca = locale.getUnicodeLocaleType(CalendarType.U_EXTENSION_OF_CALENDAR);
- if (ca != null) {
- return ca;
- }
- if (!resolved) {
- return CalendarType.DEFAULT;
- }
-
- return android.icu.util.Calendar.getInstance(locale).getType();
- }
-
- @DoNotInline
- @TemperatureUnit.TemperatureUnits
- static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
- String mu =
- locale.getUnicodeLocaleType(TemperatureUnit.U_EXTENSION_OF_TEMPERATURE_UNIT);
- if (mu != null) {
- return mu;
- }
- if (!resolved) {
- return TemperatureUnit.DEFAULT;
- }
-
- return getResolvedTemperatureUnit(locale);
- }
-
- @DoNotInline
- @FirstDayOfWeek.Days
- static String getFirstDayOfWeek(@NonNull Locale locale, boolean resolved) {
- String mu =
- locale.getUnicodeLocaleType(FirstDayOfWeek.U_EXTENSION_OF_FIRST_DAY_OF_WEEK);
- if (mu != null) {
- return mu;
- }
- if (!resolved) {
- return FirstDayOfWeek.DEFAULT;
- }
- // TODO(b/262294472) Use {@code android.icu.util.Calendar} instead of
- // {@code java.util.Calendar}.
- return getStringOfFirstDayOfWeek(
- java.util.Calendar.getInstance(locale).getFirstDayOfWeek());
- }
-
- @DoNotInline
- static Locale getDefaultLocale() {
- return Locale.getDefault(Category.FORMAT);
- }
-
- private static String getStringOfFirstDayOfWeek(int fw) {
- String[] arrDays = {
- FirstDayOfWeek.SUNDAY,
- FirstDayOfWeek.MONDAY,
- FirstDayOfWeek.TUESDAY,
- FirstDayOfWeek.WEDNESDAY,
- FirstDayOfWeek.THURSDAY,
- FirstDayOfWeek.FRIDAY,
- FirstDayOfWeek.SATURDAY};
-
- return fw >= 1 && fw <= 7 ? arrDays[fw - 1] : FirstDayOfWeek.DEFAULT;
- }
-
- @HourCycle.HourCycleTypes
- private static String getHourCycleType(
- DateFormat.HourCycle hourCycle) {
- switch (hourCycle) {
- case HOUR_CYCLE_11:
- return HourCycle.H11;
- case HOUR_CYCLE_12:
- return HourCycle.H12;
- case HOUR_CYCLE_23:
- return HourCycle.H23;
- case HOUR_CYCLE_24:
- return HourCycle.H24;
- default:
- return HourCycle.DEFAULT;
- }
- }
-
- @TemperatureUnit.TemperatureUnits
- private static String getResolvedTemperatureUnit(@NonNull Locale locale) {
- LocalizedNumberFormatter nf = NumberFormatter.with()
- .usage("temperature")
- .unit(MeasureUnit.CELSIUS)
- .locale(locale);
- String unit = nf.format(1).getOutputUnit().getIdentifier();
- if (unit.contains(TemperatureUnit.FAHRENHEIT)) {
- return TemperatureUnit.FAHRENHEIT;
- }
- return unit;
- }
-
- private Api33Impl() {
- }
- }
-
- private LocalePreferences() {
- }
-}
diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
index 823f5bb..1e39fff 100644
--- a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
+++ b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
@@ -63,7 +63,9 @@
pref.setKey(item);
pref.setOnPreferenceClickListener(clickedPref -> {
setSelected(pref);
- RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(), item);
+ RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(),
+ item.equals(RegionalPreferencesDataUtils.DEFAULT_VALUE)
+ ? null : item);
mMetricsFeatureProvider.action(mContext, getMetricsActionKey());
return true;
});
diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
index 32e00b4..d1ae40b 100644
--- a/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
+++ b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
@@ -22,6 +22,8 @@
import android.provider.Settings;
import android.text.TextUtils;
+import androidx.core.text.util.LocalePreferences;
+
import com.android.internal.app.LocalePicker;
import com.android.settings.R;
diff --git a/src/com/android/settings/regionalpreferences/TemperatureUnitController.java b/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
index 9fbf69b..4b0f22c 100644
--- a/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
+++ b/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.provider.Settings;
+import androidx.core.text.util.LocalePreferences;
+
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index 8970730..b8c72ee 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -28,6 +28,7 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
@@ -45,6 +46,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
+import android.os.Build;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -53,6 +55,7 @@
import com.android.settings.TestUtils;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import org.junit.After;
@@ -89,6 +92,7 @@
private PrintWriter mPrintWriter;
private StringWriter mStringWriter;
private BatteryBackupHelper mBatteryBackupHelper;
+ private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
@Mock
private PackageManager mPackageManager;
@@ -112,6 +116,8 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mPowerUsageFeatureProvider =
+ FakeFeatureFactory.setupForTest().powerUsageFeatureProvider;
mContext = spy(RuntimeEnvironment.application);
mStringWriter = new StringWriter();
mPrintWriter = new PrintWriter(mStringWriter);
@@ -136,19 +142,11 @@
}
@Test
- public void performBackup_nullPowerList_notBackupPowerList() throws Exception {
- doReturn(null).when(mDeviceController).getFullPowerWhitelist();
- mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
- verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
- }
-
- @Test
- public void performBackup_emptyPowerList_notBackupPowerList() throws Exception {
+ public void performBackup_emptyPowerList_backupPowerList() throws Exception {
doReturn(new String[0]).when(mDeviceController).getFullPowerWhitelist();
mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
- verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
+ verify(mBackupDataOutput, atLeastOnce()).writeEntityHeader(anyString(), anyInt());
}
@Test
@@ -160,34 +158,6 @@
}
@Test
- public void performBackup_oneFullPowerListElement_backupFullPowerListData()
- throws Exception {
- final String[] fullPowerList = {"com.android.package"};
- doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
-
- mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
- final byte[] expectedBytes = fullPowerList[0].getBytes();
- verify(mBackupDataOutput).writeEntityHeader(
- BatteryBackupHelper.KEY_FULL_POWER_LIST, expectedBytes.length);
- verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
- }
-
- @Test
- public void performBackup_backupFullPowerListData() throws Exception {
- final String[] fullPowerList = {"com.android.package1", "com.android.package2"};
- doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
-
- mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
- final String expectedResult = fullPowerList[0] + DELIMITER + fullPowerList[1];
- final byte[] expectedBytes = expectedResult.getBytes();
- verify(mBackupDataOutput).writeEntityHeader(
- BatteryBackupHelper.KEY_FULL_POWER_LIST, expectedBytes.length);
- verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
- }
-
- @Test
public void performBackup_nonOwner_ignoreAllBackupAction() throws Exception {
ShadowUserHandle.setUid(1);
final String[] fullPowerList = {"com.android.package"};
@@ -283,7 +253,7 @@
@Test
public void restoreEntity_incorrectDataKey_notReadBackupData() throws Exception {
- final String incorrectDataKey = BatteryBackupHelper.KEY_FULL_POWER_LIST;
+ final String incorrectDataKey = "incorrect_data_key";
mockBackupData(30 /*dataSize*/, incorrectDataKey);
mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
@@ -314,6 +284,20 @@
}
@Test
+ public void restoreEntity_verifyConfigurationOneTimeOnly() {
+ final int invalidScheduledLevel = 5;
+ TestUtils.setScheduledLevel(mContext, invalidScheduledLevel);
+ mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
+ TestUtils.setScheduledLevel(mContext, invalidScheduledLevel);
+
+ // Invoke the restoreEntity() method 2nd time.
+ mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
+
+ assertThat(TestUtils.getScheduledLevel(mContext))
+ .isEqualTo(invalidScheduledLevel);
+ }
+
+ @Test
public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception {
mBatteryBackupHelper.restoreOptimizationMode(new byte[0]);
verifyNoInteractions(mBatteryOptimizeUtils);
@@ -358,6 +342,26 @@
.setAppUsageState(MODE_RESTRICTED, Action.RESTORE);
}
+ @Test
+ public void performBackup_backupDeviceBuildInformation() throws Exception {
+ final String[] fullPowerList = {"com.android.package"};
+ doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
+ doReturn(null).when(mPowerUsageFeatureProvider).getBuildMetadata1(mContext);
+ final String deviceMetadata = "device.metadata.test_device";
+ doReturn(deviceMetadata).when(mPowerUsageFeatureProvider).getBuildMetadata2(mContext);
+
+ mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
+
+ final InOrder inOrder = inOrder(mBackupDataOutput);
+ verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_BRAND, Build.BRAND);
+ verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_PRODUCT, Build.PRODUCT);
+ verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_MANUFACTURER, Build.MANUFACTURER);
+ verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_FINGERPRINT, Build.FINGERPRINT);
+ inOrder.verify(mBackupDataOutput, never()).writeEntityHeader(
+ eq(BatteryBackupHelper.KEY_BUILD_METADATA_1), anyInt());
+ verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_METADATA_2, deviceMetadata);
+ }
+
private void mockUid(int uid, String packageName) throws Exception {
doReturn(uid).when(mPackageManager)
.getPackageUid(packageName, PackageManager.GET_META_DATA);
@@ -429,6 +433,13 @@
new ArraySet<>(Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3));
}
+ private void verifyBackupData(
+ InOrder inOrder, String dataKey, String dataContent) throws Exception {
+ final byte[] expectedBytes = dataContent.getBytes();
+ inOrder.verify(mBackupDataOutput).writeEntityHeader(dataKey, expectedBytes.length);
+ inOrder.verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
+ }
+
@Implements(UserHandle.class)
public static class ShadowUserHandle {
// Sets the default as thte OWNER role.
diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
index a49b4a6..66514ac 100644
--- a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
@@ -39,6 +39,7 @@
import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -152,6 +153,7 @@
verify(mSafetyCenterManagerWrapper, never()).isEnabled(any());
}
+ @Ignore("b/282413778")
@Test
public void enroll_secondVersion_onEnrollmentCallbacks_triggerGivenCallback() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -180,6 +182,7 @@
.onEnrollmentFrame(HELP_CODE, HELP_MESSAGE, CELL, STAGE, PAN, TILT, DISTANCE);
}
+ @Ignore("b/282413778")
@Test
public void enroll_secondVersion_onEnrollmentSuccess_invokedInteractionWithSafetyCenter() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -201,6 +204,7 @@
verify(mSafetyCenterManagerWrapper).isEnabled(mContext);
}
+ @Ignore("b/282413778")
@Test
public void enroll_secondVersion_onEnrollmentNotYetFinished_didntInvokeInteractionWithSafetyCenter() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
diff --git a/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java b/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
index 85272e4..c9571be 100644
--- a/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
+++ b/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
@@ -22,6 +22,7 @@
import android.os.LocaleList;
import android.provider.Settings;
+import androidx.core.text.util.LocalePreferences;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.app.LocalePicker;