From d126303343e1b57be73844fd4c273d54a5a6f7ca Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Tue, 9 May 2023 15:17:38 +0800 Subject: [PATCH 01/13] Enable presubmit biometrics unit tests Enable biometrics/biometrics2/password unit tests Bug: 281627891 Test: atest :presubmit in Settings folder Change-Id: I2587b50b75a161c7b19f1e3430e41b98cfe6cf63 Merged-In: I2587b50b75a161c7b19f1e3430e41b98cfe6cf63 (cherry picked from commit a90536b632aa1be9e050fd2f73c36d949c70cec4) --- TEST_MAPPING | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/TEST_MAPPING b/TEST_MAPPING index 836806cea11..4e85cb8f5b0 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": [ From abfb8a5e9da28932be4847727941b81e16983181 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Thu, 11 May 2023 13:41:12 +0800 Subject: [PATCH 02/13] Fix FaceUpdater.enroll unit test fail in aosp Ignore related tests Bug: 281627891 Test: atest FaceUpdaterTest Change-Id: I028a7dd7fd2e56889ac27051678ca954c896da20 --- .../com/android/settings/biometrics/face/FaceUpdaterTest.java | 4 ++++ 1 file changed, 4 insertions(+) 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 a49b4a6c170..66514ac5068 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 @@ public class FaceUpdaterTest { verify(mSafetyCenterManagerWrapper, never()).isEnabled(any()); } + @Ignore("b/282413778") @Test public void enroll_secondVersion_onEnrollmentCallbacks_triggerGivenCallback() { ArgumentCaptor callbackCaptor = @@ -180,6 +182,7 @@ public class FaceUpdaterTest { .onEnrollmentFrame(HELP_CODE, HELP_MESSAGE, CELL, STAGE, PAN, TILT, DISTANCE); } + @Ignore("b/282413778") @Test public void enroll_secondVersion_onEnrollmentSuccess_invokedInteractionWithSafetyCenter() { ArgumentCaptor callbackCaptor = @@ -201,6 +204,7 @@ public class FaceUpdaterTest { verify(mSafetyCenterManagerWrapper).isEnabled(mContext); } + @Ignore("b/282413778") @Test public void enroll_secondVersion_onEnrollmentNotYetFinished_didntInvokeInteractionWithSafetyCenter() { ArgumentCaptor callbackCaptor = From 0d1638c3d32439740b90900f5bbc31821357a72a Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 15 May 2023 07:23:32 +0000 Subject: [PATCH 03/13] [Use] Replace settings LocalePreference with androidx LocalePreference Bug: 263861083 Test: atest and manual test Change-Id: I7af48074278df0b12c83500f0d2b61eb279e70be --- .../FirstDayOfWeekController.java | 2 + .../LocalePreferences.java | 605 ------------------ .../RegionalPreferencesDataUtils.java | 2 + .../TemperatureUnitController.java | 2 + .../RegionalPreferencesDataUtilsTest.java | 1 + 5 files changed, 7 insertions(+), 605 deletions(-) delete mode 100644 src/com/android/settings/regionalpreferences/LocalePreferences.java diff --git a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java index 1ebd1665aea..574e62f9aa9 100644 --- a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java +++ b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java @@ -19,6 +19,8 @@ package com.android.settings.regionalpreferences; 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 20062218334..00000000000 --- 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/RegionalPreferencesDataUtils.java b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java index 32e00b4a29f..d1ae40b2761 100644 --- a/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java +++ b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java @@ -22,6 +22,8 @@ import android.os.LocaleList; 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 9fbf69b3c44..4b0f22c8a65 100644 --- a/src/com/android/settings/regionalpreferences/TemperatureUnitController.java +++ b/src/com/android/settings/regionalpreferences/TemperatureUnitController.java @@ -19,6 +19,8 @@ package com.android.settings.regionalpreferences; 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/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java b/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java index 85272e426c0..c9571be099b 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.content.Context; 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; From 98e4d7bf1672e456a4736f0514dcfd341df1fa88 Mon Sep 17 00:00:00 2001 From: Ankita Vyas Date: Mon, 15 May 2023 13:11:14 +0000 Subject: [PATCH 04/13] Fetch summary only if feature is available onResume(loads summary) of controller seems to be invoked even when availabilty status is unspported. Bug: 278294334 Test: manual Change-Id: I2486a7d61bea1b981ae56f0ff32b9d411be2ad14 --- .../settings/applications/ClonedAppsPreferenceController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/settings/applications/ClonedAppsPreferenceController.java b/src/com/android/settings/applications/ClonedAppsPreferenceController.java index a8a79f487e7..332df1837b5 100644 --- a/src/com/android/settings/applications/ClonedAppsPreferenceController.java +++ b/src/com/android/settings/applications/ClonedAppsPreferenceController.java @@ -75,6 +75,9 @@ public class ClonedAppsPreferenceController extends BasePreferenceController } private void updatePreferenceSummary() { + if (!isAvailable()) { + return; + } new AsyncTask() { @Override From 2c125d29a3c449567c492a5b6690ac0ea6258e56 Mon Sep 17 00:00:00 2001 From: ykhung Date: Mon, 15 May 2023 23:33:30 +0800 Subject: [PATCH 05/13] Remove useless optimization mode backup for FULL_POWER_LIST Remove the useless backup for the FULL_POWER_LIST, since we will not use it to restore data, only backup the optimization_mode_list is enough Test: presubmit Bug: 192523697 Change-Id: I95f1f41732b8aff090e8b722896d153f6181a6ac --- .../fuelgauge/BatteryBackupHelper.java | 10 ++----- .../fuelgauge/BatteryBackupHelperTest.java | 30 +------------------ 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java index 1bb3b4de001..eb4bbf687d7 100644 --- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java +++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java @@ -55,7 +55,6 @@ public final class BatteryBackupHelper implements BackupHelper { 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 @@ -83,7 +82,7 @@ public final class BatteryBackupHelper implements BackupHelper { Log.w(TAG, "ignore performBackup() for non-owner or empty data"); return; } - final List allowlistedApps = backupFullPowerList(data); + final List allowlistedApps = getFullPowerList(); if (allowlistedApps != null) { backupOptimizationMode(data, allowlistedApps); } @@ -117,7 +116,7 @@ public final class BatteryBackupHelper implements BackupHelper { public void writeNewStateDescription(ParcelFileDescriptor newState) { } - private List backupFullPowerList(BackupDataOutput data) { + private List getFullPowerList() { final long timestamp = System.currentTimeMillis(); String[] allowlistedApps; try { @@ -131,10 +130,7 @@ public final class BatteryBackupHelper implements BackupHelper { 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); } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java index 89707305add..a800fdbd2cc 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java @@ -159,34 +159,6 @@ public final class BatteryBackupHelperTest { verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt()); } - @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); @@ -283,7 +255,7 @@ public final class BatteryBackupHelperTest { @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); From 82dc52376a4e40f265e3be2ed9320eb55bc43192 Mon Sep 17 00:00:00 2001 From: Varun Shah Date: Tue, 16 May 2023 01:51:17 +0000 Subject: [PATCH 06/13] Hide "Long Background Tasks" page from Settings. Since the RUN_USER_INITIATED_JOBS permission is no longer a special permission, the related page in Settings should be hidden. Bug: 282824927 Test: page hidden from Special App Access screen. Change-Id: I51d681f97247be45654dd2eb12df08f429a43938 --- res/xml/app_info_settings.xml | 2 ++ res/xml/special_access.xml | 2 ++ .../applications/ApplicationFeatureProviderImpl.java | 10 ++++------ .../applications/LongBackgroundTaskController.java | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index d8af0092819..73241b705f4 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -193,6 +193,8 @@ android:key="long_background_tasks" android:title="@string/long_background_tasks_title" android:summary="@string/summary_placeholder" + settings:isPreferenceVisible="false" + settings:searchable="false" settings:controller="com.android.settings.applications.appinfo.LongBackgroundTasksDetailsPreferenceController" /> diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml index 2fb4af46825..b3f3f7dd5da 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -128,6 +128,8 @@ android:title="@string/long_background_tasks_title" android:order="-800" android:fragment="com.android.settings.applications.manageapplications.ManageApplications" + settings:isPreferenceVisible="false" + settings:searchable="false" settings:keywords="@string/keywords_long_background_tasks" settings:controller="com.android.settings.applications.specialaccess.applications.LongBackgroundTaskController"> Date: Sat, 13 May 2023 01:04:16 +0000 Subject: [PATCH 07/13] Toggle switch back when user dismisses dialog by tapping screen The reboot dialog can be dismissed when user: 1) Clicks any button on the reboot dialog 2) Taps any screen area outside of reboot dialog We want to toggle back the "Enable ANGLE" switch whenever the user chooses to not reboot the device immetiately. This change adds the function to toggle the "Enable ANGLE" switch back when: 1) User clicks "Cancel" on reboot dialog. 2) User taps screen area outside of reboot dialog to dismiss the reboot dialog. Bug: b/270994705 Test: m; flash and device can boot. atest -c GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest Change-Id: I84fde5ea5bae9d8793bcef30f4c37d832152ae43 --- .../RebootConfirmationDialogFragment.java | 31 +- .../RebootConfirmationDialogHost.java | 16 +- ...erEnableAngleAsSystemDriverController.java | 71 +++- ...ngleAsSystemDriverControllerJUnitTest.java | 360 +++++++++++++----- 4 files changed, 338 insertions(+), 140 deletions(-) diff --git a/src/com/android/settings/development/RebootConfirmationDialogFragment.java b/src/com/android/settings/development/RebootConfirmationDialogFragment.java index 2fa07476878..45c36976343 100644 --- a/src/com/android/settings/development/RebootConfirmationDialogFragment.java +++ b/src/com/android/settings/development/RebootConfirmationDialogFragment.java @@ -28,11 +28,9 @@ import androidx.fragment.app.FragmentManager; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; -/** - * Dialog fragment for reboot confirmation when enabling certain features. - */ +/** Dialog fragment for reboot confirmation when enabling certain features. */ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment - implements DialogInterface.OnClickListener { + implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener { private static final String TAG = "FreeformPrefRebootDlg"; @@ -40,18 +38,17 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment private final int mCancelButtonId; private final RebootConfirmationDialogHost mHost; - /** - * Show an instance of this dialog. - */ + /** Show an instance of this dialog. */ public static void show(Fragment fragment, int messageId, RebootConfirmationDialogHost host) { show(fragment, messageId, R.string.reboot_dialog_reboot_later, host); } - /** - * Show an instance of this dialog with cancel button string set as cancelButtonId - */ - public static void show(Fragment fragment, int messageId, - int cancelButtonId, RebootConfirmationDialogHost host) { + /** Show an instance of this dialog with cancel button string set as cancelButtonId */ + public static void show( + Fragment fragment, + int messageId, + int cancelButtonId, + RebootConfirmationDialogHost host) { final FragmentManager manager = fragment.getActivity().getSupportFragmentManager(); if (manager.findFragmentByTag(TAG) == null) { final RebootConfirmationDialogFragment dialog = @@ -60,8 +57,8 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment } } - private RebootConfirmationDialogFragment(int messageId, - int cancelButtonId, RebootConfirmationDialogHost host) { + private RebootConfirmationDialogFragment( + int messageId, int cancelButtonId, RebootConfirmationDialogHost host) { mMessageId = messageId; mCancelButtonId = cancelButtonId; mHost = host; @@ -89,4 +86,10 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment mHost.onRebootCancelled(); } } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + mHost.onRebootDialogDismissed(); + } } diff --git a/src/com/android/settings/development/RebootConfirmationDialogHost.java b/src/com/android/settings/development/RebootConfirmationDialogHost.java index 65ffbed0aa3..1be25a71bd4 100644 --- a/src/com/android/settings/development/RebootConfirmationDialogHost.java +++ b/src/com/android/settings/development/RebootConfirmationDialogHost.java @@ -20,22 +20,20 @@ import android.content.Context; import android.content.Intent; /** - * Host of {@link RebootConfirmationDialogFragment} that provides callback when user - * interacts with the UI. + * Host of {@link RebootConfirmationDialogFragment} that provides callback when user interacts with + * the UI. */ public interface RebootConfirmationDialogHost { - /** - * Called when user made a decision to reboot the device. - */ + /** Called when user made a decision to reboot the device. */ default void onRebootConfirmed(Context context) { // user presses button "Reboot now", reboot the device final Intent intent = new Intent(Intent.ACTION_REBOOT); context.startActivity(intent); } - /** - * Called when user made a decision to cancel the reboot - * Default to do nothing - */ + /** Called when user made a decision to cancel the reboot Default to do nothing */ default void onRebootCancelled() {} + + /** Called when reboot dialog is dismissed Default to do nothing */ + default void onRebootDialogDismissed() {} } diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java index 04252fa0d56..1a065a96aaa 100644 --- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java +++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java @@ -17,6 +17,7 @@ package com.android.settings.development.graphicsdriver; import android.content.Context; +import android.content.Intent; import android.os.GraphicsEnvironment; import android.os.SystemProperties; import android.text.TextUtils; @@ -33,9 +34,7 @@ import com.android.settings.development.RebootConfirmationDialogFragment; import com.android.settings.development.RebootConfirmationDialogHost; import com.android.settingslib.development.DeveloperOptionsPreferenceController; -/** - * Controller to handle the events when user toggles this developer option switch: Enable ANGLE - */ +/** Controller to handle the events when user toggles this developer option switch: Enable ANGLE */ public class GraphicsDriverEnableAngleAsSystemDriverController extends DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, @@ -50,14 +49,15 @@ public class GraphicsDriverEnableAngleAsSystemDriverController private final GraphicsDriverSystemPropertiesWrapper mSystemProperties; + private boolean mShouldToggleSwitchBackOnRebootDialogDismiss; + @VisibleForTesting static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported"; @VisibleForTesting static final String PROPERTY_PERSISTENT_GRAPHICS_EGL = "persist.graphics.egl"; - @VisibleForTesting - static final String ANGLE_DRIVER_SUFFIX = "angle"; + @VisibleForTesting static final String ANGLE_DRIVER_SUFFIX = "angle"; @VisibleForTesting static class Injector { @@ -87,6 +87,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverController super(context); mFragment = fragment; mSystemProperties = injector.createSystemPropertiesWrapper(); + // By default, when the reboot dialog is dismissed we want to toggle the switch back. + // Exception is when user chooses to reboot now, the switch should keep its current value + // and persist its' state over reboot. + mShouldToggleSwitchBackOnRebootDialogDismiss = true; } @Override @@ -108,11 +112,12 @@ public class GraphicsDriverEnableAngleAsSystemDriverController @VisibleForTesting void showRebootDialog() { RebootConfirmationDialogFragment.show( - mFragment, R.string.reboot_dialog_enable_angle_as_system_driver, - R.string.cancel, this); + mFragment, + R.string.reboot_dialog_enable_angle_as_system_driver, + R.string.cancel, + this); } - @Override public void updateState(Preference preference) { // set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor @@ -120,8 +125,9 @@ public class GraphicsDriverEnableAngleAsSystemDriverController final String currentGlesDriver = mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, ""); final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver); - final boolean isAngleSupported = TextUtils - .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true"); + final boolean isAngleSupported = + TextUtils.equals( + mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true"); ((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported); ((SwitchPreference) mPreference).setEnabled(isAngleSupported); } @@ -130,8 +136,9 @@ public class GraphicsDriverEnableAngleAsSystemDriverController protected void onDeveloperOptionsSwitchEnabled() { // only enable the switch if ro.gfx.angle.supported is true // we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor - final boolean isAngleSupported = TextUtils - .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true"); + final boolean isAngleSupported = + TextUtils.equals( + mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true"); ((SwitchPreference) mPreference).setEnabled(isAngleSupported); } @@ -145,9 +152,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverController ((SwitchPreference) mPreference).setEnabled(false); } - @Override - public void onRebootCancelled() { - // if user presses button "Cancel", do not reboot the device, and toggles switch back + void toggleSwitchBack() { final String currentGlesDriver = mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, ""); if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) { @@ -169,4 +174,40 @@ public class GraphicsDriverEnableAngleAsSystemDriverController // if persist.graphics.egl holds values other than the above two, log error message Log.e(TAG, "Invalid persist.graphics.egl property value"); } + + @VisibleForTesting + void rebootDevice(Context context) { + final Intent intent = new Intent(Intent.ACTION_REBOOT); + context.startActivity(intent); + } + + @Override + public void onRebootConfirmed(Context context) { + // User chooses to reboot now, do not toggle switch back + mShouldToggleSwitchBackOnRebootDialogDismiss = false; + + // Reboot the device + rebootDevice(context); + } + + @Override + public void onRebootCancelled() { + // User chooses to cancel reboot, toggle switch back + mShouldToggleSwitchBackOnRebootDialogDismiss = true; + } + + @Override + public void onRebootDialogDismissed() { + // If reboot dialog is dismissed either from + // 1) User clicks cancel + // 2) User taps phone screen area outside of reboot dialog + // do not reboot the device, and toggles switch back. + if (mShouldToggleSwitchBackOnRebootDialogDismiss) { + toggleSwitchBack(); + } + + // Reset the flag so that the default option is to toggle switch back + // on reboot dialog dismissed. + mShouldToggleSwitchBackOnRebootDialogDismiss = true; + } } diff --git a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java index 3f85535df53..c23292ac54a 100644 --- a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java +++ b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java @@ -56,11 +56,39 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { private GraphicsDriverEnableAngleAsSystemDriverController mController; - @Mock - private DevelopmentSettingsDashboardFragment mFragment; + // Signal to wait for SystemProperty values changed + private class PropertyChangeSignal { + private CountDownLatch mCountDownLatch; - @Mock - private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock; + private Runnable mCountDownJob; + + PropertyChangeSignal() { + mCountDownLatch = new CountDownLatch(1); + mCountDownJob = + new Runnable() { + @Override + public void run() { + mCountDownLatch.countDown(); + } + }; + } + + public Runnable getCountDownJob() { + return mCountDownJob; + } + + public void wait(int timeoutInMilliSeconds) { + try { + mCountDownLatch.await(timeoutInMilliSeconds, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Assert.fail(e.getMessage()); + } + } + } + + @Mock private DevelopmentSettingsDashboardFragment mFragment; + + @Mock private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock; @Before public void setUp() { @@ -76,18 +104,27 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { // so we can force the SystemProperties with values we need to run tests. // 2) Override the showRebootDialog() to do nothing. // We do not need to pop up the reboot dialog in the test. + // 3) Override the rebootDevice() to do nothing. mController = new GraphicsDriverEnableAngleAsSystemDriverController( - mContext, mFragment, new Injector(){ - @Override - public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() { - return mSystemPropertiesMock; - } - }) { - @Override - void showRebootDialog() { - // do nothing - } - }; + mContext, + mFragment, + new Injector() { + @Override + public GraphicsDriverSystemPropertiesWrapper + createSystemPropertiesWrapper() { + return mSystemPropertiesMock; + } + }) { + @Override + void showRebootDialog() { + // do nothing + } + + @Override + void rebootDevice(Context context) { + // do nothing + } + }; final PreferenceManager preferenceManager = new PreferenceManager(mContext); final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); @@ -99,58 +136,42 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { @Test public void onPreferenceChange_switchOn_shouldEnableAngleAsSystemDriver() { + // Step 1: toggle the switch "Enable ANGLE" on // Add a callback when SystemProperty changes. // This allows the thread to wait until // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. - final CountDownLatch countDownLatch = new CountDownLatch(1); - Runnable countDown = new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }; - SystemProperties.addChangeCallback(countDown); - - // Test onPreferenceChange(true) updates the persist.graphics.egl to "angle" + PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob()); mController.onPreferenceChange(mPreference, true); - try { - countDownLatch.await(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } + propertyChangeSignal.wait(100); + + // Step 2: verify results final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX); + // Step 3: clean up // Done with the test, remove the callback - SystemProperties.removeChangeCallback(countDown); + SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob()); } @Test public void onPreferenceChange_switchOff_shouldDisableAngleAsSystemDriver() { + // Step 1: toggle the switch "Enable ANGLE" off // Add a callback when SystemProperty changes. // This allows the thread to wait until // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. - final CountDownLatch countDownLatch = new CountDownLatch(1); - Runnable countDown = new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }; - SystemProperties.addChangeCallback(countDown); - - // Test onPreferenceChange(false) updates the persist.graphics.egl to "" + PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob()); mController.onPreferenceChange(mPreference, false); - try { - countDownLatch.await(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } + propertyChangeSignal.wait(100); + + // Step 2: verify results final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); assertThat(systemEGLDriver).isEqualTo(""); + // Step 3: clean up // Done with the test, remove the callback - SystemProperties.removeChangeCallback(countDown); + SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob()); } @Test @@ -162,8 +183,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { @Test public void updateState_angleNotSupported_PreferenceShouldNotBeChecked() { - when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())) - .thenReturn(""); + when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())).thenReturn(""); mController.updateState(mPreference); assertThat(mPreference.isChecked()).isFalse(); } @@ -191,8 +211,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { updateState_angleSupported_angleIsNotSystemGLESDriver_PreferenceShouldNotBeChecked() { when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())) .thenReturn("true"); - when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) - .thenReturn(""); + when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())).thenReturn(""); mController.updateState(mPreference); assertThat(mPreference.isChecked()).isFalse(); } @@ -218,28 +237,18 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { // Add a callback when SystemProperty changes. // This allows the thread to wait until // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. - final CountDownLatch countDownLatch = new CountDownLatch(1); - Runnable countDown = new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }; - SystemProperties.addChangeCallback(countDown); + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); // Test that onDeveloperOptionSwitchDisabled, // persist.graphics.egl updates to "" mController.onDeveloperOptionsSwitchDisabled(); - try { - countDownLatch.await(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } + propertyChangeSignal1.wait(100); final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); assertThat(systemEGLDriver).isEqualTo(""); // Done with the test, remove the callback - SystemProperties.removeChangeCallback(countDown); + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); } @Test @@ -256,70 +265,217 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest { @Test public void onRebootCancelled_ToggleSwitchFromOnToOff() { + // Step 1: Toggle the "Enable ANGLE" switch on // Add a callback when SystemProperty changes. // This allows the thread to wait until // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. - final CountDownLatch countDownLatch = new CountDownLatch(1); - Runnable countDown = new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }; - SystemProperties.addChangeCallback(countDown); + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, true); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); - // Test that if the current persist.graphics.egl is "angle", - // when reboot is cancelled, persist.graphics.egl is changed back to "", - // and switch is set to unchecked. + // Step 2: Cancel reboot + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) - .thenReturn(ANGLE_DRIVER_SUFFIX); + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); mController.onRebootCancelled(); - try { - countDownLatch.await(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + // Step 3: Verify results + // 1) Test that persist.graphics.egl is changed back to "". final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); assertThat(systemEGLDriver).isEqualTo(""); + // 2) Test that the switch is set to unchecked. assertThat(mPreference.isChecked()).isFalse(); - // Done with the test, remove the callback. - SystemProperties.removeChangeCallback(countDown); + // Step 4: Clean up + // Done with the test, remove the callback + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); } @Test public void onRebootCancelled_ToggleSwitchFromOffToOn() { + // Step 1: Toggle off the switch "Enable ANGLE" // Add a callback when SystemProperty changes. // This allows the thread to wait until // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. - final CountDownLatch countDownLatch = new CountDownLatch(1); - Runnable countDown = new Runnable() { - @Override - public void run() { - countDownLatch.countDown(); - } - }; - SystemProperties.addChangeCallback(countDown); + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, false); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); - // Test that if the current persist.graphics.egl is "", - // when reboot is cancelled, persist.graphics.egl is changed back to "angle", - // and switch is set to checked. + // Step 2: Cancel reboot + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) - .thenReturn(""); + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); mController.onRebootCancelled(); - try { - countDownLatch.await(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + // Step 3: Verify results + // 1) Test that persist.graphics.egl is changed back to "ANGLE" final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX); + // 2) Test that the switch is set to checked assertThat(mPreference.isChecked()).isTrue(); + // Step 4: Clean up // Done with the test, remove the callback. - SystemProperties.removeChangeCallback(countDown); + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); } + @Test + public void onRebootDialogDismissed_ToggleSwitchFromOnToOff() { + // Step 1: Toggle on the switch "Enable ANGLE" + // Add a callback when SystemProperty changes. + // This allows the thread to wait until + // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, true); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); + + // Step 2: Dismiss the reboot dialog + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); + when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + + // Step 3: Verify results + // 1) Test that persist.graphics.egl is changed back to "". + final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); + assertThat(systemEGLDriver).isEqualTo(""); + // 2) Test that the switch is set to unchecked. + assertThat(mPreference.isChecked()).isFalse(); + + // Step 4: Clean up + // Done with the test, remove the callback + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); + } + + @Test + public void onRebootDialogDismissed_ToggleSwitchFromOffToOn() { + // Step 1: Toggle on the switch "Enable ANGLE" + // Add a callback when SystemProperty changes. + // This allows the thread to wait until + // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, false); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); + + // Step 2: Dismiss the reboot dialog + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); + when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + + // Step 3: Verify results + // 1) Test that persist.graphics.egl is changed back to "ANGLE" + final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); + assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX); + // 2) Test that the switch is set to checked + assertThat(mPreference.isChecked()).isTrue(); + + // Step 4: Clean up + // Done with the test, remove the callback + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); + } + + @Test + public void onRebootDialogConfirmed_ToggleSwitchOnRemainsOn() { + // Step 1: Toggle on the switch "Enable ANGLE" + // Add a callback when SystemProperty changes. + // This allows the thread to wait until + // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, true); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); + + // Step 2: Confirm reboot + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); + when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); + mController.onRebootConfirmed(mContext); + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + + // Step 3: Verify Results + // Test that persist.graphics.egl remains to be "ANGLE" + final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); + assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX); + + // Step 4: Clean up + // Done with the test, remove the callback + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); + } + + @Test + public void onRebootDialogConfirmed_ToggleSwitchOffRemainsOff() { + // Step 1: Toggle off the switch "Enable ANGLE" + // Add a callback when SystemProperty changes. + // This allows the thread to wait until + // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl. + PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob()); + mController.onPreferenceChange(mPreference, false); + // Block the following code execution until the "persist.graphics.egl" property value is + // changed. + propertyChangeSignal1.wait(100); + + // Step 2: Confirm reboot + PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal(); + SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob()); + when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())) + .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL)); + mController.onRebootConfirmed(mContext); + mController.onRebootDialogDismissed(); + // Block the following code execution until the "persist.graphics.egl" property valye is + // changed. + propertyChangeSignal2.wait(100); + + // Step 3: Verify Results + // Test that persist.graphics.egl remains to be "" + final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL); + assertThat(systemEGLDriver).isEqualTo(""); + + // Step 4: Clean up + // Done with the test, remove the callback + SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob()); + SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob()); + } } From cad41681d60fe239abb6de33e4037d2afb6933f4 Mon Sep 17 00:00:00 2001 From: ykhung Date: Tue, 16 May 2023 08:36:00 +0800 Subject: [PATCH 08/13] Add device build information in the backup stage Insert the device build information in the battery optimization mode backup stage, such that we can use it to decide whether we should restore the data in the targeted device or not Bug: 192523697 Test: make test RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.* Change-Id: I3ab76e013ea9aca4d336a62e0c7cb6882c5b5085 --- .../fuelgauge/BatteryBackupHelper.java | 29 +++++++++++- .../fuelgauge/PowerUsageFeatureProvider.java | 10 +++++ .../PowerUsageFeatureProviderImpl.java | 10 +++++ .../fuelgauge/BatteryBackupHelperTest.java | 45 ++++++++++++++----- 4 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java index eb4bbf687d7..5d4f2664050 100644 --- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java +++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java @@ -25,6 +25,7 @@ import android.content.Context; 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; @@ -36,6 +37,7 @@ 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; @@ -56,6 +58,13 @@ public final class BatteryBackupHelper implements BackupHelper { static final String DELIMITER = ","; static final String DELIMITER_MODE = ":"; static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list"; + static final String KEY_BUILD_BRAND = "device_build_brand"; + static final String KEY_BUILD_PRODUCT = "device_build_product"; + static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture"; + static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint"; + // Customized fields for device extra information. + static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1"; + static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2"; @VisibleForTesting ArraySet mTestApplicationInfoList = null; @@ -83,9 +92,21 @@ public final class BatteryBackupHelper implements BackupHelper { return; } final List allowlistedApps = getFullPowerList(); - if (allowlistedApps != null) { - backupOptimizationMode(data, allowlistedApps); + 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. + 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 @@ -301,6 +322,9 @@ public final class BatteryBackupHelper implements BackupHelper { 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); @@ -308,5 +332,6 @@ public final class BatteryBackupHelper implements BackupHelper { } catch (IOException e) { Log.e(TAG, "writeBackupData() is failed for " + dataKey, e); } + Log.d(TAG, String.format("%s:%s", dataKey, dataContent)); } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 9f30473e209..724ca04d7ae 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -166,4 +166,14 @@ public interface PowerUsageFeatureProvider { * Returns {@link Set} for ignoring task root class names for screen on time */ Set 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); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index d65c2126658..f73a4d5a256 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -188,4 +188,14 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider public Set getIgnoreScreenOnTimeTaskRootSet() { return new ArraySet<>(); } + + @Override + public String getBuildMetadata1(Context context) { + return null; + } + + @Override + public String getBuildMetadata2(Context context) { + return null; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java index a800fdbd2cc..49354c1c5b5 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.anyInt; 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.IPackageManager; 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 android.util.ArraySet; 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 @@ public final class BatteryBackupHelperTest { private PrintWriter mPrintWriter; private StringWriter mStringWriter; private BatteryBackupHelper mBatteryBackupHelper; + private PowerUsageFeatureProvider mPowerUsageFeatureProvider; @Mock private PackageManager mPackageManager; @@ -112,6 +116,8 @@ public final class BatteryBackupHelperTest { @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 @@ public final class BatteryBackupHelperTest { } @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 @@ -330,6 +328,26 @@ public final class BatteryBackupHelperTest { .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); @@ -401,6 +419,13 @@ public final class BatteryBackupHelperTest { 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. From ceebc93e895f4b6f8459d574f277d31549ef7835 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 15 May 2023 12:00:57 +0000 Subject: [PATCH 09/13] [Regional Preference] Should not save "default" into Locale. Set wrong value in the previous refactory changes, should set valus as null when the default is selected Bug: 281993323 Test: manual test and QA test Change-Id: I897791a38a50588d7d721bf57c0d7bdc1734e189 --- .../RegionalPreferenceListBasePreferenceController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java index 823f5bbc5c3..1e39ffff5e7 100644 --- a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java +++ b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java @@ -63,7 +63,9 @@ public abstract class RegionalPreferenceListBasePreferenceController extends 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; }); From cc1b643a79266fa59dcf17916ce808358f3cccc9 Mon Sep 17 00:00:00 2001 From: Avinash Vadlamudi Date: Mon, 15 May 2023 13:58:23 +0000 Subject: [PATCH 10/13] [Auto Pin Confirmation]: Increase the touch target of checkbox to 48dp for accessibility Bug: 281945287 Test: Manual test by flashing on device and verifying using layout bounds Change-Id: Ibfbb3f3e7e8307c9ec5c01226c24da10fb5e080a --- res/drawable/checkbox_circle_shape.xml | 49 +++++++++++++++----------- res/layout/choose_lock_password.xml | 1 - 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/res/drawable/checkbox_circle_shape.xml b/res/drawable/checkbox_circle_shape.xml index 68c5a2ed359..51a567c220f 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. +--> + - - \ No newline at end of file + android:bottom="12dp" + android:left="12dp" + android:right="12dp" + android:top="12dp"> + + + + + + \ No newline at end of file diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml index b748f94e80a..5819774a75e 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" From 41eeb31b200fa6764432378d974c01c3a17d843a Mon Sep 17 00:00:00 2001 From: Edgar Wang Date: Tue, 16 May 2023 18:02:17 +0800 Subject: [PATCH 11/13] Update theme for ChannelPanelActivity - set correct switch style - update background color Fixes: 238845212 Test: visual Change-Id: Iaf54fa5d98f7527543fc02d1108cbafe851bd574 --- AndroidManifest.xml | 2 +- res/drawable/button_border_selected.xml | 3 --- res/drawable/button_border_unselected.xml | 2 +- res/values/themes.xml | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6fe6832b76a..08fbf04441d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3717,7 +3717,7 @@ diff --git a/res/drawable/button_border_selected.xml b/res/drawable/button_border_selected.xml index 0cd4aa54b5a..1402380d0ed 100644 --- a/res/drawable/button_border_selected.xml +++ b/res/drawable/button_border_selected.xml @@ -15,10 +15,7 @@ limitations under the License. --> - diff --git a/res/drawable/button_border_unselected.xml b/res/drawable/button_border_unselected.xml index 2c2ef3d8d83..d0ce75b8c86 100644 --- a/res/drawable/button_border_unselected.xml +++ b/res/drawable/button_border_unselected.xml @@ -18,7 +18,7 @@ android:shape="rectangle"> + android:color="?android:attr/colorAccent"/> diff --git a/res/values/themes.xml b/res/values/themes.xml index eeba1c77aca..8f132799b79 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -227,6 +227,9 @@ @*android:string/config_headlineFontFamilyMedium +