[DataStore] Migrate BatteryBackupHelper to BackupRestoreStorage
Bug: 325144964 Test: Manual tests Change-Id: I19f7c78969d70648d1e45f1627827d98b1fdd1e0
This commit is contained in:
@@ -90,6 +90,7 @@ android_library {
|
|||||||
"MediaDrmSettingsFlagsLib",
|
"MediaDrmSettingsFlagsLib",
|
||||||
"Settings-change-ids",
|
"Settings-change-ids",
|
||||||
"SettingsLib",
|
"SettingsLib",
|
||||||
|
"SettingsLibDataStore",
|
||||||
"SettingsLibActivityEmbedding",
|
"SettingsLibActivityEmbedding",
|
||||||
"aconfig_settings_flags_lib",
|
"aconfig_settings_flags_lib",
|
||||||
"accessibility_settings_flags_lib",
|
"accessibility_settings_flags_lib",
|
||||||
|
@@ -28,11 +28,13 @@ import androidx.annotation.NonNull;
|
|||||||
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
||||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||||
import com.android.settings.core.instrumentation.ElapsedTimeUtils;
|
import com.android.settings.core.instrumentation.ElapsedTimeUtils;
|
||||||
|
import com.android.settings.fuelgauge.BatterySettingsStorage;
|
||||||
import com.android.settings.homepage.SettingsHomepageActivity;
|
import com.android.settings.homepage.SettingsHomepageActivity;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.overlay.FeatureFactoryImpl;
|
import com.android.settings.overlay.FeatureFactoryImpl;
|
||||||
import com.android.settings.spa.SettingsSpaEnvironment;
|
import com.android.settings.spa.SettingsSpaEnvironment;
|
||||||
import com.android.settingslib.applications.AppIconCacheManager;
|
import com.android.settingslib.applications.AppIconCacheManager;
|
||||||
|
import com.android.settingslib.datastore.BackupRestoreStorageManager;
|
||||||
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory;
|
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory;
|
||||||
|
|
||||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||||
@@ -54,6 +56,8 @@ public class SettingsApplication extends Application {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
|
BackupRestoreStorageManager.getInstance(this).add(new BatterySettingsStorage(this));
|
||||||
|
|
||||||
// Add null checking to avoid test case failed.
|
// Add null checking to avoid test case failed.
|
||||||
if (getApplicationContext() != null) {
|
if (getApplicationContext() != null) {
|
||||||
ElapsedTimeUtils.assignSuwFinishedTimeStamp(getApplicationContext());
|
ElapsedTimeUtils.assignSuwFinishedTimeStamp(getApplicationContext());
|
||||||
@@ -73,6 +77,12 @@ public class SettingsApplication extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTerminate() {
|
||||||
|
BackupRestoreStorageManager.getInstance(this).removeAll();
|
||||||
|
super.onTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
protected FeatureFactory getFeatureFactory() {
|
protected FeatureFactory getFeatureFactory() {
|
||||||
return new FeatureFactoryImpl();
|
return new FeatureFactoryImpl();
|
||||||
|
@@ -22,10 +22,10 @@ import android.app.backup.BackupAgentHelper;
|
|||||||
import android.app.backup.SharedPreferencesBackupHelper;
|
import android.app.backup.SharedPreferencesBackupHelper;
|
||||||
|
|
||||||
import com.android.settings.flags.Flags;
|
import com.android.settings.flags.Flags;
|
||||||
import com.android.settings.fuelgauge.BatteryBackupHelper;
|
|
||||||
import com.android.settings.onboarding.OnboardingFeatureProvider;
|
import com.android.settings.onboarding.OnboardingFeatureProvider;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.shortcut.CreateShortcutPreferenceController;
|
import com.android.settings.shortcut.CreateShortcutPreferenceController;
|
||||||
|
import com.android.settingslib.datastore.BackupRestoreStorageManager;
|
||||||
|
|
||||||
/** Backup agent for Settings APK */
|
/** Backup agent for Settings APK */
|
||||||
public class SettingsBackupHelper extends BackupAgentHelper {
|
public class SettingsBackupHelper extends BackupAgentHelper {
|
||||||
@@ -35,7 +35,7 @@ public class SettingsBackupHelper extends BackupAgentHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
addHelper(BatteryBackupHelper.TAG, new BatteryBackupHelper(this));
|
BackupRestoreStorageManager.getInstance(this).addBackupAgentHelpers(this);
|
||||||
addHelper(PREF_LOCALE_NOTIFICATION,
|
addHelper(PREF_LOCALE_NOTIFICATION,
|
||||||
new SharedPreferencesBackupHelper(this, LOCALE_NOTIFICATION));
|
new SharedPreferencesBackupHelper(this, LOCALE_NOTIFICATION));
|
||||||
if (Flags.enableSoundBackup()) {
|
if (Flags.enableSoundBackup()) {
|
||||||
@@ -51,6 +51,7 @@ public class SettingsBackupHelper extends BackupAgentHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void onRestoreFinished() {
|
public void onRestoreFinished() {
|
||||||
super.onRestoreFinished();
|
super.onRestoreFinished();
|
||||||
|
BackupRestoreStorageManager.getInstance(this).onRestoreFinished();
|
||||||
CreateShortcutPreferenceController.updateRestoredShortcuts(this);
|
CreateShortcutPreferenceController.updateRestoredShortcuts(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@ import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isUserCon
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -53,6 +52,7 @@ import com.android.settingslib.applications.AppUtils;
|
|||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||||
|
import com.android.settingslib.datastore.ChangeReason;
|
||||||
import com.android.settingslib.widget.LayoutPreference;
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -105,7 +105,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
|||||||
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
||||||
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
|
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
|
||||||
|
|
||||||
@VisibleForTesting BackupManager mBackupManager;
|
|
||||||
@VisibleForTesting StringBuilder mLogStringBuilder;
|
@VisibleForTesting StringBuilder mLogStringBuilder;
|
||||||
|
|
||||||
// A wrapper class to carry LaunchBatteryDetailPage required arguments.
|
// A wrapper class to carry LaunchBatteryDetailPage required arguments.
|
||||||
@@ -293,9 +292,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void notifyBackupManager() {
|
void notifyBackupManager() {
|
||||||
if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
|
if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
|
||||||
final BackupManager backupManager =
|
BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE);
|
||||||
mBackupManager != null ? mBackupManager : new BackupManager(getContext());
|
|
||||||
backupManager.dataChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
370
src/com/android/settings/fuelgauge/BatterySettingsStorage.java
Normal file
370
src/com/android/settings/fuelgauge/BatterySettingsStorage.java
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fuelgauge;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import android.app.AppGlobals;
|
||||||
|
import android.app.AppOpsManager;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.IDeviceIdleController;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settingslib.datastore.BackupContext;
|
||||||
|
import com.android.settingslib.datastore.BackupRestoreEntity;
|
||||||
|
import com.android.settingslib.datastore.BackupRestoreStorageManager;
|
||||||
|
import com.android.settingslib.datastore.EntityBackupResult;
|
||||||
|
import com.android.settingslib.datastore.ObservableBackupRestoreStorage;
|
||||||
|
import com.android.settingslib.datastore.RestoreContext;
|
||||||
|
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** An implementation to backup and restore battery configurations. */
|
||||||
|
public final class BatterySettingsStorage extends ObservableBackupRestoreStorage {
|
||||||
|
public static final String TAG = "BatteryBackupHelper";
|
||||||
|
|
||||||
|
// Definition for the device build information.
|
||||||
|
public static final String KEY_BUILD_BRAND = "device_build_brand";
|
||||||
|
public static final String KEY_BUILD_PRODUCT = "device_build_product";
|
||||||
|
public static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture";
|
||||||
|
public static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint";
|
||||||
|
// Customized fields for device extra information.
|
||||||
|
public static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1";
|
||||||
|
public static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2";
|
||||||
|
|
||||||
|
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
||||||
|
private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME =
|
||||||
|
"battery_optimize_backup_historical_logs";
|
||||||
|
private static final int DEVICE_BUILD_INFO_SIZE = 6;
|
||||||
|
|
||||||
|
static final String DELIMITER = ",";
|
||||||
|
static final String DELIMITER_MODE = ":";
|
||||||
|
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
|
||||||
|
|
||||||
|
@Nullable private byte[] mOptimizationModeBytes;
|
||||||
|
|
||||||
|
private final Application mApplication;
|
||||||
|
// Device information map from restore.
|
||||||
|
private final ArrayMap<String, String> mDeviceBuildInfoMap =
|
||||||
|
new ArrayMap<>(DEVICE_BUILD_INFO_SIZE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link BatterySettingsStorage} registered to {@link BackupRestoreStorageManager}.
|
||||||
|
*/
|
||||||
|
public static @NonNull BatterySettingsStorage get(@NonNull Context context) {
|
||||||
|
return (BatterySettingsStorage)
|
||||||
|
BackupRestoreStorageManager.getInstance(context).getOrThrow(TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BatterySettingsStorage(@NonNull Context context) {
|
||||||
|
mApplication = (Application) context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enableBackup(@NonNull BackupContext backupContext) {
|
||||||
|
return isOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enableRestore() {
|
||||||
|
return isOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isOwner() {
|
||||||
|
return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<BackupRestoreEntity> createBackupRestoreEntities() {
|
||||||
|
List<String> allowlistedApps = getFullPowerList();
|
||||||
|
if (allowlistedApps == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
PowerUsageFeatureProvider provider =
|
||||||
|
FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
|
||||||
|
return Arrays.asList(
|
||||||
|
new StringEntity(KEY_BUILD_BRAND, Build.BRAND),
|
||||||
|
new StringEntity(KEY_BUILD_PRODUCT, Build.PRODUCT),
|
||||||
|
new StringEntity(KEY_BUILD_MANUFACTURER, Build.MANUFACTURER),
|
||||||
|
new StringEntity(KEY_BUILD_FINGERPRINT, Build.FINGERPRINT),
|
||||||
|
new StringEntity(KEY_BUILD_METADATA_1, provider.getBuildMetadata1(mApplication)),
|
||||||
|
new StringEntity(KEY_BUILD_METADATA_2, provider.getBuildMetadata2(mApplication)),
|
||||||
|
new OptimizationModeEntity(allowlistedApps));
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable List<String> getFullPowerList() {
|
||||||
|
final long timestamp = System.currentTimeMillis();
|
||||||
|
String[] allowlistedApps;
|
||||||
|
try {
|
||||||
|
IDeviceIdleController deviceIdleController =
|
||||||
|
IDeviceIdleController.Stub.asInterface(
|
||||||
|
ServiceManager.getService(DEVICE_IDLE_SERVICE));
|
||||||
|
allowlistedApps = deviceIdleController.getFullPowerWhitelist();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "backupFullPowerList() failed", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Ignores unexpected empty result case.
|
||||||
|
if (allowlistedApps == null || allowlistedApps.length == 0) {
|
||||||
|
Log.w(TAG, "no data found in the getFullPowerList()");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
String.format(
|
||||||
|
"getFullPowerList() size=%d in %d/ms",
|
||||||
|
allowlistedApps.length, (System.currentTimeMillis() - timestamp)));
|
||||||
|
return Arrays.asList(allowlistedApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeNewStateDescription(@NonNull ParcelFileDescriptor newState) {
|
||||||
|
BatterySettingsMigrateChecker.verifySaverConfiguration(mApplication);
|
||||||
|
performRestoreIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performRestoreIfNeeded() {
|
||||||
|
byte[] bytes = mOptimizationModeBytes;
|
||||||
|
mOptimizationModeBytes = null; // clear data
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final PowerUsageFeatureProvider provider =
|
||||||
|
FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
|
||||||
|
if (!provider.isValidToRestoreOptimizationMode(mDeviceBuildInfoMap)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Start to restore the app optimization mode data.
|
||||||
|
final int restoreCount = restoreOptimizationMode(bytes);
|
||||||
|
if (restoreCount > 0) {
|
||||||
|
BatterySettingsMigrateChecker.verifyBatteryOptimizeModes(mApplication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int restoreOptimizationMode(byte[] dataBytes) {
|
||||||
|
final long timestamp = System.currentTimeMillis();
|
||||||
|
final String dataContent = new String(dataBytes, UTF_8);
|
||||||
|
if (dataContent.isEmpty()) {
|
||||||
|
Log.w(TAG, "no data found in the restoreOptimizationMode()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
final String[] appConfigurations = dataContent.split(BatteryBackupHelper.DELIMITER);
|
||||||
|
if (appConfigurations.length == 0) {
|
||||||
|
Log.w(TAG, "no data found from the split() processing");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int restoreCount = 0;
|
||||||
|
for (String appConfiguration : appConfigurations) {
|
||||||
|
final String[] results = appConfiguration.split(BatteryBackupHelper.DELIMITER_MODE);
|
||||||
|
// Example format: com.android.systemui:2 we should have length=2
|
||||||
|
if (results.length != 2) {
|
||||||
|
Log.w(TAG, "invalid raw data found:" + appConfiguration);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String packageName = results[0];
|
||||||
|
final int uid = BatteryUtils.getInstance(mApplication).getPackageUid(packageName);
|
||||||
|
// Ignores system/default apps.
|
||||||
|
if (isSystemOrDefaultApp(packageName, uid)) {
|
||||||
|
Log.w(TAG, "ignore from isSystemOrDefaultApp():" + packageName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
@BatteryOptimizeUtils.OptimizationMode int optimizationMode;
|
||||||
|
try {
|
||||||
|
optimizationMode = Integer.parseInt(results[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Log.e(TAG, "failed to parse the optimization mode: " + appConfiguration, e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
restoreOptimizationMode(packageName, optimizationMode);
|
||||||
|
restoreCount++;
|
||||||
|
}
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
String.format(
|
||||||
|
"restoreOptimizationMode() count=%d in %d/ms",
|
||||||
|
restoreCount, (System.currentTimeMillis() - timestamp)));
|
||||||
|
return restoreCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreOptimizationMode(
|
||||||
|
String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) {
|
||||||
|
final BatteryOptimizeUtils batteryOptimizeUtils =
|
||||||
|
newBatteryOptimizeUtils(mApplication, packageName);
|
||||||
|
if (batteryOptimizeUtils == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
batteryOptimizeUtils.setAppUsageState(
|
||||||
|
mode, BatteryOptimizeHistoricalLogEntry.Action.RESTORE);
|
||||||
|
Log.d(TAG, String.format("restore:%s mode=%d", packageName, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static BatteryOptimizeUtils newBatteryOptimizeUtils(Context context, String packageName) {
|
||||||
|
final int uid = BatteryUtils.getInstance(context).getPackageUid(packageName);
|
||||||
|
return uid == BatteryUtils.UID_NULL
|
||||||
|
? null
|
||||||
|
: new BatteryOptimizeUtils(context, uid, packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSystemOrDefaultApp(String packageName, int uid) {
|
||||||
|
return BatteryOptimizeUtils.isSystemOrDefaultApp(
|
||||||
|
mApplication, PowerAllowlistBackend.getInstance(mApplication), packageName, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StringEntity implements BackupRestoreEntity {
|
||||||
|
private final String mKey;
|
||||||
|
private final String mValue;
|
||||||
|
|
||||||
|
StringEntity(String key, String value) {
|
||||||
|
this.mKey = key;
|
||||||
|
this.mValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return mKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull EntityBackupResult backup(
|
||||||
|
@NonNull BackupContext backupContext, @NonNull OutputStream outputStream)
|
||||||
|
throws IOException {
|
||||||
|
Log.d(TAG, String.format("backup:%s:%s", mKey, mValue));
|
||||||
|
outputStream.write(mValue.getBytes(UTF_8));
|
||||||
|
return EntityBackupResult.UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restore(
|
||||||
|
@NonNull RestoreContext restoreContext, @NonNull InputStream inputStream)
|
||||||
|
throws IOException {
|
||||||
|
String dataContent = new String(inputStream.readAllBytes(), UTF_8);
|
||||||
|
mDeviceBuildInfoMap.put(mKey, dataContent);
|
||||||
|
Log.d(TAG, String.format("restore:%s:%s", mKey, dataContent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OptimizationModeEntity implements BackupRestoreEntity {
|
||||||
|
private final List<String> mAllowlistedApps;
|
||||||
|
|
||||||
|
private OptimizationModeEntity(List<String> allowlistedApps) {
|
||||||
|
this.mAllowlistedApps = allowlistedApps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return KEY_OPTIMIZATION_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull EntityBackupResult backup(
|
||||||
|
@NonNull BackupContext backupContext, @NonNull OutputStream outputStream)
|
||||||
|
throws IOException {
|
||||||
|
final long timestamp = System.currentTimeMillis();
|
||||||
|
final ArraySet<ApplicationInfo> applications = getInstalledApplications();
|
||||||
|
if (applications == null || applications.isEmpty()) {
|
||||||
|
Log.w(TAG, "no data found in the getInstalledApplications()");
|
||||||
|
return EntityBackupResult.DELETE;
|
||||||
|
}
|
||||||
|
int backupCount = 0;
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
final AppOpsManager appOps = mApplication.getSystemService(AppOpsManager.class);
|
||||||
|
final SharedPreferences sharedPreferences = getSharedPreferences(mApplication);
|
||||||
|
// Converts application into the AppUsageState.
|
||||||
|
for (ApplicationInfo info : applications) {
|
||||||
|
final int mode = BatteryOptimizeUtils.getMode(appOps, info.uid, info.packageName);
|
||||||
|
@BatteryOptimizeUtils.OptimizationMode
|
||||||
|
final int optimizationMode =
|
||||||
|
BatteryOptimizeUtils.getAppOptimizationMode(
|
||||||
|
mode, mAllowlistedApps.contains(info.packageName));
|
||||||
|
// Ignores default optimized/unknown state or system/default apps.
|
||||||
|
if (optimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||||
|
|| optimizationMode == BatteryOptimizeUtils.MODE_UNKNOWN
|
||||||
|
|| isSystemOrDefaultApp(info.packageName, info.uid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String packageOptimizeMode =
|
||||||
|
info.packageName + DELIMITER_MODE + optimizationMode;
|
||||||
|
builder.append(packageOptimizeMode).append(DELIMITER);
|
||||||
|
Log.d(TAG, "backupOptimizationMode: " + packageOptimizeMode);
|
||||||
|
BatteryOptimizeLogUtils.writeLog(
|
||||||
|
sharedPreferences,
|
||||||
|
Action.BACKUP,
|
||||||
|
info.packageName,
|
||||||
|
/* actionDescription */ "mode: " + optimizationMode);
|
||||||
|
backupCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.write(builder.toString().getBytes(UTF_8));
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
String.format(
|
||||||
|
"backup getInstalledApplications():%d count=%d in %d/ms",
|
||||||
|
applications.size(),
|
||||||
|
backupCount,
|
||||||
|
(System.currentTimeMillis() - timestamp)));
|
||||||
|
return EntityBackupResult.UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable ArraySet<ApplicationInfo> getInstalledApplications() {
|
||||||
|
return BatteryOptimizeUtils.getInstalledApplications(
|
||||||
|
mApplication, AppGlobals.getPackageManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
static @NonNull SharedPreferences getSharedPreferences(Context context) {
|
||||||
|
return context.getSharedPreferences(
|
||||||
|
BATTERY_OPTIMIZE_BACKUP_FILE_NAME, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restore(
|
||||||
|
@NonNull RestoreContext restoreContext, @NonNull InputStream inputStream)
|
||||||
|
throws IOException {
|
||||||
|
mOptimizationModeBytes = inputStream.readAllBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,6 @@ package com.android.settings.fuelgauge;
|
|||||||
import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -42,6 +41,7 @@ import com.android.settingslib.HelpUtils;
|
|||||||
import com.android.settingslib.applications.AppUtils;
|
import com.android.settingslib.applications.AppUtils;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
|
import com.android.settingslib.datastore.ChangeReason;
|
||||||
import com.android.settingslib.widget.FooterPreference;
|
import com.android.settingslib.widget.FooterPreference;
|
||||||
import com.android.settingslib.widget.LayoutPreference;
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
import com.android.settingslib.widget.MainSwitchPreference;
|
import com.android.settingslib.widget.MainSwitchPreference;
|
||||||
@@ -78,7 +78,6 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
|||||||
@VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference;
|
@VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference;
|
||||||
@VisibleForTesting MainSwitchPreference mMainSwitchPreference;
|
@VisibleForTesting MainSwitchPreference mMainSwitchPreference;
|
||||||
@VisibleForTesting FooterPreference mFooterPreference;
|
@VisibleForTesting FooterPreference mFooterPreference;
|
||||||
@VisibleForTesting BackupManager mBackupManager;
|
|
||||||
@VisibleForTesting StringBuilder mLogStringBuilder;
|
@VisibleForTesting StringBuilder mLogStringBuilder;
|
||||||
|
|
||||||
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
||||||
@@ -187,9 +186,7 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void notifyBackupManager() {
|
void notifyBackupManager() {
|
||||||
if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
|
if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
|
||||||
final BackupManager backupManager =
|
BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE);
|
||||||
mBackupManager != null ? mBackupManager : new BackupManager(getContext());
|
|
||||||
backupManager.dataChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -61,8 +60,12 @@ import com.android.settingslib.applications.AppUtils;
|
|||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
|
import com.android.settingslib.datastore.ChangeReason;
|
||||||
|
import com.android.settingslib.datastore.Observer;
|
||||||
import com.android.settingslib.widget.LayoutPreference;
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -116,9 +119,10 @@ public class AdvancedPowerUsageDetailTest {
|
|||||||
@Mock private AppOpsManager mAppOpsManager;
|
@Mock private AppOpsManager mAppOpsManager;
|
||||||
@Mock private LoaderManager mLoaderManager;
|
@Mock private LoaderManager mLoaderManager;
|
||||||
@Mock private BatteryOptimizeUtils mBatteryOptimizeUtils;
|
@Mock private BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||||
@Mock private BackupManager mBackupManager;
|
@Mock private Observer mObserver;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private BatterySettingsStorage mBatterySettingsStorage;
|
||||||
private PrimarySwitchPreference mAllowBackgroundUsagePreference;
|
private PrimarySwitchPreference mAllowBackgroundUsagePreference;
|
||||||
private AdvancedPowerUsageDetail mFragment;
|
private AdvancedPowerUsageDetail mFragment;
|
||||||
private SettingsActivity mTestActivity;
|
private SettingsActivity mTestActivity;
|
||||||
@@ -130,6 +134,7 @@ public class AdvancedPowerUsageDetailTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
|
mBatterySettingsStorage = BatterySettingsStorage.get(mContext);
|
||||||
when(mContext.getPackageName()).thenReturn("foo");
|
when(mContext.getPackageName()).thenReturn("foo");
|
||||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
|
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
|
||||||
@@ -200,7 +205,6 @@ public class AdvancedPowerUsageDetailTest {
|
|||||||
mFragment.mHeaderPreference = mHeaderPreference;
|
mFragment.mHeaderPreference = mHeaderPreference;
|
||||||
mFragment.mState = mState;
|
mFragment.mState = mState;
|
||||||
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
|
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
|
||||||
mFragment.mBackupManager = mBackupManager;
|
|
||||||
mFragment.mLogStringBuilder = new StringBuilder();
|
mFragment.mLogStringBuilder = new StringBuilder();
|
||||||
mAppEntry.info = mock(ApplicationInfo.class);
|
mAppEntry.info = mock(ApplicationInfo.class);
|
||||||
|
|
||||||
@@ -447,23 +451,25 @@ public class AdvancedPowerUsageDetailTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged() {
|
public void notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged() {
|
||||||
|
mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor());
|
||||||
final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
|
final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||||
mFragment.mOptimizationMode = mode;
|
mFragment.mOptimizationMode = mode;
|
||||||
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
|
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
|
||||||
|
|
||||||
mFragment.notifyBackupManager();
|
mFragment.notifyBackupManager();
|
||||||
|
|
||||||
verifyNoInteractions(mBackupManager);
|
verifyNoInteractions(mObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void notifyBackupManager_optimizationModeIsChanged_invokeDataChanged() {
|
public void notifyBackupManager_optimizationModeIsChanged_invokeDataChanged() {
|
||||||
|
mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor());
|
||||||
mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED;
|
mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||||
when(mBatteryOptimizeUtils.getAppOptimizationMode())
|
when(mBatteryOptimizeUtils.getAppOptimizationMode())
|
||||||
.thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED);
|
.thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED);
|
||||||
|
|
||||||
mFragment.notifyBackupManager();
|
mFragment.notifyBackupManager();
|
||||||
|
|
||||||
verify(mBackupManager).dataChanged();
|
verify(mObserver).onChanged(ChangeReason.UPDATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -119,7 +118,6 @@ public class PowerBackgroundUsageDetailTest {
|
|||||||
@Mock private LoaderManager mLoaderManager;
|
@Mock private LoaderManager mLoaderManager;
|
||||||
@Mock private ApplicationsState.AppEntry mAppEntry;
|
@Mock private ApplicationsState.AppEntry mAppEntry;
|
||||||
@Mock private BatteryEntry mBatteryEntry;
|
@Mock private BatteryEntry mBatteryEntry;
|
||||||
@Mock private BackupManager mBackupManager;
|
|
||||||
@Mock private PackageManager mPackageManager;
|
@Mock private PackageManager mPackageManager;
|
||||||
@Mock private AppOpsManager mAppOpsManager;
|
@Mock private AppOpsManager mAppOpsManager;
|
||||||
@Mock private CompoundButton mMockSwitch;
|
@Mock private CompoundButton mMockSwitch;
|
||||||
@@ -174,7 +172,6 @@ public class PowerBackgroundUsageDetailTest {
|
|||||||
mFragment.mHeaderPreference = mHeaderPreference;
|
mFragment.mHeaderPreference = mHeaderPreference;
|
||||||
mFragment.mState = mState;
|
mFragment.mState = mState;
|
||||||
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
|
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
|
||||||
mFragment.mBackupManager = mBackupManager;
|
|
||||||
mAppEntry.info = mock(ApplicationInfo.class);
|
mAppEntry.info = mock(ApplicationInfo.class);
|
||||||
|
|
||||||
mTestActivity = spy(new SettingsActivity());
|
mTestActivity = spy(new SettingsActivity());
|
||||||
|
Reference in New Issue
Block a user