Snap for 10146593 from 384337cf12 to udc-qpr1-release
Change-Id: I0d6d773825b633e40581e5e6e6c76f9c1eba9e7c
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
14
TEST_MAPPING
14
TEST_MAPPING
@@ -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": [
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"/>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ public class BiometricFragment extends InstrumentedFragment {
|
|||||||
.setDisallowBiometricsIfPolicyExists(
|
.setDisallowBiometricsIfPolicyExists(
|
||||||
promptInfo.isDisallowBiometricsIfPolicyExists())
|
promptInfo.isDisallowBiometricsIfPolicyExists())
|
||||||
.setReceiveSystemEvents(true)
|
.setReceiveSystemEvents(true)
|
||||||
|
.setAllowBackgroundAuthentication(true)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user