From cad41681d60fe239abb6de33e4037d2afb6933f4 Mon Sep 17 00:00:00 2001 From: ykhung Date: Tue, 16 May 2023 08:36:00 +0800 Subject: [PATCH] Add device build information in the backup stage Insert the device build information in the battery optimization mode backup stage, such that we can use it to decide whether we should restore the data in the targeted device or not Bug: 192523697 Test: make test RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.* Change-Id: I3ab76e013ea9aca4d336a62e0c7cb6882c5b5085 --- .../fuelgauge/BatteryBackupHelper.java | 29 +++++++++++- .../fuelgauge/PowerUsageFeatureProvider.java | 10 +++++ .../PowerUsageFeatureProviderImpl.java | 10 +++++ .../fuelgauge/BatteryBackupHelperTest.java | 45 ++++++++++++++----- 4 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java index eb4bbf687d7..5d4f2664050 100644 --- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java +++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.os.Build; import android.os.IDeviceIdleController; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -36,6 +37,7 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.fuelgauge.PowerAllowlistBackend; import java.io.IOException; @@ -56,6 +58,13 @@ public final class BatteryBackupHelper implements BackupHelper { 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; @@ -83,9 +92,21 @@ public final class BatteryBackupHelper implements BackupHelper { return; } final List allowlistedApps = getFullPowerList(); - if (allowlistedApps != null) { - backupOptimizationMode(data, allowlistedApps); + if (allowlistedApps == null) { + 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. + 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 @@ -301,6 +322,9 @@ public final class BatteryBackupHelper implements BackupHelper { private static void writeBackupData( BackupDataOutput data, String dataKey, String dataContent) { + if (dataContent == null || dataContent.isEmpty()) { + return; + } final byte[] dataContentBytes = dataContent.getBytes(); try { data.writeEntityHeader(dataKey, dataContentBytes.length); @@ -308,5 +332,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)); } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 9f30473e209..724ca04d7ae 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -166,4 +166,14 @@ public interface PowerUsageFeatureProvider { * Returns {@link Set} for ignoring task root class names for screen on time */ Set 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); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index d65c2126658..f73a4d5a256 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -188,4 +188,14 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider public Set getIgnoreScreenOnTimeTaskRootSet() { return new ArraySet<>(); } + + @Override + public String getBuildMetadata1(Context context) { + return null; + } + + @Override + public String getBuildMetadata2(Context context) { + return null; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java index a800fdbd2cc..49354c1c5b5 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java @@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; @@ -45,6 +46,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; +import android.os.Build; import android.os.IDeviceIdleController; import android.os.RemoteException; import android.os.UserHandle; @@ -53,6 +55,7 @@ import android.util.ArraySet; import com.android.settings.TestUtils; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; +import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.fuelgauge.PowerAllowlistBackend; import org.junit.After; @@ -89,6 +92,7 @@ public final class BatteryBackupHelperTest { private PrintWriter mPrintWriter; private StringWriter mStringWriter; private BatteryBackupHelper mBatteryBackupHelper; + private PowerUsageFeatureProvider mPowerUsageFeatureProvider; @Mock private PackageManager mPackageManager; @@ -112,6 +116,8 @@ public final class BatteryBackupHelperTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mPowerUsageFeatureProvider = + FakeFeatureFactory.setupForTest().powerUsageFeatureProvider; mContext = spy(RuntimeEnvironment.application); mStringWriter = new StringWriter(); mPrintWriter = new PrintWriter(mStringWriter); @@ -136,19 +142,11 @@ public final class BatteryBackupHelperTest { } @Test - public void performBackup_nullPowerList_notBackupPowerList() 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 { + public void performBackup_emptyPowerList_backupPowerList() throws Exception { doReturn(new String[0]).when(mDeviceController).getFullPowerWhitelist(); mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null); - verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt()); + verify(mBackupDataOutput, atLeastOnce()).writeEntityHeader(anyString(), anyInt()); } @Test @@ -330,6 +328,26 @@ public final class BatteryBackupHelperTest { .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 { doReturn(uid).when(mPackageManager) .getPackageUid(packageName, PackageManager.GET_META_DATA); @@ -401,6 +419,13 @@ public final class BatteryBackupHelperTest { 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) public static class ShadowUserHandle { // Sets the default as thte OWNER role.