Merge "Reset Optimization Mode of apps when users reset app settings." into tm-qpr-dev am: 614d2dfc0b

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

Change-Id: Ib7e9e58435110c22bf6ca10c4cd9f4181d1f9e7c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
KUAN WANG
2022-05-16 05:54:28 +00:00
committed by Automerger Merge Worker
5 changed files with 301 additions and 83 deletions

View File

@@ -38,6 +38,7 @@ import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryOptimizeUtils;
import java.util.Arrays;
import java.util.List;
@@ -152,6 +153,7 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener,
} catch (RemoteException e) {
}
mAom.resetAllModes();
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
final int[] restrictedUids = mNpm.getUidsWithPolicy(
POLICY_REJECT_METERED_BACKGROUND);
final int currentUserId = ActivityManager.getCurrentUser();

View File

@@ -24,16 +24,13 @@ import android.app.backup.BackupHelper;
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.Build;
import android.os.IDeviceIdleController;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log;
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 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_MODE = ":";
static final String KEY_FULL_POWER_LIST = "full_power_list";
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
@VisibleForTesting
List<ApplicationInfo> mTestApplicationInfoList = null;
ArraySet<ApplicationInfo> mTestApplicationInfoList = null;
@VisibleForTesting
PowerAllowlistBackend mPowerAllowlistBackend;
@@ -146,7 +134,7 @@ public final class BatteryBackupHelper implements BackupHelper {
@VisibleForTesting
void backupOptimizationMode(BackupDataOutput data, List<String> allowlistedApps) {
final long timestamp = System.currentTimeMillis();
final List<ApplicationInfo> applications = getInstalledApplications();
final ArraySet<ApplicationInfo> applications = getInstalledApplications();
if (applications == null || applications.isEmpty()) {
Log.w(TAG, "no data found in the getInstalledApplications()");
return;
@@ -269,36 +257,11 @@ public final class BatteryBackupHelper implements BackupHelper {
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
}
private List<ApplicationInfo> getInstalledApplications() {
private ArraySet<ApplicationInfo> getInstalledApplications() {
if (mTestApplicationInfoList != null) {
return mTestApplicationInfoList;
}
final List<ApplicationInfo> applications = new ArrayList<>();
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;
return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager());
}
private void debugLog(String debugContent) {

View File

@@ -19,7 +19,15 @@ package com.android.settings.fuelgauge;
import android.annotation.IntDef;
import android.app.AppOpsManager;
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.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -43,6 +51,15 @@ public class BatteryOptimizeUtils {
private final String mPackageName;
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.
static final int MODE_UNKNOWN = 0;
static final int MODE_RESTRICTED = 1;
@@ -90,28 +107,20 @@ public class BatteryOptimizeUtils {
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. */
public void setAppUsageState(@OptimizationMode int mode) {
if (getAppOptimizationMode(mMode, mAllowListed) == mode) {
Log.w(TAG, "set the same optimization mode for: " + mPackageName);
return;
}
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.");
}
});
setAppUsageStateInternal(mode, mUid, mPackageName, mBatteryUtils, mPowerAllowListBackend);
}
/**
@@ -126,25 +135,111 @@ public class BatteryOptimizeUtils {
*/
public boolean isSystemOrDefaultApp() {
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() {
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 {
mBatteryUtils.setForceAppStandby(mUid, mPackageName, appStandbyMode);
batteryUtils.setForceAppStandby(uid, packageName, appStandbyMode);
if (allowListed) {
mPowerAllowListBackend.addApp(mPackageName);
powerAllowlistBackend.addApp(packageName);
} else {
mPowerAllowListBackend.removeApp(mPackageName);
powerAllowlistBackend.removeApp(packageName);
}
} 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
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d",
mPackageName,
mAllowListed,
mMode));
mPackageName, mAllowListed, mMode));
}
}