From 19b558678dc2a69068f64fc5b137e5c0e03c0a25 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Tue, 12 Jan 2021 23:03:24 -0800 Subject: [PATCH] DeviceIdleController updates AMS with temp allowlist type. 1. add a "type" parameter to AMS.updateDeviceIdleTempWhitelist() which is called by DeviceIdleController. 2. The default temp allowlist type is TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED which allows BG-FGS launch. 3. AMS.tempWhitelistUidLocked() already has a type parameter. Other API to add temp allowlist can also add type parameter other than the default. Bug: 175244558. Test: atest cts/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java Change-Id: Ib42c445c15966bd260964782a7254ed2a7ffa405 --- .../android/server/DeviceIdleInternal.java | 15 ++++++- .../android/server/DeviceIdleController.java | 45 ++++++++++++------- .../android/app/ActivityManagerInternal.java | 11 +++-- .../server/activitymanagerservice.proto | 1 + .../server/am/ActivityManagerService.java | 32 ++++++++----- .../server/am/FgsStartTempAllowList.java | 5 ++- .../com/android/server/am/OomAdjuster.java | 5 +-- 7 files changed, 78 insertions(+), 36 deletions(-) diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java index 18643ed912762..4441643905500 100644 --- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java @@ -16,6 +16,8 @@ package com.android.server; +import android.app.BroadcastOptions; + import com.android.server.deviceidle.IDeviceIdleConstraint; public interface DeviceIdleInternal { @@ -32,8 +34,17 @@ public interface DeviceIdleInternal { void addPowerSaveTempWhitelistApp(int callingUid, String packageName, long duration, int userId, boolean sync, String reason); - // duration in milliseconds - void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync, + /** + * Called by ActivityManagerService to directly add UID to DeviceIdleController's temp + * allowlist. + * @param uid + * @param duration duration in milliseconds + * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType} + * @param sync + * @param reason + */ + void addPowerSaveTempWhitelistAppDirect(int uid, long duration, + @BroadcastOptions.TempAllowListType int type, boolean sync, String reason); // duration in milliseconds diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 4b98c32db6082..7aed32c16ae24 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -21,6 +21,8 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; +import android.app.BroadcastOptions; +import android.app.BroadcastOptions.TempAllowListType; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -1941,9 +1943,9 @@ public class DeviceIdleController extends SystemService // duration in milliseconds @Override - public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync, - String reason) { - addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, sync, reason); + public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, + @TempAllowListType int type, boolean sync, String reason) { + addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, type, sync, reason); } // duration in milliseconds @@ -2719,7 +2721,9 @@ public class DeviceIdleController extends SystemService long duration, int userId, boolean sync, String reason) { try { int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId); - addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, sync, reason); + addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, duration, + BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED, sync, + reason); } catch (NameNotFoundException e) { } } @@ -2729,7 +2733,7 @@ public class DeviceIdleController extends SystemService * app an exemption to access network and acquire wakelocks. */ void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid, - long duration, boolean sync, String reason) { + long duration, @TempAllowListType int type, boolean sync, String reason) { final long timeNow = SystemClock.elapsedRealtime(); boolean informWhitelistChanged = false; int appId = UserHandle.getAppId(uid); @@ -2761,7 +2765,7 @@ public class DeviceIdleController extends SystemService } catch (RemoteException e) { } postTempActiveTimeoutMessage(uid, duration); - updateTempWhitelistAppIdsLocked(appId, true); + updateTempWhitelistAppIdsLocked(uid, true, duration, type); if (sync) { informWhitelistChanged = true; } else { @@ -2786,8 +2790,7 @@ public class DeviceIdleController extends SystemService try { final int uid = getContext().getPackageManager().getPackageUidAsUser( packageName, userId); - final int appId = UserHandle.getAppId(uid); - removePowerSaveTempWhitelistAppDirectInternal(appId); + removePowerSaveTempWhitelistAppDirectInternal(uid); } catch (NameNotFoundException e) { } } @@ -2821,7 +2824,8 @@ public class DeviceIdleController extends SystemService Slog.d(TAG, "checkTempAppWhitelistTimeout: uid=" + uid + ", timeNow=" + timeNow); } synchronized (this) { - Pair entry = mTempWhitelistAppIdEndTimes.get(appId); + Pair entry = + mTempWhitelistAppIdEndTimes.get(appId); if (entry == null) { // Nothing to do return; @@ -2832,7 +2836,7 @@ public class DeviceIdleController extends SystemService } else { // Need more time if (DEBUG) { - Slog.d(TAG, "Time to remove AppId " + appId + ": " + entry.first.value); + Slog.d(TAG, "Time to remove uid " + uid + ": " + entry.first.value); } postTempActiveTimeoutMessage(uid, entry.first.value - timeNow); } @@ -2841,12 +2845,12 @@ public class DeviceIdleController extends SystemService @GuardedBy("this") private void onAppRemovedFromTempWhitelistLocked(int uid, String reason) { - final int appId = UserHandle.getAppId(uid); if (DEBUG) { Slog.d(TAG, "Removing uid " + uid + " from temp whitelist"); } - updateTempWhitelistAppIdsLocked(appId, false); - mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED_TO_NPMS, appId, 0) + final int appId = UserHandle.getAppId(uid); + updateTempWhitelistAppIdsLocked(uid, false, 0, 0); + mHandler.obtainMessage(MSG_REPORT_TEMP_APP_WHITELIST_CHANGED, appId, 0) .sendToTarget(); reportTempWhitelistChangedLocked(uid, false); try { @@ -3869,7 +3873,16 @@ public class DeviceIdleController extends SystemService passWhiteListsToForceAppStandbyTrackerLocked(); } - private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) { + /** + * update temp allowlist. + * @param uid uid to add or remove from temp allowlist. + * @param adding true to add to temp allowlist, false to remove from temp allowlist. + * @param durationMs duration in milliseconds to add to temp allowlist, only valid when + * param adding is true. + * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType} + */ + private void updateTempWhitelistAppIdsLocked(int uid, boolean adding, long durationMs, + @TempAllowListType int type) { final int size = mTempWhitelistAppIdEndTimes.size(); if (mTempWhitelistAppIdArray.length != size) { mTempWhitelistAppIdArray = new int[size]; @@ -3882,8 +3895,8 @@ public class DeviceIdleController extends SystemService Slog.d(TAG, "Setting activity manager temp whitelist to " + Arrays.toString(mTempWhitelistAppIdArray)); } - mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId, - adding); + mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, uid, + adding, durationMs, type); } if (mLocalPowerManager != null) { if (DEBUG) { diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index f7f42a6e27134..986051cccd510 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -98,7 +98,7 @@ public abstract class ActivityManagerInternal { public abstract void killForegroundAppsForUser(@UserIdInt int userId); /** - * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions + * Sets how long a {@link PendingIntent} can be temporarily allowlisted to bypass restrictions * such as Power Save mode. * @param target * @param whitelistToken @@ -132,9 +132,14 @@ public abstract class ActivityManagerInternal { /** * Update information about which app IDs are on the temp whitelist. + * @param appids the updated list of appIds in temp allowlist. + * @param changingUid uid to add or remove to temp allowlist. + * @param adding true to add to temp allowlist, false to remove from temp allowlist. + * @param durationMs when adding is true, the duration to be in temp allowlist. + * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType}. */ - public abstract void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, - boolean adding); + public abstract void updateDeviceIdleTempWhitelist(int[] appids, int changingUid, + boolean adding, long durationMs, @BroadcastOptions.TempAllowListType int type); /** * Get the procstate for the UID. The return value will be between diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index fa046c6593afa..d3c2d31779dbf 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -626,6 +626,7 @@ message ActivityManagerServiceDumpProcessesProto { optional int32 target_uid = 1; optional int64 duration_ms = 2; optional string tag = 3; + optional int32 type = 4; } repeated PendingTempWhitelist pending_temp_whitelist = 26; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 16874cfb58190..85e9b331faeb0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -32,6 +32,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AppOpsManager.OP_NONE; +import static android.app.BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT; import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; import static android.content.pm.PackageManager.MATCH_ALL; @@ -1085,11 +1086,13 @@ public class ActivityManagerService extends IActivityManager.Stub final int targetUid; final long duration; final String tag; + final int type; - PendingTempWhitelist(int _targetUid, long _duration, String _tag) { + PendingTempWhitelist(int _targetUid, long _duration, String _tag, int _type) { targetUid = _targetUid; duration = _duration; tag = _tag; + type = _type; } void dumpDebug(ProtoOutputStream proto, long fieldId) { @@ -1097,6 +1100,7 @@ public class ActivityManagerService extends IActivityManager.Stub proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TARGET_UID, targetUid); proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.DURATION_MS, duration); proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TAG, tag); + proto.write(ActivityManagerServiceDumpProcessesProto.PendingTempWhitelist.TYPE, type); proto.end(token); } } @@ -5526,8 +5530,7 @@ public class ActivityManagerService extends IActivityManager.Stub } boolean isWhitelistedForFgsStartLocked(int uid) { - final int appId = UserHandle.getAppId(uid); - return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, appId) >= 0 + return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, UserHandle.getAppId(uid)) >= 0 || mFgsStartTempAllowList.isAllowed(uid); } @@ -9298,6 +9301,8 @@ public class ActivityManagerService extends IActivityManager.Stub TimeUtils.formatDuration(ptw.duration, pw); pw.print(" "); pw.println(ptw.tag); + pw.print(" "); + pw.print(ptw.type); } } } @@ -15359,11 +15364,12 @@ public class ActivityManagerService extends IActivityManager.Stub */ @GuardedBy("this") void tempWhitelistUidLocked(int targetUid, long duration, String tag, int type) { - mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); + mPendingTempWhitelist.put(targetUid, + new PendingTempWhitelist(targetUid, duration, tag, type)); setUidTempWhitelistStateLocked(targetUid, true); mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); - if (type == BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { + if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { mFgsStartTempAllowList.add(targetUid, duration); } } @@ -15389,7 +15395,7 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i = 0; i < N; i++) { PendingTempWhitelist ptw = list[i]; mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid, - ptw.duration, true, ptw.tag); + ptw.duration, ptw.type, true, ptw.tag); } } @@ -15406,8 +15412,8 @@ public class ActivityManagerService extends IActivityManager.Stub } @GuardedBy("this") - final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { - mOomAdjuster.setAppIdTempWhitelistStateLocked(appId, onWhitelist); + final void setAppIdTempWhitelistStateLocked(int uid, boolean onWhitelist) { + mOomAdjuster.setAppIdTempWhitelistStateLocked(uid, onWhitelist); } @GuardedBy("this") @@ -15999,10 +16005,16 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, boolean adding) { + public void updateDeviceIdleTempWhitelist(int[] appids, int changingUid, boolean adding, + long durationMs, @BroadcastOptions.TempAllowListType int type) { synchronized (ActivityManagerService.this) { mDeviceIdleTempWhitelist = appids; - setAppIdTempWhitelistStateLocked(changingAppId, adding); + if (adding) { + if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { + mFgsStartTempAllowList.add(changingUid, durationMs); + } + } + setAppIdTempWhitelistStateLocked(changingUid, adding); } } diff --git a/services/core/java/com/android/server/am/FgsStartTempAllowList.java b/services/core/java/com/android/server/am/FgsStartTempAllowList.java index 1f9039392405e..3aca4cfd01620 100644 --- a/services/core/java/com/android/server/am/FgsStartTempAllowList.java +++ b/services/core/java/com/android/server/am/FgsStartTempAllowList.java @@ -28,7 +28,7 @@ import android.util.SparseLongArray; final class FgsStartTempAllowList { private static final int MAX_SIZE = 100; /** - * The key is the UID, the value is expiration elapse time in ms of this temp-allowed UID. + * The key is the uid, the value is expiration elapse time in ms of this temp-allowed uid. */ private final SparseLongArray mTempAllowListFgs = new SparseLongArray(); @@ -37,7 +37,8 @@ final class FgsStartTempAllowList { void add(int uid, long duration) { if (duration <= 0) { - Slog.e(TAG_AM, "FgsStartTempAllowList bad duration:" + duration + " uid: " + uid); + Slog.e(TAG_AM, "FgsStartTempAllowList bad duration:" + duration + " uid: " + + uid); return; } // The temp allowlist should be a short list with only a few entries in it. diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index d69bf2d75064f..de7931535297a 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -92,7 +92,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.Trace; -import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LongSparseArray; @@ -2731,11 +2730,11 @@ public final class OomAdjuster { } @GuardedBy("mService") - final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { + final void setAppIdTempWhitelistStateLocked(int uid, boolean onWhitelist) { boolean changed = false; for (int i = mActiveUids.size() - 1; i >= 0; i--) { final UidRecord uidRec = mActiveUids.valueAt(i); - if (UserHandle.getAppId(uidRec.uid) == appId && uidRec.curWhitelist != onWhitelist) { + if (uidRec.uid == uid && uidRec.curWhitelist != onWhitelist) { uidRec.curWhitelist = onWhitelist; changed = true; }