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
This commit is contained in:
Hui Yu
2021-01-12 23:03:24 -08:00
parent ab9dd642fe
commit 19b558678d
7 changed files with 78 additions and 36 deletions

View File

@@ -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

View File

@@ -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<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
Pair<MutableLong, String> 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) {

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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;
}