diff --git a/Android.bp b/Android.bp index a9c3ea0f07b..b716117b096 100644 --- a/Android.bp +++ b/Android.bp @@ -90,6 +90,7 @@ android_library { "MediaDrmSettingsFlagsLib", "Settings-change-ids", "SettingsLib", + "SettingsLibDataStore", "SettingsLibActivityEmbedding", "aconfig_settings_flags_lib", "accessibility_settings_flags_lib", diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java index 528576de6b7..1a53b835f46 100644 --- a/src/com/android/settings/SettingsApplication.java +++ b/src/com/android/settings/SettingsApplication.java @@ -28,11 +28,13 @@ import androidx.annotation.NonNull; import com.android.settings.activityembedding.ActivityEmbeddingRulesController; import com.android.settings.activityembedding.ActivityEmbeddingUtils; import com.android.settings.core.instrumentation.ElapsedTimeUtils; +import com.android.settings.fuelgauge.BatterySettingsStorage; import com.android.settings.homepage.SettingsHomepageActivity; import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactoryImpl; import com.android.settings.spa.SettingsSpaEnvironment; import com.android.settingslib.applications.AppIconCacheManager; +import com.android.settingslib.datastore.BackupRestoreStorageManager; import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -54,6 +56,8 @@ public class SettingsApplication extends Application { public void onCreate() { super.onCreate(); + BackupRestoreStorageManager.getInstance(this).add(new BatterySettingsStorage(this)); + // Add null checking to avoid test case failed. if (getApplicationContext() != null) { ElapsedTimeUtils.assignSuwFinishedTimeStamp(getApplicationContext()); @@ -73,6 +77,12 @@ public class SettingsApplication extends Application { } } + @Override + public void onTerminate() { + BackupRestoreStorageManager.getInstance(this).removeAll(); + super.onTerminate(); + } + @NonNull protected FeatureFactory getFeatureFactory() { return new FeatureFactoryImpl(); diff --git a/src/com/android/settings/backup/SettingsBackupHelper.java b/src/com/android/settings/backup/SettingsBackupHelper.java index ecf4c71739d..0861af29d6c 100644 --- a/src/com/android/settings/backup/SettingsBackupHelper.java +++ b/src/com/android/settings/backup/SettingsBackupHelper.java @@ -22,10 +22,10 @@ import android.app.backup.BackupAgentHelper; import android.app.backup.SharedPreferencesBackupHelper; import com.android.settings.flags.Flags; -import com.android.settings.fuelgauge.BatteryBackupHelper; import com.android.settings.onboarding.OnboardingFeatureProvider; import com.android.settings.overlay.FeatureFactory; import com.android.settings.shortcut.CreateShortcutPreferenceController; +import com.android.settingslib.datastore.BackupRestoreStorageManager; /** Backup agent for Settings APK */ public class SettingsBackupHelper extends BackupAgentHelper { @@ -35,7 +35,7 @@ public class SettingsBackupHelper extends BackupAgentHelper { @Override public void onCreate() { super.onCreate(); - addHelper(BatteryBackupHelper.TAG, new BatteryBackupHelper(this)); + BackupRestoreStorageManager.getInstance(this).addBackupAgentHelpers(this); addHelper(PREF_LOCALE_NOTIFICATION, new SharedPreferencesBackupHelper(this, LOCALE_NOTIFICATION)); if (Flags.enableSoundBackup()) { @@ -51,6 +51,7 @@ public class SettingsBackupHelper extends BackupAgentHelper { @Override public void onRestoreFinished() { super.onRestoreFinished(); + BackupRestoreStorageManager.getInstance(this).onRestoreFinished(); CreateShortcutPreferenceController.updateRestoredShortcuts(this); } } diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index 6b04d3ce4f4..6ef5aa82a49 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -20,7 +20,6 @@ import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.isUserCon import android.app.Activity; import android.app.ActivityManager; -import android.app.backup.BackupManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; @@ -53,6 +52,7 @@ import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.instrumentation.Instrumentable; +import com.android.settingslib.datastore.ChangeReason; import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; @@ -105,7 +105,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment @VisibleForTesting @BatteryOptimizeUtils.OptimizationMode int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN; - @VisibleForTesting BackupManager mBackupManager; @VisibleForTesting StringBuilder mLogStringBuilder; // A wrapper class to carry LaunchBatteryDetailPage required arguments. @@ -293,9 +292,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment @VisibleForTesting void notifyBackupManager() { if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) { - final BackupManager backupManager = - mBackupManager != null ? mBackupManager : new BackupManager(getContext()); - backupManager.dataChanged(); + BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE); } } diff --git a/src/com/android/settings/fuelgauge/BatterySettingsStorage.java b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java new file mode 100644 index 00000000000..ff3223fce73 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatterySettingsStorage.java @@ -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 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 createBackupRestoreEntities() { + List 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 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 mAllowlistedApps; + + private OptimizationModeEntity(List 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 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 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(); + } + } +} diff --git a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java index 206745647c6..56702cf5c2a 100644 --- a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java +++ b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java @@ -19,7 +19,6 @@ package com.android.settings.fuelgauge; import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; import android.app.Activity; -import android.app.backup.BackupManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; @@ -42,6 +41,7 @@ import com.android.settingslib.HelpUtils; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.datastore.ChangeReason; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.widget.MainSwitchPreference; @@ -78,7 +78,6 @@ public class PowerBackgroundUsageDetail extends DashboardFragment @VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference; @VisibleForTesting MainSwitchPreference mMainSwitchPreference; @VisibleForTesting FooterPreference mFooterPreference; - @VisibleForTesting BackupManager mBackupManager; @VisibleForTesting StringBuilder mLogStringBuilder; @VisibleForTesting @BatteryOptimizeUtils.OptimizationMode @@ -187,9 +186,7 @@ public class PowerBackgroundUsageDetail extends DashboardFragment @VisibleForTesting void notifyBackupManager() { if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) { - final BackupManager backupManager = - mBackupManager != null ? mBackupManager : new BackupManager(getContext()); - backupManager.dataChanged(); + BatterySettingsStorage.get(getContext()).notifyChange(ChangeReason.UPDATE); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index 583db5e1d50..0648de4ad69 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -33,7 +33,6 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.app.AppOpsManager; -import android.app.backup.BackupManager; import android.app.settings.SettingsEnums; import android.content.Context; 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.instantapps.InstantAppDataProvider; 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.google.common.util.concurrent.MoreExecutors; + import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -116,9 +119,10 @@ public class AdvancedPowerUsageDetailTest { @Mock private AppOpsManager mAppOpsManager; @Mock private LoaderManager mLoaderManager; @Mock private BatteryOptimizeUtils mBatteryOptimizeUtils; - @Mock private BackupManager mBackupManager; + @Mock private Observer mObserver; private Context mContext; + private BatterySettingsStorage mBatterySettingsStorage; private PrimarySwitchPreference mAllowBackgroundUsagePreference; private AdvancedPowerUsageDetail mFragment; private SettingsActivity mTestActivity; @@ -130,6 +134,7 @@ public class AdvancedPowerUsageDetailTest { @Before public void setUp() { mContext = spy(ApplicationProvider.getApplicationContext()); + mBatterySettingsStorage = BatterySettingsStorage.get(mContext); when(mContext.getPackageName()).thenReturn("foo"); mFeatureFactory = FakeFeatureFactory.setupForTest(); mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider; @@ -200,7 +205,6 @@ public class AdvancedPowerUsageDetailTest { mFragment.mHeaderPreference = mHeaderPreference; mFragment.mState = mState; mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils; - mFragment.mBackupManager = mBackupManager; mFragment.mLogStringBuilder = new StringBuilder(); mAppEntry.info = mock(ApplicationInfo.class); @@ -447,23 +451,25 @@ public class AdvancedPowerUsageDetailTest { @Test public void notifyBackupManager_optimizationModeIsNotChanged_notInvokeDataChanged() { + mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor()); final int mode = BatteryOptimizeUtils.MODE_RESTRICTED; mFragment.mOptimizationMode = mode; when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); mFragment.notifyBackupManager(); - verifyNoInteractions(mBackupManager); + verifyNoInteractions(mObserver); } @Test public void notifyBackupManager_optimizationModeIsChanged_invokeDataChanged() { + mBatterySettingsStorage.addObserver(mObserver, MoreExecutors.directExecutor()); mFragment.mOptimizationMode = BatteryOptimizeUtils.MODE_RESTRICTED; when(mBatteryOptimizeUtils.getAppOptimizationMode()) .thenReturn(BatteryOptimizeUtils.MODE_UNRESTRICTED); mFragment.notifyBackupManager(); - verify(mBackupManager).dataChanged(); + verify(mObserver).onChanged(ChangeReason.UPDATE); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java index b6caa7f2061..90611178fdb 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java @@ -33,7 +33,6 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.app.AppOpsManager; -import android.app.backup.BackupManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; @@ -119,7 +118,6 @@ public class PowerBackgroundUsageDetailTest { @Mock private LoaderManager mLoaderManager; @Mock private ApplicationsState.AppEntry mAppEntry; @Mock private BatteryEntry mBatteryEntry; - @Mock private BackupManager mBackupManager; @Mock private PackageManager mPackageManager; @Mock private AppOpsManager mAppOpsManager; @Mock private CompoundButton mMockSwitch; @@ -174,7 +172,6 @@ public class PowerBackgroundUsageDetailTest { mFragment.mHeaderPreference = mHeaderPreference; mFragment.mState = mState; mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils; - mFragment.mBackupManager = mBackupManager; mAppEntry.info = mock(ApplicationInfo.class); mTestActivity = spy(new SettingsActivity());