Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fff8a890 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Limit the optimization mode restore mechanism for specific conditions"...

Merge "Limit the optimization mode restore mechanism for specific conditions" into udc-dev am: b2de62c0

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/23241740



Change-Id: I11170a8000ddc56ac382a8c01df84f2113932b85
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 2427d3b5 b2de62c0
Loading
Loading
Loading
Loading
+78 −24
Original line number Diff line number Diff line
@@ -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<ApplicationInfo> 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<String, String> 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) {
        // 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));
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -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<String, String> deviceInfoMap);
}
+6 −0
Original line number Diff line number Diff line
@@ -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<String, String> deviceInfoMap) {
        return false;
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -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]);