diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java index 5d4f2664050..66ffc90c877 100644 --- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java +++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java @@ -31,6 +31,7 @@ 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; @@ -51,20 +52,23 @@ import java.util.List; public final class BatteryBackupHelper implements BackupHelper { /** An inditifier for {@link BackupHelper}. */ public static final String TAG = "BatteryBackupHelper"; + // Definition for the device build information. + public static final String KEY_BUILD_BRAND = "device_build_brand"; + public static final String KEY_BUILD_PRODUCT = "device_build_product"; + public static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture"; + public static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint"; + // Customized fields for device extra information. + public static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1"; + public static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2"; + private static final String DEVICE_IDLE_SERVICE = "deviceidle"; private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME = "battery_optimize_backup_historical_logs"; + private static final int DEVICE_BUILD_INFO_SIZE = 6; static final String DELIMITER = ","; static final String DELIMITER_MODE = ":"; static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list"; - static final String KEY_BUILD_BRAND = "device_build_brand"; - static final String KEY_BUILD_PRODUCT = "device_build_product"; - static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture"; - static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint"; - // Customized fields for device extra information. - static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1"; - static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2"; @VisibleForTesting ArraySet mTestApplicationInfoList = null; @@ -78,7 +82,13 @@ public final class BatteryBackupHelper implements BackupHelper { @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils; + private byte[] mOptimizationModeBytes; + private boolean mVerifyMigrateConfiguration = false; + private final Context mContext; + // Device information map from the restoreEntity() method. + private final ArrayMap mDeviceBuildInfoMap = + new ArrayMap<>(DEVICE_BUILD_INFO_SIZE); public BatteryBackupHelper(Context context) { mContext = context.getApplicationContext(); @@ -101,7 +111,7 @@ public final class BatteryBackupHelper implements BackupHelper { writeBackupData(data, KEY_BUILD_MANUFACTURER, Build.MANUFACTURER); writeBackupData(data, KEY_BUILD_FINGERPRINT, Build.FINGERPRINT); // Add customized device build metadata fields. - PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext) + 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)); @@ -111,26 +121,31 @@ public final class BatteryBackupHelper implements BackupHelper { @Override public void restoreEntity(BackupDataInputStream data) { - BatterySettingsMigrateChecker.verifySaverConfiguration(mContext); + // Ensure we only verify the migrate configuration one time. + if (!mVerifyMigrateConfiguration) { + mVerifyMigrateConfiguration = true; + BatterySettingsMigrateChecker.verifySaverConfiguration(mContext); + } if (!isOwner() || data == null || data.size() == 0) { Log.w(TAG, "ignore restoreEntity() for non-owner or empty data"); return; } - - if (KEY_OPTIMIZATION_LIST.equals(data.getKey())) { - final int dataSize = data.size(); - final byte[] dataBytes = new byte[dataSize]; - try { - data.read(dataBytes, 0 /*offset*/, dataSize); - } catch (IOException e) { - Log.e(TAG, "failed to load BackupDataInputStream", e); - return; - } - final int restoreCount = restoreOptimizationMode(dataBytes); - if (restoreCount > 0) { - BatterySettingsMigrateChecker.verifyOptimizationModes(mContext); - } + final String dataKey = data.getKey(); + switch (dataKey) { + case KEY_BUILD_BRAND: + case KEY_BUILD_PRODUCT: + case KEY_BUILD_MANUFACTURER: + case KEY_BUILD_FINGERPRINT: + case KEY_BUILD_METADATA_1: + case KEY_BUILD_METADATA_2: + restoreBackupData(dataKey, data); + break; + case KEY_OPTIMIZATION_LIST: + // Hold the optimization mode data until all conditions are matched. + mOptimizationModeBytes = getBackupData(dataKey, data); + break; } + performRestoreIfNeeded(); } @Override @@ -241,6 +256,23 @@ public final class BatteryBackupHelper implements BackupHelper { return restoreCount; } + private void performRestoreIfNeeded() { + if (mOptimizationModeBytes == null || mOptimizationModeBytes.length == 0) { + return; + } + final PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext) + .getPowerUsageFeatureProvider(mContext); + if (!provider.isValidToRestoreOptimizationMode(mDeviceBuildInfoMap)) { + return; + } + // Start to restore the app optimization mode data. + final int restoreCount = restoreOptimizationMode(mOptimizationModeBytes); + if (restoreCount > 0) { + BatterySettingsMigrateChecker.verifyOptimizationModes(mContext); + } + mOptimizationModeBytes = null; // clear data + } + /** Dump the app optimization mode backup history data. */ public static void dumpHistoricalData(Context context, PrintWriter writer) { BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog( @@ -320,6 +352,28 @@ public final class BatteryBackupHelper implements BackupHelper { return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager()); } + private void restoreBackupData(String dataKey, BackupDataInputStream data) { + final byte[] dataBytes = getBackupData(dataKey, data); + if (dataBytes == null || dataBytes.length == 0) { + return; + } + final String dataContent = new String(dataBytes, StandardCharsets.UTF_8); + mDeviceBuildInfoMap.put(dataKey, dataContent); + Log.d(TAG, String.format("restore:%s:%s", dataKey, dataContent)); + } + + private static byte[] getBackupData(String dataKey, BackupDataInputStream data) { + final int dataSize = data.size(); + final byte[] dataBytes = new byte[dataSize]; + try { + data.read(dataBytes, 0 /*offset*/, dataSize); + } catch (IOException e) { + Log.e(TAG, "failed to getBackupData() " + dataKey, e); + return null; + } + return dataBytes; + } + private static void writeBackupData( BackupDataOutput data, String dataKey, String dataContent) { if (dataContent == null || dataContent.isEmpty()) { @@ -332,6 +386,6 @@ public final class BatteryBackupHelper implements BackupHelper { } catch (IOException e) { Log.e(TAG, "writeBackupData() is failed for " + dataKey, e); } - Log.d(TAG, String.format("%s:%s", dataKey, dataContent)); + Log.d(TAG, String.format("backup:%s:%s", dataKey, dataContent)); } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 724ca04d7ae..0b0e2430c90 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -18,6 +18,7 @@ package com.android.settings.fuelgauge; import android.content.Context; import android.content.Intent; +import android.util.ArrayMap; import android.util.SparseIntArray; import com.android.settingslib.fuelgauge.Estimate; @@ -176,4 +177,9 @@ public interface PowerUsageFeatureProvider { * 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 deviceInfoMap); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index f73a4d5a256..1d0ba18b40f 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Process; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseIntArray; @@ -198,4 +199,9 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider public String getBuildMetadata2(Context context) { return null; } + + @Override + public boolean isValidToRestoreOptimizationMode(ArrayMap deviceInfoMap) { + return false; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java index 49354c1c5b5..b8c72eeef14 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java @@ -283,6 +283,20 @@ public final class BatteryBackupHelperTest { 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 public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception { mBatteryBackupHelper.restoreOptimizationMode(new byte[0]);