Reset Optimization Mode of apps when users reset app settings.
Fix the issue that Optimization Mode is not reset when users click the "Reset apps" button in the setting. Bug: 222037028 Test: make RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.fuelgauge" + emulator Change-Id: I22fb8aa19e284e11882b2920b77b544dee4cc33c
This commit is contained in:
@@ -38,6 +38,7 @@ import android.util.Log;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -152,6 +153,7 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener,
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
mAom.resetAllModes();
|
mAom.resetAllModes();
|
||||||
|
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
|
||||||
final int[] restrictedUids = mNpm.getUidsWithPolicy(
|
final int[] restrictedUids = mNpm.getUidsWithPolicy(
|
||||||
POLICY_REJECT_METERED_BACKGROUND);
|
POLICY_REJECT_METERED_BACKGROUND);
|
||||||
final int currentUserId = ActivityManager.getCurrentUser();
|
final int currentUserId = ActivityManager.getCurrentUser();
|
||||||
|
@@ -24,16 +24,13 @@ import android.app.backup.BackupHelper;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageManager;
|
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.Build;
|
||||||
import android.os.IDeviceIdleController;
|
import android.os.IDeviceIdleController;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -53,22 +50,13 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
||||||
private static final boolean DEBUG = Build.TYPE.equals("userdebug");
|
private static final boolean DEBUG = Build.TYPE.equals("userdebug");
|
||||||
|
|
||||||
// Only the owner can see all apps.
|
|
||||||
private static final int RETRIEVE_FLAG_ADMIN =
|
|
||||||
PackageManager.MATCH_ANY_USER |
|
|
||||||
PackageManager.MATCH_DISABLED_COMPONENTS |
|
|
||||||
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
|
|
||||||
private static final int RETRIEVE_FLAG =
|
|
||||||
PackageManager.MATCH_DISABLED_COMPONENTS |
|
|
||||||
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
|
|
||||||
|
|
||||||
static final String DELIMITER = ",";
|
static final String DELIMITER = ",";
|
||||||
static final String DELIMITER_MODE = ":";
|
static final String DELIMITER_MODE = ":";
|
||||||
static final String KEY_FULL_POWER_LIST = "full_power_list";
|
static final String KEY_FULL_POWER_LIST = "full_power_list";
|
||||||
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
|
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<ApplicationInfo> mTestApplicationInfoList = null;
|
ArraySet<ApplicationInfo> mTestApplicationInfoList = null;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
PowerAllowlistBackend mPowerAllowlistBackend;
|
PowerAllowlistBackend mPowerAllowlistBackend;
|
||||||
@@ -146,7 +134,7 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void backupOptimizationMode(BackupDataOutput data, List<String> allowlistedApps) {
|
void backupOptimizationMode(BackupDataOutput data, List<String> allowlistedApps) {
|
||||||
final long timestamp = System.currentTimeMillis();
|
final long timestamp = System.currentTimeMillis();
|
||||||
final List<ApplicationInfo> applications = getInstalledApplications();
|
final ArraySet<ApplicationInfo> applications = getInstalledApplications();
|
||||||
if (applications == null || applications.isEmpty()) {
|
if (applications == null || applications.isEmpty()) {
|
||||||
Log.w(TAG, "no data found in the getInstalledApplications()");
|
Log.w(TAG, "no data found in the getInstalledApplications()");
|
||||||
return;
|
return;
|
||||||
@@ -269,36 +257,11 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
|
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ApplicationInfo> getInstalledApplications() {
|
private ArraySet<ApplicationInfo> getInstalledApplications() {
|
||||||
if (mTestApplicationInfoList != null) {
|
if (mTestApplicationInfoList != null) {
|
||||||
return mTestApplicationInfoList;
|
return mTestApplicationInfoList;
|
||||||
}
|
}
|
||||||
final List<ApplicationInfo> applications = new ArrayList<>();
|
return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager());
|
||||||
final UserManager um = mContext.getSystemService(UserManager.class);
|
|
||||||
for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
|
|
||||||
try {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final ParceledListSlice<ApplicationInfo> infoList =
|
|
||||||
getIPackageManager().getInstalledApplications(
|
|
||||||
userInfo.isAdmin() ? RETRIEVE_FLAG_ADMIN : RETRIEVE_FLAG,
|
|
||||||
userInfo.id);
|
|
||||||
if (infoList != null) {
|
|
||||||
applications.addAll(infoList.getList());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "getInstalledApplications() is failed", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Removes the application which is disabled by the system.
|
|
||||||
for (int index = applications.size() - 1; index >= 0; index--) {
|
|
||||||
final ApplicationInfo info = applications.get(index);
|
|
||||||
if (info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
|
|
||||||
&& !info.enabled) {
|
|
||||||
applications.remove(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return applications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void debugLog(String debugContent) {
|
private void debugLog(String debugContent) {
|
||||||
|
@@ -19,7 +19,15 @@ package com.android.settings.fuelgauge;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ParceledListSlice;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -43,6 +51,15 @@ public class BatteryOptimizeUtils {
|
|||||||
private final String mPackageName;
|
private final String mPackageName;
|
||||||
private final int mUid;
|
private final int mUid;
|
||||||
|
|
||||||
|
// If current user is admin, match apps from all users. Otherwise, only match the currect user.
|
||||||
|
private static final int RETRIEVE_FLAG_ADMIN =
|
||||||
|
PackageManager.MATCH_ANY_USER
|
||||||
|
| PackageManager.MATCH_DISABLED_COMPONENTS
|
||||||
|
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
|
||||||
|
private static final int RETRIEVE_FLAG =
|
||||||
|
PackageManager.MATCH_DISABLED_COMPONENTS
|
||||||
|
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
|
||||||
|
|
||||||
// Optimization modes.
|
// Optimization modes.
|
||||||
static final int MODE_UNKNOWN = 0;
|
static final int MODE_UNKNOWN = 0;
|
||||||
static final int MODE_RESTRICTED = 1;
|
static final int MODE_RESTRICTED = 1;
|
||||||
@@ -90,28 +107,20 @@ public class BatteryOptimizeUtils {
|
|||||||
return getAppOptimizationMode(mMode, mAllowListed);
|
return getAppOptimizationMode(mMode, mAllowListed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resets optimization mode for all applications. */
|
||||||
|
public static void resetAppOptimizationMode(
|
||||||
|
Context context, IPackageManager ipm, AppOpsManager aom) {
|
||||||
|
resetAppOptimizationMode(context, ipm, aom,
|
||||||
|
PowerAllowlistBackend.getInstance(context), BatteryUtils.getInstance(context));
|
||||||
|
}
|
||||||
|
|
||||||
/** Sets the {@link OptimizationMode} for associated app. */
|
/** Sets the {@link OptimizationMode} for associated app. */
|
||||||
public void setAppUsageState(@OptimizationMode int mode) {
|
public void setAppUsageState(@OptimizationMode int mode) {
|
||||||
if (getAppOptimizationMode(mMode, mAllowListed) == mode) {
|
if (getAppOptimizationMode(mMode, mAllowListed) == mode) {
|
||||||
Log.w(TAG, "set the same optimization mode for: " + mPackageName);
|
Log.w(TAG, "set the same optimization mode for: " + mPackageName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setAppUsageStateInternal(mode, mUid, mPackageName, mBatteryUtils, mPowerAllowListBackend);
|
||||||
AsyncTask.execute(() -> {
|
|
||||||
switch (mode) {
|
|
||||||
case MODE_RESTRICTED:
|
|
||||||
setAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
|
|
||||||
break;
|
|
||||||
case MODE_UNRESTRICTED:
|
|
||||||
setAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
|
|
||||||
break;
|
|
||||||
case MODE_OPTIMIZED:
|
|
||||||
setAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.d(TAG, "set unknown app optimization mode.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,25 +135,111 @@ public class BatteryOptimizeUtils {
|
|||||||
*/
|
*/
|
||||||
public boolean isSystemOrDefaultApp() {
|
public boolean isSystemOrDefaultApp() {
|
||||||
mPowerAllowListBackend.refreshList();
|
mPowerAllowListBackend.refreshList();
|
||||||
|
return isSystemOrDefaultApp(mPowerAllowListBackend, mPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
return mPowerAllowListBackend.isSysAllowlisted(mPackageName)
|
/**
|
||||||
|| mPowerAllowListBackend.isDefaultActiveApp(mPackageName);
|
* Gets the list of installed applications.
|
||||||
|
*/
|
||||||
|
public static ArraySet<ApplicationInfo> getInstalledApplications(
|
||||||
|
Context context, IPackageManager ipm) {
|
||||||
|
final ArraySet<ApplicationInfo> applications = new ArraySet<>();
|
||||||
|
final UserManager um = context.getSystemService(UserManager.class);
|
||||||
|
for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final ParceledListSlice<ApplicationInfo> infoList = ipm.getInstalledApplications(
|
||||||
|
userInfo.isAdmin() ? RETRIEVE_FLAG_ADMIN : RETRIEVE_FLAG,
|
||||||
|
userInfo.id);
|
||||||
|
if (infoList != null) {
|
||||||
|
applications.addAll(infoList.getList());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "getInstalledApplications() is failed", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Removes the application which is disabled by the system.
|
||||||
|
applications.removeIf(
|
||||||
|
info -> info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
|
||||||
|
&& !info.enabled);
|
||||||
|
return applications;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static void resetAppOptimizationMode(
|
||||||
|
Context context, IPackageManager ipm, AppOpsManager aom,
|
||||||
|
PowerAllowlistBackend allowlistBackend, BatteryUtils batteryUtils) {
|
||||||
|
final ArraySet<ApplicationInfo> applications = getInstalledApplications(context, ipm);
|
||||||
|
if (applications == null || applications.isEmpty()) {
|
||||||
|
Log.w(TAG, "no data found in the getInstalledApplications()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allowlistBackend.refreshList();
|
||||||
|
// Resets optimization mode for each application.
|
||||||
|
for (ApplicationInfo info : applications) {
|
||||||
|
final int mode = aom.checkOpNoThrow(
|
||||||
|
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, info.uid, info.packageName);
|
||||||
|
@OptimizationMode
|
||||||
|
final int optimizationMode = getAppOptimizationMode(
|
||||||
|
mode, allowlistBackend.isAllowlisted(info.packageName));
|
||||||
|
// Ignores default optimized/unknown state or system/default apps.
|
||||||
|
if (optimizationMode == MODE_OPTIMIZED
|
||||||
|
|| optimizationMode == MODE_UNKNOWN
|
||||||
|
|| isSystemOrDefaultApp(allowlistBackend, info.packageName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resets to the default mode: MODE_OPTIMIZED.
|
||||||
|
setAppUsageStateInternal(MODE_OPTIMIZED, info.uid, info.packageName, batteryUtils,
|
||||||
|
allowlistBackend);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPackageName() {
|
String getPackageName() {
|
||||||
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
|
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAppOptimizationMode(int appStandbyMode, boolean allowListed) {
|
private static boolean isSystemOrDefaultApp(
|
||||||
|
PowerAllowlistBackend powerAllowlistBackend, String packageName) {
|
||||||
|
return powerAllowlistBackend.isSysAllowlisted(packageName)
|
||||||
|
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setAppUsageStateInternal(
|
||||||
|
@OptimizationMode int mode, int uid, String packageName, BatteryUtils batteryUtils,
|
||||||
|
PowerAllowlistBackend powerAllowlistBackend) {
|
||||||
|
if (mode == MODE_UNKNOWN) {
|
||||||
|
Log.d(TAG, "set unknown app optimization mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODE_RESTRICTED = AppOpsManager.MODE_IGNORED + !allowListed
|
||||||
|
// MODE_UNRESTRICTED = AppOpsManager.MODE_ALLOWED + allowListed
|
||||||
|
// MODE_OPTIMIZED = AppOpsManager.MODE_ALLOWED + !allowListed
|
||||||
|
final int appOpsManagerMode =
|
||||||
|
mode == MODE_RESTRICTED ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED;
|
||||||
|
final boolean allowListed = mode == MODE_UNRESTRICTED;
|
||||||
|
|
||||||
|
AsyncTask.execute(() -> {
|
||||||
|
setAppOptimizationModeInternal(appOpsManagerMode, allowListed, uid, packageName,
|
||||||
|
batteryUtils, powerAllowlistBackend);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setAppOptimizationModeInternal(
|
||||||
|
int appStandbyMode, boolean allowListed, int uid, String packageName,
|
||||||
|
BatteryUtils batteryUtils, PowerAllowlistBackend powerAllowlistBackend) {
|
||||||
try {
|
try {
|
||||||
mBatteryUtils.setForceAppStandby(mUid, mPackageName, appStandbyMode);
|
batteryUtils.setForceAppStandby(uid, packageName, appStandbyMode);
|
||||||
if (allowListed) {
|
if (allowListed) {
|
||||||
mPowerAllowListBackend.addApp(mPackageName);
|
powerAllowlistBackend.addApp(packageName);
|
||||||
} else {
|
} else {
|
||||||
mPowerAllowListBackend.removeApp(mPackageName);
|
powerAllowlistBackend.removeApp(packageName);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "set OPTIMIZED failed for " + mPackageName, e);
|
Log.e(TAG, "set OPTIMIZATION MODE failed for " + packageName, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,8 +249,6 @@ public class BatteryOptimizeUtils {
|
|||||||
mMode = mAppOpsManager
|
mMode = mAppOpsManager
|
||||||
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
|
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
|
||||||
Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d",
|
Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d",
|
||||||
mPackageName,
|
mPackageName, mAllowListed, mMode));
|
||||||
mAllowListed,
|
|
||||||
mMode));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@@ -48,6 +49,7 @@ import android.os.IDeviceIdleController;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
||||||
|
|
||||||
@@ -193,7 +195,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
doReturn(Arrays.asList(userInfo)).when(mUserManager).getProfiles(anyInt());
|
doReturn(Arrays.asList(userInfo)).when(mUserManager).getProfiles(anyInt());
|
||||||
doThrow(new RuntimeException())
|
doThrow(new RuntimeException())
|
||||||
.when(mIPackageManager)
|
.when(mIPackageManager)
|
||||||
.getInstalledApplications(anyInt(), anyInt());
|
.getInstalledApplications(anyLong(), anyInt());
|
||||||
|
|
||||||
mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, null);
|
mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, null);
|
||||||
|
|
||||||
@@ -369,7 +371,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
doReturn(new ParceledListSlice<ApplicationInfo>(
|
doReturn(new ParceledListSlice<ApplicationInfo>(
|
||||||
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3)))
|
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3)))
|
||||||
.when(mIPackageManager)
|
.when(mIPackageManager)
|
||||||
.getInstalledApplications(anyInt(), anyInt());
|
.getInstalledApplications(anyLong(), anyInt());
|
||||||
// Sets the AppOpsManager for checkOpNoThrow() method.
|
// Sets the AppOpsManager for checkOpNoThrow() method.
|
||||||
doReturn(AppOpsManager.MODE_ALLOWED)
|
doReturn(AppOpsManager.MODE_ALLOWED)
|
||||||
.when(mAppOpsManager)
|
.when(mAppOpsManager)
|
||||||
@@ -384,7 +386,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
applicationInfo2.uid,
|
applicationInfo2.uid,
|
||||||
applicationInfo2.packageName);
|
applicationInfo2.packageName);
|
||||||
mBatteryBackupHelper.mTestApplicationInfoList =
|
mBatteryBackupHelper.mTestApplicationInfoList =
|
||||||
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3);
|
new ArraySet<>(Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Implements(UserHandle.class)
|
@Implements(UserHandle.class)
|
||||||
|
@@ -22,26 +22,43 @@ import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRIC
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ParceledListSlice;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@@ -50,9 +67,11 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
private static final int UID = 12345;
|
private static final int UID = 12345;
|
||||||
private static final String PACKAGE_NAME = "com.android.app";
|
private static final String PACKAGE_NAME = "com.android.app";
|
||||||
|
|
||||||
@Mock BatteryUtils mMockBatteryUtils;
|
@Mock private BatteryUtils mMockBatteryUtils;
|
||||||
@Mock AppOpsManager mMockAppOpsManager;
|
@Mock private AppOpsManager mMockAppOpsManager;
|
||||||
@Mock PowerAllowlistBackend mMockBackend;
|
@Mock private PowerAllowlistBackend mMockBackend;
|
||||||
|
@Mock private IPackageManager mMockIPackageManager;
|
||||||
|
@Mock private UserManager mMockUserManager;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private BatteryOptimizeUtils mBatteryOptimizeUtils;
|
private BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||||
@@ -68,6 +87,7 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
// Sets the default mode as MODE_RESTRICTED.
|
// Sets the default mode as MODE_RESTRICTED.
|
||||||
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_IGNORED;
|
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_IGNORED;
|
||||||
mBatteryOptimizeUtils.mAllowListed = false;
|
mBatteryOptimizeUtils.mAllowListed = false;
|
||||||
|
doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -135,9 +155,7 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
mBatteryOptimizeUtils.setAppUsageState(MODE_RESTRICTED);
|
mBatteryOptimizeUtils.setAppUsageState(MODE_RESTRICTED);
|
||||||
TimeUnit.SECONDS.sleep(1);
|
TimeUnit.SECONDS.sleep(1);
|
||||||
|
|
||||||
verify(mMockBatteryUtils).setForceAppStandby(UID,
|
verifySetAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
|
||||||
PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
|
|
||||||
verify(mMockBackend).removeApp(PACKAGE_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -145,9 +163,7 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
|
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
|
||||||
TimeUnit.SECONDS.sleep(1);
|
TimeUnit.SECONDS.sleep(1);
|
||||||
|
|
||||||
verify(mMockBatteryUtils).setForceAppStandby(UID,
|
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
|
||||||
PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
|
|
||||||
verify(mMockBackend).addApp(PACKAGE_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -155,9 +171,7 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
mBatteryOptimizeUtils.setAppUsageState(MODE_OPTIMIZED);
|
mBatteryOptimizeUtils.setAppUsageState(MODE_OPTIMIZED);
|
||||||
TimeUnit.SECONDS.sleep(1);
|
TimeUnit.SECONDS.sleep(1);
|
||||||
|
|
||||||
verify(mMockBatteryUtils).setForceAppStandby(UID,
|
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
|
||||||
PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
|
|
||||||
verify(mMockBackend).removeApp(PACKAGE_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -172,4 +186,148 @@ public class BatteryOptimizeUtilsTest {
|
|||||||
verifyZeroInteractions(mMockBackend);
|
verifyZeroInteractions(mMockBackend);
|
||||||
verifyZeroInteractions(mMockBatteryUtils);
|
verifyZeroInteractions(mMockBatteryUtils);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInstalledApplications_returnEmptyArray() {
|
||||||
|
assertTrue(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager)
|
||||||
|
.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInstalledApplications_returnNull() throws Exception {
|
||||||
|
final UserInfo userInfo =
|
||||||
|
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
|
||||||
|
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
|
||||||
|
doThrow(new RuntimeException())
|
||||||
|
.when(mMockIPackageManager)
|
||||||
|
.getInstalledApplications(anyLong(), anyInt());
|
||||||
|
|
||||||
|
assertNull(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInstalledApplications_returnInstalledApps() throws Exception {
|
||||||
|
final UserInfo userInfo =
|
||||||
|
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
|
||||||
|
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
|
||||||
|
|
||||||
|
final ApplicationInfo applicationInfo1 = new ApplicationInfo();
|
||||||
|
applicationInfo1.enabled = true;
|
||||||
|
applicationInfo1.uid = 1;
|
||||||
|
final ApplicationInfo applicationInfo2 = new ApplicationInfo();
|
||||||
|
applicationInfo2.enabled = false;
|
||||||
|
applicationInfo2.uid = 2;
|
||||||
|
applicationInfo2.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
|
||||||
|
final ApplicationInfo applicationInfo3 = new ApplicationInfo();
|
||||||
|
applicationInfo3.enabled = false;
|
||||||
|
applicationInfo3.uid = 3;
|
||||||
|
applicationInfo3.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
||||||
|
final ApplicationInfo applicationInfo4 = new ApplicationInfo();
|
||||||
|
applicationInfo4.enabled = true;
|
||||||
|
applicationInfo4.uid = 4;
|
||||||
|
applicationInfo4.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
|
||||||
|
doReturn(new ParceledListSlice<ApplicationInfo>(
|
||||||
|
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3, applicationInfo4)))
|
||||||
|
.when(mMockIPackageManager)
|
||||||
|
.getInstalledApplications(anyLong(), anyInt());
|
||||||
|
|
||||||
|
final ArraySet<ApplicationInfo> applications =
|
||||||
|
BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager);
|
||||||
|
assertThat(applications.size()).isEqualTo(3);
|
||||||
|
// applicationInfo3 should be filtered.
|
||||||
|
assertTrue(applications.contains(applicationInfo1));
|
||||||
|
assertTrue(applications.contains(applicationInfo2));
|
||||||
|
assertFalse(applications.contains(applicationInfo3));
|
||||||
|
assertTrue(applications.contains(applicationInfo4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetAppOptimizationMode_Optimized_verifyAction() throws Exception {
|
||||||
|
runTestForResetWithMode(
|
||||||
|
AppOpsManager.MODE_ALLOWED, /* allowListed */ false,
|
||||||
|
/* isSystemOrDefaultApp */ false);
|
||||||
|
|
||||||
|
verifyZeroInteractions(mMockBatteryUtils);
|
||||||
|
|
||||||
|
final InOrder inOrder = inOrder(mMockBackend);
|
||||||
|
inOrder.verify(mMockBackend).refreshList();
|
||||||
|
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
|
||||||
|
verifyNoMoreInteractions(mMockBackend);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetAppOptimizationMode_SystemOrDefault_verifyAction() throws Exception {
|
||||||
|
runTestForResetWithMode(
|
||||||
|
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
|
||||||
|
/* isSystemOrDefaultApp */ true);
|
||||||
|
|
||||||
|
verifyZeroInteractions(mMockBatteryUtils);
|
||||||
|
|
||||||
|
final InOrder inOrder = inOrder(mMockBackend);
|
||||||
|
inOrder.verify(mMockBackend).refreshList();
|
||||||
|
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
|
||||||
|
inOrder.verify(mMockBackend).isSysAllowlisted(PACKAGE_NAME);
|
||||||
|
verifyNoMoreInteractions(mMockBackend);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetAppOptimizationMode_Restricted_verifyAction() throws Exception {
|
||||||
|
runTestForResetWithMode(
|
||||||
|
AppOpsManager.MODE_IGNORED, /* allowListed */ false,
|
||||||
|
/* isSystemOrDefaultApp */ false);
|
||||||
|
|
||||||
|
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetAppOptimizationMode_Unrestricted_verifyAction() throws Exception {
|
||||||
|
runTestForResetWithMode(
|
||||||
|
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
|
||||||
|
/* isSystemOrDefaultApp */ false);
|
||||||
|
|
||||||
|
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runTestForResetWithMode(
|
||||||
|
int appStandbyMode, boolean allowListed, boolean isSystemOrDefaultApp)
|
||||||
|
throws Exception {
|
||||||
|
final UserInfo userInfo =
|
||||||
|
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
|
||||||
|
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
|
||||||
|
final ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||||
|
applicationInfo.uid = UID;
|
||||||
|
applicationInfo.packageName = PACKAGE_NAME;
|
||||||
|
applicationInfo.enabled = true;
|
||||||
|
doReturn(new ParceledListSlice<ApplicationInfo>(
|
||||||
|
Arrays.asList(applicationInfo)))
|
||||||
|
.when(mMockIPackageManager)
|
||||||
|
.getInstalledApplications(anyLong(), anyInt());
|
||||||
|
|
||||||
|
doReturn(appStandbyMode)
|
||||||
|
.when(mMockAppOpsManager)
|
||||||
|
.checkOpNoThrow(anyInt(), anyInt(), anyString());
|
||||||
|
doReturn(allowListed)
|
||||||
|
.when(mMockBackend)
|
||||||
|
.isAllowlisted(anyString());
|
||||||
|
doReturn(isSystemOrDefaultApp)
|
||||||
|
.when(mMockBackend)
|
||||||
|
.isSysAllowlisted(anyString());
|
||||||
|
doReturn(isSystemOrDefaultApp)
|
||||||
|
.when(mMockBackend)
|
||||||
|
.isDefaultActiveApp(anyString());
|
||||||
|
|
||||||
|
BatteryOptimizeUtils.resetAppOptimizationMode(
|
||||||
|
mContext, mMockIPackageManager, mMockAppOpsManager, mMockBackend,
|
||||||
|
mMockBatteryUtils);
|
||||||
|
TimeUnit.SECONDS.sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifySetAppOptimizationMode(int appStandbyMode, boolean allowListed) {
|
||||||
|
verify(mMockBatteryUtils).setForceAppStandby(UID, PACKAGE_NAME, appStandbyMode);
|
||||||
|
if (allowListed) {
|
||||||
|
verify(mMockBackend).addApp(PACKAGE_NAME);
|
||||||
|
} else {
|
||||||
|
verify(mMockBackend).removeApp(PACKAGE_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user