Snap for 10146593 from 384337cf12 to udc-qpr1-release

Change-Id: I0d6d773825b633e40581e5e6e6c76f9c1eba9e7c
This commit is contained in:
Android Build Coastguard Worker
2023-05-17 01:32:00 +00:00
48 changed files with 566 additions and 812 deletions

View File

@@ -3717,7 +3717,7 @@
<!-- Show channel-level notification settings (channel passed in as extras) --> <!-- Show channel-level notification settings (channel passed in as extras) -->
<activity android:name=".notification.app.ChannelPanelActivity" <activity android:name=".notification.app.ChannelPanelActivity"
android:label="@string/notification_channel_title" android:label="@string/notification_channel_title"
android:theme="@style/Theme.Panel" android:theme="@style/Theme.Panel.Material"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:configChanges="keyboardHidden|screenSize" android:configChanges="keyboardHidden|screenSize"
android:exported="true"> android:exported="true">

View File

@@ -2,6 +2,20 @@
"presubmit": [ "presubmit": [
{ {
"name": "SettingsSpaUnitTests" "name": "SettingsSpaUnitTests"
},
{
"name": "SettingsUnitTests",
"options": [
{
"include-filter": "com.android.settings.password"
},
{
"include-filter": "com.android.settings.biometrics"
},
{
"include-filter": "com.android.settings.biometrics2"
}
]
} }
], ],
"postsubmit": [ "postsubmit": [

View File

@@ -20,6 +20,7 @@ message BatteryOptimizeHistoricalLogEntry {
RESET = 3; RESET = 3;
RESTORE = 4; RESTORE = 4;
BACKUP = 5; BACKUP = 5;
FORCE_RESET = 6;
} }
optional string package_name = 1; optional string package_name = 1;

View File

@@ -15,10 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid
android:color="?androidprv:attr/materialColorSurfaceContainer" />
<stroke <stroke
android:width="2dp" android:width="2dp"
android:color="?android:attr/colorAccent"/> android:color="?android:attr/colorAccent"/>

View File

@@ -18,7 +18,7 @@
android:shape="rectangle"> android:shape="rectangle">
<stroke <stroke
android:width="1dp" android:width="1dp"
android:color="@color/notification_importance_button_unselected"/> android:color="?android:attr/colorAccent"/>
<corners android:radius="@dimen/rect_button_radius" /> <corners android:radius="@dimen/rect_button_radius" />
</shape> </shape>

View File

@@ -1,24 +1,31 @@
<!-- <!--
~ Copyright (C) 2023 The Android Open Source Project 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.
-->
<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 <item
android:state_checked="true" android:bottom="12dp"
android:drawable="@drawable/ic_check_circle_filled_24dp" /> android:left="12dp"
<item android:right="12dp"
android:state_checked="false" android:top="12dp">
android:drawable="@drawable/ic_circle_outline_24dp" /> <selector>
</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>

View File

@@ -74,7 +74,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:gravity="center" android:gravity="center"
android:paddingLeft="14dp"
android:text="@string/auto_pin_confirm_user_message" android:text="@string/auto_pin_confirm_user_message"
android:textSize="16sp" android:textSize="16sp"
android:button="@drawable/checkbox_circle_shape" android:button="@drawable/checkbox_circle_shape"

View File

@@ -526,6 +526,10 @@
<item>content://com.android.settings.slices/intent/media_output_indicator</item> <item>content://com.android.settings.slices/intent/media_output_indicator</item>
</string-array> </string-array>
<!-- List containing the apps cannot be changed the battery optimize modes -->
<string-array name="config_disable_optimization_mode_apps" translatable="false">
</string-array>
<!-- Uri to query non-public Slice Uris. --> <!-- Uri to query non-public Slice Uris. -->
<string name="config_non_public_slice_query_uri" translatable="false"></string> <string name="config_non_public_slice_query_uri" translatable="false"></string>

View File

@@ -4243,7 +4243,7 @@
<string name="accessibility_screen_magnification_follow_typing_title">Magnify typing</string> <string name="accessibility_screen_magnification_follow_typing_title">Magnify typing</string>
<!-- Summary for accessibility follow typing preference for magnification. [CHAR LIMIT=none] --> <!-- 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> <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> <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] --> <!-- 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> <string name="accessibility_screen_magnification_always_on_summary">Magnifier stays on and zooms out when you switch apps</string>

View File

@@ -227,6 +227,9 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style> </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 --> <!-- Material theme for the pages containing TabLayout and ViewPager -->
<style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight"> <style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/edge_effect_device_default_light</item> <item name="colorPrimary">@*android:color/edge_effect_device_default_light</item>

View File

@@ -66,6 +66,10 @@ public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceControlle
@Override @Override
public void onDestroy() { public void onDestroy() {
mHandler.removeCallbacksAndMessages(null); mHandler.removeCallbacksAndMessages(null);
final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
if (isTooltipWindowShowing) {
mTooltipWindow.dismiss();
}
} }
@Override @Override

View File

@@ -28,7 +28,6 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.widget.LabeledSeekBarPreference; import com.android.settings.widget.LabeledSeekBarPreference;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate; import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnDestroy; import com.android.settingslib.core.lifecycle.events.OnDestroy;
@@ -111,6 +110,10 @@ abstract class PreviewSizeSeekBarController extends BasePreferenceController imp
public void onDestroy() { public void onDestroy() {
// remove runnables in the queue. // remove runnables in the queue.
mHandler.removeCallbacksAndMessages(null); mHandler.removeCallbacksAndMessages(null);
final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
if (isTooltipWindowShowing) {
mTooltipWindow.dismiss();
}
} }
@Override @Override

View File

@@ -296,6 +296,10 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
removeActionBarToggleSwitch(); removeActionBarToggleSwitch();
final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
if (isTooltipWindowShowing) {
mTooltipWindow.dismiss();
}
} }
@Override @Override

View File

@@ -75,6 +75,9 @@ public class ClonedAppsPreferenceController extends BasePreferenceController
} }
private void updatePreferenceSummary() { private void updatePreferenceSummary() {
if (!isAvailable()) {
return;
}
new AsyncTask<Void, Void, Integer[]>() { new AsyncTask<Void, Void, Integer[]>() {
@Override @Override

View File

@@ -343,7 +343,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
final String stateString; final String stateString;
final String footerString; final String footerString;
if (!mBatteryOptimizeUtils.isValidPackageName()) { if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
// Present optimized only string when the package name is invalid. // Present optimized only string when the package name is invalid.
stateString = context.getString(R.string.manager_battery_usage_optimized_only); stateString = context.getString(R.string.manager_battery_usage_optimized_only);
footerString = context.getString( footerString = context.getString(

View File

@@ -25,17 +25,20 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager; import android.content.pm.IPackageManager;
import android.os.Build;
import android.os.IDeviceIdleController; import android.os.IDeviceIdleController;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend; import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import java.io.IOException; import java.io.IOException;
@@ -49,13 +52,22 @@ import java.util.List;
public final class BatteryBackupHelper implements BackupHelper { public final class BatteryBackupHelper implements BackupHelper {
/** An inditifier for {@link BackupHelper}. */ /** An inditifier for {@link BackupHelper}. */
public static final String TAG = "BatteryBackupHelper"; 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 DEVICE_IDLE_SERVICE = "deviceidle";
private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME = private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME =
"battery_optimize_backup_historical_logs"; "battery_optimize_backup_historical_logs";
private static final int DEVICE_BUILD_INFO_SIZE = 6;
static final String DELIMITER = ","; static final String DELIMITER = ",";
static final String DELIMITER_MODE = ":"; static final String DELIMITER_MODE = ":";
static final String KEY_FULL_POWER_LIST = "full_power_list";
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list"; static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
@VisibleForTesting @VisibleForTesting
@@ -70,7 +82,13 @@ public final class BatteryBackupHelper implements BackupHelper {
@VisibleForTesting @VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils; BatteryOptimizeUtils mBatteryOptimizeUtils;
private byte[] mOptimizationModeBytes;
private boolean mVerifyMigrateConfiguration = false;
private final Context mContext; 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) { public BatteryBackupHelper(Context context) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
@@ -83,37 +101,58 @@ public final class BatteryBackupHelper implements BackupHelper {
Log.w(TAG, "ignore performBackup() for non-owner or empty data"); Log.w(TAG, "ignore performBackup() for non-owner or empty data");
return; return;
} }
final List<String> allowlistedApps = backupFullPowerList(data); final List<String> allowlistedApps = getFullPowerList();
if (allowlistedApps != null) { if (allowlistedApps == null) {
backupOptimizationMode(data, allowlistedApps); 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 @Override
public void restoreEntity(BackupDataInputStream data) { public void restoreEntity(BackupDataInputStream data) {
BatterySettingsMigrateChecker.verifyConfiguration(mContext); // Ensure we only verify the migrate configuration one time.
if (!mVerifyMigrateConfiguration) {
mVerifyMigrateConfiguration = true;
BatterySettingsMigrateChecker.verifySaverConfiguration(mContext);
}
if (!isOwner() || data == null || data.size() == 0) { if (!isOwner() || data == null || data.size() == 0) {
Log.w(TAG, "ignore restoreEntity() for non-owner or empty data"); Log.w(TAG, "ignore restoreEntity() for non-owner or empty data");
return; return;
} }
if (KEY_OPTIMIZATION_LIST.equals(data.getKey())) { final String dataKey = data.getKey();
final int dataSize = data.size(); switch (dataKey) {
final byte[] dataBytes = new byte[dataSize]; case KEY_BUILD_BRAND:
try { case KEY_BUILD_PRODUCT:
data.read(dataBytes, 0 /*offset*/, dataSize); case KEY_BUILD_MANUFACTURER:
} catch (IOException e) { case KEY_BUILD_FINGERPRINT:
Log.e(TAG, "failed to load BackupDataInputStream", e); case KEY_BUILD_METADATA_1:
return; case KEY_BUILD_METADATA_2:
} restoreBackupData(dataKey, data);
restoreOptimizationMode(dataBytes); break;
case KEY_OPTIMIZATION_LIST:
// Hold the optimization mode data until all conditions are matched.
mOptimizationModeBytes = getBackupData(dataKey, data);
break;
} }
performRestoreIfNeeded();
} }
@Override @Override
public void writeNewStateDescription(ParcelFileDescriptor newState) { public void writeNewStateDescription(ParcelFileDescriptor newState) {
} }
private List<String> backupFullPowerList(BackupDataOutput data) { private List<String> getFullPowerList() {
final long timestamp = System.currentTimeMillis(); final long timestamp = System.currentTimeMillis();
String[] allowlistedApps; String[] allowlistedApps;
try { try {
@@ -127,10 +166,7 @@ public final class BatteryBackupHelper implements BackupHelper {
Log.w(TAG, "no data found in the getFullPowerList()"); Log.w(TAG, "no data found in the getFullPowerList()");
return new ArrayList<>(); return new ArrayList<>();
} }
Log.d(TAG, String.format("getFullPowerList() size=%d in %d/ms",
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",
allowlistedApps.length, (System.currentTimeMillis() - timestamp))); allowlistedApps.length, (System.currentTimeMillis() - timestamp)));
return Arrays.asList(allowlistedApps); return Arrays.asList(allowlistedApps);
} }
@@ -175,17 +211,17 @@ public final class BatteryBackupHelper implements BackupHelper {
} }
@VisibleForTesting @VisibleForTesting
void restoreOptimizationMode(byte[] dataBytes) { int restoreOptimizationMode(byte[] dataBytes) {
final long timestamp = System.currentTimeMillis(); final long timestamp = System.currentTimeMillis();
final String dataContent = new String(dataBytes, StandardCharsets.UTF_8); final String dataContent = new String(dataBytes, StandardCharsets.UTF_8);
if (dataContent == null || dataContent.isEmpty()) { if (dataContent == null || dataContent.isEmpty()) {
Log.w(TAG, "no data found in the restoreOptimizationMode()"); Log.w(TAG, "no data found in the restoreOptimizationMode()");
return; return 0;
} }
final String[] appConfigurations = dataContent.split(BatteryBackupHelper.DELIMITER); final String[] appConfigurations = dataContent.split(BatteryBackupHelper.DELIMITER);
if (appConfigurations == null || appConfigurations.length == 0) { if (appConfigurations == null || appConfigurations.length == 0) {
Log.w(TAG, "no data found from the split() processing"); Log.w(TAG, "no data found from the split() processing");
return; return 0;
} }
int restoreCount = 0; int restoreCount = 0;
for (int index = 0; index < appConfigurations.length; index++) { for (int index = 0; index < appConfigurations.length; index++) {
@@ -217,6 +253,24 @@ public final class BatteryBackupHelper implements BackupHelper {
} }
Log.d(TAG, String.format("restoreOptimizationMode() count=%d in %d/ms", Log.d(TAG, String.format("restoreOptimizationMode() count=%d in %d/ms",
restoreCount, (System.currentTimeMillis() - timestamp))); restoreCount, (System.currentTimeMillis() - timestamp)));
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. */ /** Dump the app optimization mode backup history data. */
@@ -225,6 +279,23 @@ public final class BatteryBackupHelper implements BackupHelper {
getSharedPreferences(context), writer); getSharedPreferences(context), writer);
} }
static boolean isOwner() {
return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
}
static BatteryOptimizeUtils newBatteryOptimizeUtils(
Context context, String packageName, BatteryOptimizeUtils testOptimizeUtils) {
final int uid = BatteryUtils.getInstance(context).getPackageUid(packageName);
if (uid == BatteryUtils.UID_NULL) {
return null;
}
final BatteryOptimizeUtils batteryOptimizeUtils =
testOptimizeUtils != null
? testOptimizeUtils /*testing only*/
: new BatteryOptimizeUtils(context, uid, packageName);
return batteryOptimizeUtils;
}
@VisibleForTesting @VisibleForTesting
static SharedPreferences getSharedPreferences(Context context) { static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences( return context.getSharedPreferences(
@@ -233,14 +304,11 @@ public final class BatteryBackupHelper implements BackupHelper {
private void restoreOptimizationMode( private void restoreOptimizationMode(
String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) { String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) {
final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName); final BatteryOptimizeUtils batteryOptimizeUtils =
if (uid == BatteryUtils.UID_NULL) { newBatteryOptimizeUtils(mContext, packageName, mBatteryOptimizeUtils);
if (batteryOptimizeUtils == null) {
return; return;
} }
final BatteryOptimizeUtils batteryOptimizeUtils =
mBatteryOptimizeUtils != null
? mBatteryOptimizeUtils /*testing only*/
: new BatteryOptimizeUtils(mContext, uid, packageName);
batteryOptimizeUtils.setAppUsageState( batteryOptimizeUtils.setAppUsageState(
mode, BatteryOptimizeHistoricalLogEntry.Action.RESTORE); mode, BatteryOptimizeHistoricalLogEntry.Action.RESTORE);
Log.d(TAG, String.format("restore:%s mode=%d", packageName, mode)); Log.d(TAG, String.format("restore:%s mode=%d", packageName, mode));
@@ -284,8 +352,33 @@ public final class BatteryBackupHelper implements BackupHelper {
return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager()); 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( private static void writeBackupData(
BackupDataOutput data, String dataKey, String dataContent) { BackupDataOutput data, String dataKey, String dataContent) {
if (dataContent == null || dataContent.isEmpty()) {
return;
}
final byte[] dataContentBytes = dataContent.getBytes(); final byte[] dataContentBytes = dataContent.getBytes();
try { try {
data.writeEntityHeader(dataKey, dataContentBytes.length); data.writeEntityHeader(dataKey, dataContentBytes.length);
@@ -293,9 +386,6 @@ public final class BatteryBackupHelper implements BackupHelper {
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "writeBackupData() is failed for " + dataKey, e); Log.e(TAG, "writeBackupData() is failed for " + dataKey, e);
} }
} Log.d(TAG, String.format("backup:%s:%s", dataKey, dataContent));
private static boolean isOwner() {
return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
} }
} }

View File

@@ -34,24 +34,20 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
/** /**
* Use this broadcastReceiver to listen to the battery change, and it will invoke * Use this broadcastReceiver to listen to the battery change and it will invoke
* {@link OnBatteryChangedListener} if any of the following has been changed: * {@link OnBatteryChangedListener}
*
* 1. Battery level(e.g. 100%->99%)
* 2. Battery status(e.g. plugged->unplugged)
* 3. Battery saver(e.g. off->on)
* 4. Battery health(e.g. good->overheat)
*/ */
public class BatteryBroadcastReceiver extends BroadcastReceiver { public class BatteryBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "BatteryBroadcastRcvr"; private static final String TAG = "BatteryBroadcastRcvr";
/** /**
* Callback when the following has been changed: * Callback if any of the monitored fields has been changed:
* *
* Battery level(e.g. 100%->99%) * Battery level(e.g. 100%->99%)
* Battery status(e.g. plugged->unplugged) * Battery status(e.g. plugged->unplugged)
* Battery saver(e.g. off->on) * Battery saver(e.g. off->on)
* Battery health(e.g. good->overheat) * Battery health(e.g. good->overheat)
* Battery charging status(e.g. default->long life)
*/ */
public interface OnBatteryChangedListener { public interface OnBatteryChangedListener {
void onBatteryChanged(@BatteryUpdateType int type); void onBatteryChanged(@BatteryUpdateType int type);
@@ -63,6 +59,7 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
BatteryUpdateType.BATTERY_SAVER, BatteryUpdateType.BATTERY_SAVER,
BatteryUpdateType.BATTERY_STATUS, BatteryUpdateType.BATTERY_STATUS,
BatteryUpdateType.BATTERY_HEALTH, BatteryUpdateType.BATTERY_HEALTH,
BatteryUpdateType.CHARGING_STATUS,
BatteryUpdateType.BATTERY_NOT_PRESENT}) BatteryUpdateType.BATTERY_NOT_PRESENT})
public @interface BatteryUpdateType { public @interface BatteryUpdateType {
int MANUAL = 0; int MANUAL = 0;
@@ -70,7 +67,8 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
int BATTERY_SAVER = 2; int BATTERY_SAVER = 2;
int BATTERY_STATUS = 3; int BATTERY_STATUS = 3;
int BATTERY_HEALTH = 4; int BATTERY_HEALTH = 4;
int BATTERY_NOT_PRESENT = 5; int CHARGING_STATUS = 5;
int BATTERY_NOT_PRESENT = 6;
} }
@VisibleForTesting @VisibleForTesting
@@ -78,6 +76,8 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
@VisibleForTesting @VisibleForTesting
String mBatteryStatus; String mBatteryStatus;
@VisibleForTesting @VisibleForTesting
int mChargingStatus;
@VisibleForTesting
int mBatteryHealth; int mBatteryHealth;
private OnBatteryChangedListener mBatteryListener; private OnBatteryChangedListener mBatteryListener;
private Context mContext; private Context mContext;
@@ -121,21 +121,27 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
final String batteryLevel = Utils.getBatteryPercentage(intent); final String batteryLevel = Utils.getBatteryPercentage(intent);
final String batteryStatus = final String batteryStatus =
Utils.getBatteryStatus(mContext, intent, /* compactStatus= */ false); Utils.getBatteryStatus(mContext, intent, /* compactStatus= */ false);
final int chargingStatus = intent.getIntExtra(
BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_DEFAULT);
final int batteryHealth = intent.getIntExtra( final int batteryHealth = intent.getIntExtra(
BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN); BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
Log.d( Log.d(
TAG, TAG,
"Battery changed: level=" "Battery changed: level: "
+ batteryLevel + batteryLevel
+ ", status=" + "| status: "
+ batteryStatus + batteryStatus
+ ", health=" + "| chargingStatus: "
+ chargingStatus
+ "| health: "
+ batteryHealth); + batteryHealth);
if (!Utils.isBatteryPresent(intent)) { if (!Utils.isBatteryPresent(intent)) {
Log.w(TAG, "Problem reading the battery meter."); Log.w(TAG, "Problem reading the battery meter.");
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT); mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
} else if (forceUpdate) { } else if (forceUpdate) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL); mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL);
} else if (chargingStatus != mChargingStatus) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.CHARGING_STATUS);
} else if (batteryHealth != mBatteryHealth) { } else if (batteryHealth != mBatteryHealth) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH); mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH);
} else if(!batteryLevel.equals(mBatteryLevel)) { } else if(!batteryLevel.equals(mBatteryLevel)) {
@@ -145,6 +151,7 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
} }
mBatteryLevel = batteryLevel; mBatteryLevel = batteryLevel;
mBatteryStatus = batteryStatus; mBatteryStatus = batteryStatus;
mChargingStatus = chargingStatus;
mBatteryHealth = batteryHealth; mBatteryHealth = batteryHealth;
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) { } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER); mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER);

View File

@@ -51,7 +51,7 @@ public class BatteryInfo {
public int batteryStatus; public int batteryStatus;
public int pluggedStatus; public int pluggedStatus;
public boolean discharging = true; public boolean discharging = true;
public boolean isOverheated; public boolean isBatteryDefender;
public long remainingTimeUs = 0; public long remainingTimeUs = 0;
public long averageTimeToDischarge = EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN; public long averageTimeToDischarge = EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN;
public String batteryPercentString; public String batteryPercentString;
@@ -257,9 +257,9 @@ public class BatteryInfo {
info.pluggedStatus = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); info.pluggedStatus = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
info.mCharging = info.pluggedStatus != 0; info.mCharging = info.pluggedStatus != 0;
info.averageTimeToDischarge = estimate.getAverageDischargeTime(); info.averageTimeToDischarge = estimate.getAverageDischargeTime();
info.isOverheated = batteryBroadcast.getIntExtra( info.isBatteryDefender = batteryBroadcast.getIntExtra(
BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN) BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_DEFAULT)
== BatteryManager.BATTERY_HEALTH_OVERHEAT; == BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE;
info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast, isCompactStatus); info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast, isCompactStatus);
info.batteryStatus = batteryBroadcast.getIntExtra( info.batteryStatus = batteryBroadcast.getIntExtra(
@@ -283,7 +283,7 @@ public class BatteryInfo {
info.discharging = false; info.discharging = false;
info.suggestionLabel = null; info.suggestionLabel = null;
int dockDefenderMode = BatteryUtils.getCurrentDockDefenderMode(context, info); int dockDefenderMode = BatteryUtils.getCurrentDockDefenderMode(context, info);
if ((info.isOverheated && status != BatteryManager.BATTERY_STATUS_FULL if ((info.isBatteryDefender && status != BatteryManager.BATTERY_STATUS_FULL
&& dockDefenderMode == BatteryUtils.DockDefenderMode.DISABLED) && dockDefenderMode == BatteryUtils.DockDefenderMode.DISABLED)
|| dockDefenderMode == BatteryUtils.DockDefenderMode.ACTIVE) { || dockDefenderMode == BatteryUtils.DockDefenderMode.ACTIVE) {
// Battery defender active, battery charging paused // Battery defender active, battery charging paused

View File

@@ -31,11 +31,14 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend; import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
/** A utility class for application usage operation. */ /** A utility class for application usage operation. */
public class BatteryOptimizeUtils { public class BatteryOptimizeUtils {
@@ -125,11 +128,10 @@ public class BatteryOptimizeUtils {
mContext, mode, mUid, mPackageName, mBatteryUtils, mPowerAllowListBackend, action); mContext, mode, mUid, mPackageName, mBatteryUtils, mPowerAllowListBackend, action);
} }
/** /** Return {@code true} if it is disabled for default optimized mode only. */
* Return {@code true} if package name is valid (can get an uid). public boolean isDisabledForOptimizeModeOnly() {
*/ return getAllowList(mContext).contains(mPackageName)
public boolean isValidPackageName() { || mBatteryUtils.getPackageUid(mPackageName) == BatteryUtils.UID_NULL;
return mBatteryUtils.getPackageUid(mPackageName) != BatteryUtils.UID_NULL;
} }
/** /**
@@ -214,6 +216,11 @@ public class BatteryOptimizeUtils {
|| powerAllowlistBackend.isDefaultActiveApp(packageName, uid); || powerAllowlistBackend.isDefaultActiveApp(packageName, uid);
} }
static List<String> getAllowList(Context context) {
return Arrays.asList(context.getResources().getStringArray(
R.array.config_disable_optimization_mode_apps));
}
private static void setAppUsageStateInternal( private static void setAppUsageStateInternal(
Context context, @OptimizationMode int mode, int uid, String packageName, Context context, @OptimizationMode int mode, int uid, String packageName,
BatteryUtils batteryUtils, PowerAllowlistBackend powerAllowlistBackend, BatteryUtils batteryUtils, PowerAllowlistBackend powerAllowlistBackend,

View File

@@ -23,16 +23,27 @@ import android.content.Intent;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController; import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.fuelgauge.BatterySaverUtils;
import java.util.List;
/** Execute battery settings migration tasks in the device booting stage. */ /** Execute battery settings migration tasks in the device booting stage. */
public final class BatterySettingsMigrateChecker extends BroadcastReceiver { public final class BatterySettingsMigrateChecker extends BroadcastReceiver {
private static final String TAG = "BatterySettingsMigrateChecker"; private static final String TAG = "BatterySettingsMigrateChecker";
@VisibleForTesting
static BatteryOptimizeUtils sBatteryOptimizeUtils = null;
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (intent != null && Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { if (intent != null
&& Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())
&& BatteryBackupHelper.isOwner()) {
verifyConfiguration(context); verifyConfiguration(context);
} }
} }
@@ -40,9 +51,35 @@ public final class BatterySettingsMigrateChecker extends BroadcastReceiver {
static void verifyConfiguration(Context context) { static void verifyConfiguration(Context context) {
context = context.getApplicationContext(); context = context.getApplicationContext();
verifySaverConfiguration(context); verifySaverConfiguration(context);
verifyOptimizationModes(context);
} }
private static void verifySaverConfiguration(Context context) { /** Avoid users set important apps into the unexpected battery optimize modes */
static void verifyOptimizationModes(Context context) {
Log.d(TAG, "invoke verifyOptimizationModes()");
verifyOptimizationModes(context, BatteryOptimizeUtils.getAllowList(context));
}
@VisibleForTesting
static void verifyOptimizationModes(Context context, List<String> allowList) {
allowList.forEach(packageName -> {
final BatteryOptimizeUtils batteryOptimizeUtils =
BatteryBackupHelper.newBatteryOptimizeUtils(context, packageName,
/* testOptimizeUtils */ sBatteryOptimizeUtils);
if (batteryOptimizeUtils == null) {
return;
}
if (batteryOptimizeUtils.getAppOptimizationMode() !=
BatteryOptimizeUtils.MODE_OPTIMIZED) {
Log.w(TAG, "Reset optimization mode for: " + packageName);
batteryOptimizeUtils.setAppUsageState(BatteryOptimizeUtils.MODE_OPTIMIZED,
BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
}
});
}
static void verifySaverConfiguration(Context context) {
Log.d(TAG, "invoke verifySaverConfiguration()");
final ContentResolver resolver = context.getContentResolver(); final ContentResolver resolver = context.getContentResolver();
final int threshold = Settings.Global.getInt(resolver, final int threshold = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0); Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);

View File

@@ -18,7 +18,6 @@ package com.android.settings.fuelgauge;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo; import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
@@ -322,10 +321,10 @@ public class BatteryUtils {
} }
/** /**
* Return {@code true} if battery is overheated and charging. * Return {@code true} if battery defender is on and charging.
*/ */
public static boolean isBatteryDefenderOn(BatteryInfo batteryInfo) { public static boolean isBatteryDefenderOn(BatteryInfo batteryInfo) {
return batteryInfo.isOverheated && !batteryInfo.discharging; return batteryInfo.isBatteryDefender && !batteryInfo.discharging;
} }
/** /**
@@ -627,11 +626,11 @@ public class BatteryUtils {
if (Settings.Global.getInt(context.getContentResolver(), if (Settings.Global.getInt(context.getContentResolver(),
SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 0) == 1) { SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 0) == 1) {
return DockDefenderMode.TEMPORARILY_BYPASSED; return DockDefenderMode.TEMPORARILY_BYPASSED;
} else if (batteryInfo.isOverheated && FeatureFactory.getFactory(context) } else if (batteryInfo.isBatteryDefender && FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context) .getPowerUsageFeatureProvider(context)
.isExtraDefend()) { .isExtraDefend()) {
return DockDefenderMode.ACTIVE; return DockDefenderMode.ACTIVE;
} else if (!batteryInfo.isOverheated) { } else if (!batteryInfo.isBatteryDefender) {
return DockDefenderMode.FUTURE_BYPASS; return DockDefenderMode.FUTURE_BYPASS;
} }
} }

View File

@@ -46,8 +46,8 @@ public class OptimizedPreferenceController extends AbstractPreferenceController
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (!mBatteryOptimizeUtils.isValidPackageName()) { if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
Log.d(TAG, "invalid package name, optimized states only"); Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
preference.setEnabled(true); preference.setEnabled(true);
((SelectorWithWidgetPreference) preference).setChecked(true); ((SelectorWithWidgetPreference) preference).setChecked(true);
return; return;

View File

@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.ArrayMap;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.fuelgauge.Estimate;
@@ -166,4 +167,19 @@ public interface PowerUsageFeatureProvider {
* Returns {@link Set} for ignoring task root class names for screen on time * Returns {@link Set} for ignoring task root class names for screen on time
*/ */
Set<String> getIgnoreScreenOnTimeTaskRootSet(); 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);
} }

View File

@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Process; import android.os.Process;
import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.SparseIntArray; import android.util.SparseIntArray;
@@ -188,4 +189,19 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
public Set<String> getIgnoreScreenOnTimeTaskRootSet() { public Set<String> getIgnoreScreenOnTimeTaskRootSet() {
return new ArraySet<>(); 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;
}
} }

View File

@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
@@ -43,8 +42,8 @@ public class RestrictedPreferenceController extends AbstractPreferenceController
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (!mBatteryOptimizeUtils.isValidPackageName()) { if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
Log.d(TAG, "invalid package name, disable pref"); Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
preference.setEnabled(false); preference.setEnabled(false);
return; return;
} else { } else {

View File

@@ -42,8 +42,8 @@ public class UnrestrictedPreferenceController extends AbstractPreferenceControll
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (!mBatteryOptimizeUtils.isValidPackageName()) { if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
Log.d(TAG, "invalid package name, disable pref"); Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
preference.setEnabled(false); preference.setEnabled(false);
return; return;
} else { } else {

View File

@@ -37,13 +37,12 @@ public class BatteryDefenderDetector implements BatteryTipDetector {
@Override @Override
public BatteryTip detect() { public BatteryTip detect() {
final boolean isBasicBatteryDefend = mBatteryInfo.isOverheated final boolean isBasicBatteryDefend = mBatteryInfo.isBatteryDefender
&& !FeatureFactory.getFactory(mContext) && !FeatureFactory.getFactory(mContext).getPowerUsageFeatureProvider(mContext)
.getPowerUsageFeatureProvider(mContext) .isExtraDefend();
.isExtraDefend(); final int state = isBasicBatteryDefend
final int state = isBasicBatteryDefend ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE;
? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE; final boolean isPluggedIn = mBatteryInfo.pluggedStatus != 0;
final boolean isPluggedIn = mBatteryInfo.pluggedStatus != 0; return new BatteryDefenderTip(state, isPluggedIn);
return new BatteryDefenderTip(state, isPluggedIn);
} }
} }

View File

@@ -141,6 +141,7 @@ public class BiometricFragment extends InstrumentedFragment {
.setDisallowBiometricsIfPolicyExists( .setDisallowBiometricsIfPolicyExists(
promptInfo.isDisallowBiometricsIfPolicyExists()) promptInfo.isDisallowBiometricsIfPolicyExists())
.setReceiveSystemEvents(true) .setReceiveSystemEvents(true)
.setAllowBackgroundAuthentication(true)
.build(); .build();
} }

View File

@@ -19,6 +19,8 @@ package com.android.settings.regionalpreferences;
import android.content.Context; import android.content.Context;
import android.provider.Settings; import android.provider.Settings;
import androidx.core.text.util.LocalePreferences;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;

View File

@@ -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() {
}
}

View File

@@ -63,7 +63,9 @@ public abstract class RegionalPreferenceListBasePreferenceController extends
pref.setKey(item); pref.setKey(item);
pref.setOnPreferenceClickListener(clickedPref -> { pref.setOnPreferenceClickListener(clickedPref -> {
setSelected(pref); setSelected(pref);
RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(), item); RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(),
item.equals(RegionalPreferencesDataUtils.DEFAULT_VALUE)
? null : item);
mMetricsFeatureProvider.action(mContext, getMetricsActionKey()); mMetricsFeatureProvider.action(mContext, getMetricsActionKey());
return true; return true;
}); });

View File

@@ -22,6 +22,8 @@ import android.os.LocaleList;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.core.text.util.LocalePreferences;
import com.android.internal.app.LocalePicker; import com.android.internal.app.LocalePicker;
import com.android.settings.R; import com.android.settings.R;

View File

@@ -19,6 +19,8 @@ package com.android.settings.regionalpreferences;
import android.content.Context; import android.content.Context;
import android.provider.Settings; import android.provider.Settings;
import androidx.core.text.util.LocalePreferences;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;

View File

@@ -710,7 +710,7 @@ public class AdvancedPowerUsageDetailTest {
@Test @Test
public void initPreferenceForTriState_isValidPackageName_hasCorrectString() { public void initPreferenceForTriState_isValidPackageName_hasCorrectString() {
when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mFragment.initPreferenceForTriState(mContext); mFragment.initPreferenceForTriState(mContext);
@@ -720,7 +720,7 @@ public class AdvancedPowerUsageDetailTest {
@Test @Test
public void initPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() { public void initPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mFragment.initPreferenceForTriState(mContext); mFragment.initPreferenceForTriState(mContext);
@@ -731,7 +731,7 @@ public class AdvancedPowerUsageDetailTest {
@Test @Test
public void initPreferenceForTriState_hasCorrectString() { public void initPreferenceForTriState_hasCorrectString() {
when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mFragment.initPreferenceForTriState(mContext); mFragment.initPreferenceForTriState(mContext);

View File

@@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.inOrder;
@@ -45,6 +46,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.Build;
import android.os.IDeviceIdleController; import android.os.IDeviceIdleController;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
@@ -53,6 +55,7 @@ import android.util.ArraySet;
import com.android.settings.TestUtils; import com.android.settings.TestUtils;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend; import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import org.junit.After; import org.junit.After;
@@ -89,6 +92,7 @@ public final class BatteryBackupHelperTest {
private PrintWriter mPrintWriter; private PrintWriter mPrintWriter;
private StringWriter mStringWriter; private StringWriter mStringWriter;
private BatteryBackupHelper mBatteryBackupHelper; private BatteryBackupHelper mBatteryBackupHelper;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@@ -112,6 +116,8 @@ public final class BatteryBackupHelperTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mPowerUsageFeatureProvider =
FakeFeatureFactory.setupForTest().powerUsageFeatureProvider;
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
mStringWriter = new StringWriter(); mStringWriter = new StringWriter();
mPrintWriter = new PrintWriter(mStringWriter); mPrintWriter = new PrintWriter(mStringWriter);
@@ -136,19 +142,11 @@ public final class BatteryBackupHelperTest {
} }
@Test @Test
public void performBackup_nullPowerList_notBackupPowerList() throws Exception { public void performBackup_emptyPowerList_backupPowerList() 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 {
doReturn(new String[0]).when(mDeviceController).getFullPowerWhitelist(); doReturn(new String[0]).when(mDeviceController).getFullPowerWhitelist();
mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null); mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt()); verify(mBackupDataOutput, atLeastOnce()).writeEntityHeader(anyString(), anyInt());
} }
@Test @Test
@@ -159,34 +157,6 @@ public final class BatteryBackupHelperTest {
verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt()); 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 @Test
public void performBackup_nonOwner_ignoreAllBackupAction() throws Exception { public void performBackup_nonOwner_ignoreAllBackupAction() throws Exception {
ShadowUserHandle.setUid(1); ShadowUserHandle.setUid(1);
@@ -283,7 +253,7 @@ public final class BatteryBackupHelperTest {
@Test @Test
public void restoreEntity_incorrectDataKey_notReadBackupData() throws Exception { 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); mockBackupData(30 /*dataSize*/, incorrectDataKey);
mBatteryBackupHelper.restoreEntity(mBackupDataInputStream); mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
@@ -313,6 +283,20 @@ public final class BatteryBackupHelperTest {
assertThat(TestUtils.getScheduledLevel(mContext)).isNotEqualTo(invalidScheduledLevel); assertThat(TestUtils.getScheduledLevel(mContext)).isNotEqualTo(invalidScheduledLevel);
} }
@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 @Test
public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception { public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception {
mBatteryBackupHelper.restoreOptimizationMode(new byte[0]); mBatteryBackupHelper.restoreOptimizationMode(new byte[0]);
@@ -358,6 +342,26 @@ public final class BatteryBackupHelperTest {
.setAppUsageState(MODE_RESTRICTED, Action.RESTORE); .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 { private void mockUid(int uid, String packageName) throws Exception {
doReturn(uid).when(mPackageManager) doReturn(uid).when(mPackageManager)
.getPackageUid(packageName, PackageManager.GET_META_DATA); .getPackageUid(packageName, PackageManager.GET_META_DATA);
@@ -429,6 +433,13 @@ public final class BatteryBackupHelperTest {
new ArraySet<>(Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3)); 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) @Implements(UserHandle.class)
public static class ShadowUserHandle { public static class ShadowUserHandle {
// Sets the default as thte OWNER role. // Sets the default as thte OWNER role.

View File

@@ -69,6 +69,7 @@ public class BatteryBroadcastReceiverTest {
mBatteryBroadcastReceiver.mBatteryLevel = BATTERY_INIT_LEVEL; mBatteryBroadcastReceiver.mBatteryLevel = BATTERY_INIT_LEVEL;
mBatteryBroadcastReceiver.mBatteryStatus = BATTERY_INIT_STATUS; mBatteryBroadcastReceiver.mBatteryStatus = BATTERY_INIT_STATUS;
mBatteryBroadcastReceiver.mBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN; mBatteryBroadcastReceiver.mBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN;
mBatteryBroadcastReceiver.mChargingStatus = BatteryManager.CHARGING_POLICY_DEFAULT;
mBatteryBroadcastReceiver.setBatteryChangedListener(mBatteryListener); mBatteryBroadcastReceiver.setBatteryChangedListener(mBatteryListener);
mChargingIntent = new Intent(Intent.ACTION_BATTERY_CHANGED); mChargingIntent = new Intent(Intent.ACTION_BATTERY_CHANGED);
@@ -91,8 +92,8 @@ public class BatteryBroadcastReceiverTest {
@Test @Test
public void onReceive_batteryHealthChanged_dataUpdated() { public void onReceive_batteryHealthChanged_dataUpdated() {
mChargingIntent mChargingIntent.putExtra(
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT); BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT);
mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent); mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent);
assertThat(mBatteryBroadcastReceiver.mBatteryHealth) assertThat(mBatteryBroadcastReceiver.mBatteryHealth)
@@ -100,6 +101,17 @@ public class BatteryBroadcastReceiverTest {
verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH); verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH);
} }
@Test
public void onReceive_chargingStatusChanged_dataUpdated() {
mChargingIntent.putExtra(BatteryManager.EXTRA_CHARGING_STATUS,
BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE);
mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent);
assertThat(mBatteryBroadcastReceiver.mChargingStatus)
.isEqualTo(BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE);
verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.CHARGING_STATUS);
}
@Test @Test
public void onReceive_batteryNotPresent_shouldShowHelpMessage() { public void onReceive_batteryNotPresent_shouldShowHelpMessage() {
mChargingIntent.putExtra(BatteryManager.EXTRA_PRESENT, false); mChargingIntent.putExtra(BatteryManager.EXTRA_PRESENT, false);
@@ -131,6 +143,8 @@ public class BatteryBroadcastReceiverTest {
assertThat(mBatteryBroadcastReceiver.mBatteryStatus).isEqualTo(batteryStatus); assertThat(mBatteryBroadcastReceiver.mBatteryStatus).isEqualTo(batteryStatus);
assertThat(mBatteryBroadcastReceiver.mBatteryHealth) assertThat(mBatteryBroadcastReceiver.mBatteryHealth)
.isEqualTo(BatteryManager.BATTERY_HEALTH_UNKNOWN); .isEqualTo(BatteryManager.BATTERY_HEALTH_UNKNOWN);
assertThat(mBatteryBroadcastReceiver.mChargingStatus)
.isEqualTo(BatteryManager.CHARGING_POLICY_DEFAULT);
verify(mBatteryListener, never()).onBatteryChanged(anyInt()); verify(mBatteryListener, never()).onBatteryChanged(anyInt());
} }
@@ -163,6 +177,8 @@ public class BatteryBroadcastReceiverTest {
Utils.getBatteryStatus(mContext, mChargingIntent, /* compactStatus= */ false)); Utils.getBatteryStatus(mContext, mChargingIntent, /* compactStatus= */ false));
assertThat(mBatteryBroadcastReceiver.mBatteryHealth) assertThat(mBatteryBroadcastReceiver.mBatteryHealth)
.isEqualTo(BatteryManager.BATTERY_HEALTH_UNKNOWN); .isEqualTo(BatteryManager.BATTERY_HEALTH_UNKNOWN);
assertThat(mBatteryBroadcastReceiver.mChargingStatus)
.isEqualTo(BatteryManager.CHARGING_POLICY_DEFAULT);
// 2 times because register will force update the battery // 2 times because register will force update the battery
verify(mBatteryListener, times(2)).onBatteryChanged(BatteryUpdateType.MANUAL); verify(mBatteryListener, times(2)).onBatteryChanged(BatteryUpdateType.MANUAL);
} }

View File

@@ -290,8 +290,8 @@ public class BatteryHeaderPreferenceControllerTest {
} }
@Test @Test
public void updatePreference_isOverheat_showEmptyText() { public void updatePreference_isBatteryDefender_showEmptyText() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
mController.updateHeaderPreference(mBatteryInfo); mController.updateHeaderPreference(mBatteryInfo);

View File

@@ -214,18 +214,18 @@ public class BatteryInfoTest {
} }
@Test @Test
public void testGetBatteryInfo_chargingWithOverheated_updateChargeLabel() { public void testGetBatteryInfo_chargingWithDefender_updateChargeLabel() {
doReturn(TEST_CHARGE_TIME_REMAINING) doReturn(TEST_CHARGE_TIME_REMAINING)
.when(mBatteryUsageStats) .when(mBatteryUsageStats)
.getChargeTimeRemainingMs(); .getChargeTimeRemainingMs();
mChargingBatteryBroadcast mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_CHARGING_STATUS,
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT); BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast, BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */); false /* shortString */);
assertThat(info.isOverheated).isTrue(); assertThat(info.isBatteryDefender).isTrue();
assertThat(info.chargeLabel.toString()).contains(STATUS_CHARGING_PAUSED); assertThat(info.chargeLabel.toString()).contains(STATUS_CHARGING_PAUSED);
} }
@@ -238,7 +238,8 @@ public class BatteryInfoTest {
50 /* level */, 50 /* level */,
100 /* scale */, 100 /* scale */,
BatteryManager.BATTERY_STATUS_CHARGING) BatteryManager.BATTERY_STATUS_CHARGING)
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT); .putExtra(BatteryManager.EXTRA_CHARGING_STATUS,
BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, intent, BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, intent,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
@@ -250,8 +251,8 @@ public class BatteryInfoTest {
@Test @Test
public void testGetBatteryInfo_dockDefenderTemporarilyBypassed_updateChargeLabel() { public void testGetBatteryInfo_dockDefenderTemporarilyBypassed_updateChargeLabel() {
doReturn(REMAINING_TIME).when(mBatteryUsageStats).getChargeTimeRemainingMs(); doReturn(REMAINING_TIME).when(mBatteryUsageStats).getChargeTimeRemainingMs();
mChargingBatteryBroadcast mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_CHARGING_STATUS,
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_GOOD); BatteryManager.CHARGING_POLICY_DEFAULT);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.putInt(mContext.getContentResolver(),
BatteryUtils.SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 1); BatteryUtils.SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 1);
@@ -269,8 +270,8 @@ public class BatteryInfoTest {
@Test @Test
public void testGetBatteryInfo_dockDefenderFutureBypass_updateChargeLabel() { public void testGetBatteryInfo_dockDefenderFutureBypass_updateChargeLabel() {
doReturn(false).when(mFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(false).when(mFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
mChargingBatteryBroadcast mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_CHARGING_STATUS,
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_GOOD); BatteryManager.CHARGING_POLICY_DEFAULT);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, BatteryInfo info = BatteryInfo.getBatteryInfo(mContext,
BatteryTestUtils.getCustomBatteryIntent(BatteryManager.BATTERY_PLUGGED_DOCK, BatteryTestUtils.getCustomBatteryIntent(BatteryManager.BATTERY_PLUGGED_DOCK,

View File

@@ -136,16 +136,16 @@ public class BatteryOptimizeUtilsTest {
} }
@Test @Test
public void testIsValidPackageName_InvalidPackageName_returnFalse() { public void isDisabledForOptimizeModeOnly_invalidPackageName_returnTrue() {
final BatteryOptimizeUtils testBatteryOptimizeUtils = final BatteryOptimizeUtils testBatteryOptimizeUtils =
new BatteryOptimizeUtils(mContext, UID, null); new BatteryOptimizeUtils(mContext, UID, null);
assertThat(testBatteryOptimizeUtils.isValidPackageName()).isFalse(); assertThat(testBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).isTrue();
} }
@Test @Test
public void testIsValidPackageName_validPackageName_returnTrue() { public void isDisabledForOptimizeModeOnly_validPackageName_returnFalse() {
assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue(); assertThat(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).isFalse();
} }
@Test @Test

View File

@@ -18,35 +18,76 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.TestUtils; import com.android.settings.TestUtils;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController; import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import java.util.ArrayList;
import java.util.Arrays;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {BatterySettingsMigrateCheckerTest.ShadowUserHandle.class})
public final class BatterySettingsMigrateCheckerTest { public final class BatterySettingsMigrateCheckerTest {
private static final Intent BOOT_COMPLETED_INTENT = private static final Intent BOOT_COMPLETED_INTENT =
new Intent(Intent.ACTION_BOOT_COMPLETED); new Intent(Intent.ACTION_BOOT_COMPLETED);
private static final int UID = 2003;
private static final String PACKAGE_NAME = "com.android.test.app";
private Context mContext; private Context mContext;
private BatterySettingsMigrateChecker mBatterySettingsMigrateChecker; private BatterySettingsMigrateChecker mBatterySettingsMigrateChecker;
@Mock
private PackageManager mPackageManager;
@Mock
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Before @Before
public void setUp() { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application; mContext = spy(RuntimeEnvironment.application);
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(UID).when(mPackageManager)
.getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
BatterySettingsMigrateChecker.sBatteryOptimizeUtils = mBatteryOptimizeUtils;
mBatterySettingsMigrateChecker = new BatterySettingsMigrateChecker(); mBatterySettingsMigrateChecker = new BatterySettingsMigrateChecker();
} }
@After
public void resetShadows() {
ShadowUserHandle.reset();
}
@Test @Test
public void onReceive_invalidScheduledLevel_resetScheduledValue() { public void onReceive_invalidScheduledLevel_resetScheduledValue() {
final int invalidScheduledLevel = 5; final int invalidScheduledLevel = 5;
@@ -98,6 +139,54 @@ public final class BatterySettingsMigrateCheckerTest {
assertThat(getScheduledLevel()).isEqualTo(invalidScheduledLevel); assertThat(getScheduledLevel()).isEqualTo(invalidScheduledLevel);
} }
@Test
public void onReceive_nonOwner_noAction() {
ShadowUserHandle.setUid(1);
final int invalidScheduledLevel = 5;
setScheduledLevel(invalidScheduledLevel);
mBatterySettingsMigrateChecker.onReceive(mContext, BOOT_COMPLETED_INTENT);
assertThat(getScheduledLevel()).isEqualTo(invalidScheduledLevel);
}
@Test
public void verifyOptimizationModes_inAllowList_resetOptimizationMode() throws Exception {
doReturn(BatteryOptimizeUtils.MODE_RESTRICTED).when(mBatteryOptimizeUtils)
.getAppOptimizationMode();
mBatterySettingsMigrateChecker.verifyOptimizationModes(
mContext, Arrays.asList(PACKAGE_NAME));
final InOrder inOrder = inOrder(mBatteryOptimizeUtils);
inOrder.verify(mBatteryOptimizeUtils).getAppOptimizationMode();
inOrder.verify(mBatteryOptimizeUtils).setAppUsageState(
BatteryOptimizeUtils.MODE_OPTIMIZED,
BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
}
@Test
public void verifyOptimizationModes_optimizedMode_noAction() throws Exception {
doReturn(BatteryOptimizeUtils.MODE_OPTIMIZED).when(mBatteryOptimizeUtils)
.getAppOptimizationMode();
mBatterySettingsMigrateChecker.verifyOptimizationModes(
mContext, Arrays.asList(PACKAGE_NAME));
verify(mBatteryOptimizeUtils, never()).setAppUsageState(anyInt(), any());
}
@Test
public void verifyOptimizationModes_notInAllowList_noAction() throws Exception {
doReturn(BatteryOptimizeUtils.MODE_RESTRICTED).when(mBatteryOptimizeUtils)
.getAppOptimizationMode();
mBatterySettingsMigrateChecker.verifyOptimizationModes(
mContext, new ArrayList<String>());
verifyNoInteractions(mBatteryOptimizeUtils);
}
private void setScheduledLevel(int scheduledLevel) { private void setScheduledLevel(int scheduledLevel) {
TestUtils.setScheduledLevel(mContext, scheduledLevel); TestUtils.setScheduledLevel(mContext, scheduledLevel);
} }
@@ -105,4 +194,24 @@ public final class BatterySettingsMigrateCheckerTest {
private int getScheduledLevel() { private int getScheduledLevel() {
return TestUtils.getScheduledLevel(mContext); return TestUtils.getScheduledLevel(mContext);
} }
@Implements(UserHandle.class)
public static class ShadowUserHandle {
// Sets the default as thte OWNER role.
private static int sUid = 0;
public static void setUid(int uid) {
sUid = uid;
}
@Implementation
public static int myUserId() {
return sUid;
}
@Resetter
public static void reset() {
sUid = 0;
}
}
} }

View File

@@ -487,32 +487,32 @@ public class BatteryUtilsTest {
} }
@Test @Test
public void testIsBatteryDefenderOn_isOverheatedAndIsCharging_returnTrue() { public void testIsBatteryDefenderOn_isDefenderAndIsCharging_returnTrue() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
mBatteryInfo.discharging = false; mBatteryInfo.discharging = false;
assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isTrue(); assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isTrue();
} }
@Test @Test
public void testIsBatteryDefenderOn_isOverheatedAndDischarging_returnFalse() { public void testIsBatteryDefenderOn_isDefenderAndDischarging_returnFalse() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
mBatteryInfo.discharging = true; mBatteryInfo.discharging = true;
assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse(); assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();
} }
@Test @Test
public void testIsBatteryDefenderOn_notOverheatedAndDischarging_returnFalse() { public void testIsBatteryDefenderOn_notDefenderAndDischarging_returnFalse() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
mBatteryInfo.discharging = true; mBatteryInfo.discharging = true;
assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse(); assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();
} }
@Test @Test
public void testIsBatteryDefenderOn_notOverheatedAndIsCharging_returnFalse() { public void testIsBatteryDefenderOn_notDefenderAndIsCharging_returnFalse() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
mBatteryInfo.discharging = false; mBatteryInfo.discharging = false;
assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse(); assertThat(mBatteryUtils.isBatteryDefenderOn(mBatteryInfo)).isFalse();

View File

@@ -52,7 +52,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_invalidPackage_prefEnabled() { public void testUpdateState_invalidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -62,7 +62,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() { public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED); BatteryOptimizeUtils.MODE_OPTIMIZED);
@@ -74,7 +74,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() { public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -85,7 +85,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isOptimizedStates_prefChecked() { public void testUpdateState_isOptimizedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED); BatteryOptimizeUtils.MODE_OPTIMIZED);
@@ -96,7 +96,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_prefUnchecked() { public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);

View File

@@ -52,7 +52,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isValidPackage_prefEnabled() { public void testUpdateState_isValidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -61,7 +61,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_invalidPackage_prefDisabled() { public void testUpdateState_invalidPackage_prefDisabled() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -70,7 +70,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() { public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED); BatteryOptimizeUtils.MODE_RESTRICTED);
@@ -82,7 +82,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() { public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -93,7 +93,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isRestrictedStates_prefChecked() { public void testUpdateState_isRestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED); BatteryOptimizeUtils.MODE_RESTRICTED);
@@ -104,7 +104,7 @@ public class RestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_prefUnchecked() { public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);

View File

@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -53,7 +52,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isValidPackage_prefEnabled() { public void testUpdateState_isValidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -62,7 +61,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_invalidPackage_prefDisabled() { public void testUpdateState_invalidPackage_prefDisabled() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -71,7 +70,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() { public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED); BatteryOptimizeUtils.MODE_UNRESTRICTED);
@@ -83,7 +82,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() { public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -94,7 +93,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isUnrestrictedStates_prefChecked() { public void testUpdateState_isUnrestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED); BatteryOptimizeUtils.MODE_UNRESTRICTED);
@@ -105,7 +104,7 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_prefUnchecked() { public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true); when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);

View File

@@ -60,32 +60,32 @@ public class BatteryDefenderDetectorTest {
} }
@Test @Test
public void testDetect_notOverheatedNotExtraDefend_tipInvisible() { public void testDetect_notDefenderNotExtraDefend_tipInvisible() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false); when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false);
assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse(); assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
} }
@Test @Test
public void testDetect_notOverheatedIsExtraDefend_tipInvisible() { public void testDetect_notDefenderIsExtraDefend_tipInvisible() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true); when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true);
assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse(); assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
} }
@Test @Test
public void testDetect_isOverheatedIsExtraDefend_tipInvisible() { public void testDetect_isDefenderIsExtraDefend_tipInvisible() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true); when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(true);
assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse(); assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse();
} }
@Test @Test
public void testDetect_isOverheatedNotExtraDefend_tipNew() { public void testDetect_isDefenderNotExtraDefend_tipNew() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false); when(mFakeFeatureFactory.powerUsageFeatureProvider.isExtraDefend()).thenReturn(false);
assertThat(mBatteryDefenderDetector.detect().getState()) assertThat(mBatteryDefenderDetector.detect().getState())

View File

@@ -83,7 +83,7 @@ public class DockDefenderDetectorTest {
@Test @Test
public void testDetect_dockDefenderActive() { public void testDetect_dockDefenderActive() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
doReturn(true).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(true).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
BatteryTip batteryTip = mDockDefenderDetector.detect(); BatteryTip batteryTip = mDockDefenderDetector.detect();
@@ -95,7 +95,7 @@ public class DockDefenderDetectorTest {
@Test @Test
public void testDetect_dockDefenderFutureBypass() { public void testDetect_dockDefenderFutureBypass() {
mBatteryInfo.isOverheated = false; mBatteryInfo.isBatteryDefender = false;
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
BatteryTip batteryTip = mDockDefenderDetector.detect(); BatteryTip batteryTip = mDockDefenderDetector.detect();
@@ -107,7 +107,7 @@ public class DockDefenderDetectorTest {
@Test @Test
public void testDetect_overheatedTrue_dockDefenderDisabled() { public void testDetect_overheatedTrue_dockDefenderDisabled() {
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
BatteryTip batteryTip = mDockDefenderDetector.detect(); BatteryTip batteryTip = mDockDefenderDetector.detect();
@@ -131,7 +131,7 @@ public class DockDefenderDetectorTest {
@Test @Test
public void testDetect_overheatedTrueAndDockDefenderNotTriggered_dockDefenderDisabled() { public void testDetect_overheatedTrueAndDockDefenderNotTriggered_dockDefenderDisabled() {
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
mBatteryInfo.isOverheated = true; mBatteryInfo.isBatteryDefender = true;
BatteryTip batteryTip = mDockDefenderDetector.detect(); BatteryTip batteryTip = mDockDefenderDetector.detect();

View File

@@ -39,6 +39,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.safetycenter.SafetyCenterManagerWrapper; import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@@ -152,6 +153,7 @@ public class FaceUpdaterTest {
verify(mSafetyCenterManagerWrapper, never()).isEnabled(any()); verify(mSafetyCenterManagerWrapper, never()).isEnabled(any());
} }
@Ignore("b/282413778")
@Test @Test
public void enroll_secondVersion_onEnrollmentCallbacks_triggerGivenCallback() { public void enroll_secondVersion_onEnrollmentCallbacks_triggerGivenCallback() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor = ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -180,6 +182,7 @@ public class FaceUpdaterTest {
.onEnrollmentFrame(HELP_CODE, HELP_MESSAGE, CELL, STAGE, PAN, TILT, DISTANCE); .onEnrollmentFrame(HELP_CODE, HELP_MESSAGE, CELL, STAGE, PAN, TILT, DISTANCE);
} }
@Ignore("b/282413778")
@Test @Test
public void enroll_secondVersion_onEnrollmentSuccess_invokedInteractionWithSafetyCenter() { public void enroll_secondVersion_onEnrollmentSuccess_invokedInteractionWithSafetyCenter() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor = ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -201,6 +204,7 @@ public class FaceUpdaterTest {
verify(mSafetyCenterManagerWrapper).isEnabled(mContext); verify(mSafetyCenterManagerWrapper).isEnabled(mContext);
} }
@Ignore("b/282413778")
@Test @Test
public void enroll_secondVersion_onEnrollmentNotYetFinished_didntInvokeInteractionWithSafetyCenter() { public void enroll_secondVersion_onEnrollmentNotYetFinished_didntInvokeInteractionWithSafetyCenter() {
ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor = ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =

View File

@@ -22,6 +22,7 @@ import android.content.Context;
import android.os.LocaleList; import android.os.LocaleList;
import android.provider.Settings; import android.provider.Settings;
import androidx.core.text.util.LocalePreferences;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.internal.app.LocalePicker; import com.android.internal.app.LocalePicker;