Merge "While-idle alarm timeout & EBS"
This commit is contained in:
@@ -27,6 +27,7 @@ package com.android.server;
|
||||
|
||||
option java_multiple_files = true;
|
||||
|
||||
// next ID: 43
|
||||
message AlarmManagerServiceProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
@@ -114,7 +115,14 @@ message AlarmManagerServiceProto {
|
||||
optional int32 uid = 1;
|
||||
// In the 'elapsed' timebase.
|
||||
optional int64 time_ms = 2;
|
||||
|
||||
// Time when the next while-idle is allowed, in the 'elapsed' timebase.
|
||||
optional int64 next_allowed_ms = 3;
|
||||
}
|
||||
|
||||
// Whether the short or long while-idle timeout should be used for each UID.
|
||||
repeated int32 use_allow_while_idle_short_time = 42;
|
||||
|
||||
// For each uid, this is the last time we dispatched an "allow while idle"
|
||||
// alarm, used to determine the earliest we can dispatch the next such alarm.
|
||||
repeated LastAllowWhileIdleDispatch last_allow_while_idle_dispatch_times = 36;
|
||||
|
||||
@@ -24,14 +24,19 @@ package com.android.server;
|
||||
option java_multiple_files = true;
|
||||
|
||||
// Dump from com.android.server.ForceAppStandbyTracker.
|
||||
//
|
||||
// Next ID: 12
|
||||
message ForceAppStandbyTrackerProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
// Whether all apps are forced standby or not.
|
||||
optional bool force_all_apps_standby = 1;
|
||||
|
||||
// UIDs currently active.
|
||||
repeated int32 active_uids = 2;
|
||||
|
||||
// UIDs currently in the foreground.
|
||||
repeated int32 foreground_uids = 2;
|
||||
repeated int32 foreground_uids = 11;
|
||||
|
||||
// App ids that are in power-save whitelist.
|
||||
repeated int32 power_save_whitelist_app_ids = 3;
|
||||
|
||||
@@ -1840,14 +1840,6 @@ class AlarmManagerService extends SystemService {
|
||||
if (!blocked) {
|
||||
pw.println(" none");
|
||||
}
|
||||
pw.print(" mUseAllowWhileIdleShortTime: [");
|
||||
for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
|
||||
if (mUseAllowWhileIdleShortTime.valueAt(i)) {
|
||||
UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
|
||||
pw.print(" ");
|
||||
}
|
||||
}
|
||||
pw.println("]");
|
||||
|
||||
pw.println(" mLastAlarmDeliveredForPackage:");
|
||||
for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
|
||||
@@ -1913,14 +1905,32 @@ class AlarmManagerService extends SystemService {
|
||||
if (mLastAllowWhileIdleDispatch.size() > 0) {
|
||||
pw.println(" Last allow while idle dispatch times:");
|
||||
for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
|
||||
pw.print(" UID ");
|
||||
UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
|
||||
pw.print(" UID ");
|
||||
final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
|
||||
UserHandle.formatUid(pw, uid);
|
||||
pw.print(": ");
|
||||
TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
|
||||
nowELAPSED, pw);
|
||||
final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
|
||||
TimeUtils.formatDuration(lastTime, nowELAPSED, pw);
|
||||
|
||||
final long minInterval = getWhileIdleMinIntervalLocked(uid);
|
||||
pw.print(" Next allowed:");
|
||||
TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
|
||||
pw.print(" (");
|
||||
TimeUtils.formatDuration(minInterval, 0, pw);
|
||||
pw.print(")");
|
||||
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
|
||||
pw.print(" mUseAllowWhileIdleShortTime: [");
|
||||
for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
|
||||
if (mUseAllowWhileIdleShortTime.valueAt(i)) {
|
||||
UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
|
||||
pw.print(" ");
|
||||
}
|
||||
}
|
||||
pw.println("]");
|
||||
pw.println();
|
||||
|
||||
if (mLog.dump(pw, " Recent problems", " ")) {
|
||||
@@ -2181,13 +2191,23 @@ class AlarmManagerService extends SystemService {
|
||||
for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
|
||||
final long token = proto.start(
|
||||
AlarmManagerServiceProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
|
||||
proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID,
|
||||
mLastAllowWhileIdleDispatch.keyAt(i));
|
||||
proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS,
|
||||
mLastAllowWhileIdleDispatch.valueAt(i));
|
||||
final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
|
||||
final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
|
||||
|
||||
proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID, uid);
|
||||
proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime);
|
||||
proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
|
||||
lastTime + getWhileIdleMinIntervalLocked(uid));
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
|
||||
if (mUseAllowWhileIdleShortTime.valueAt(i)) {
|
||||
proto.write(AlarmManagerServiceProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
|
||||
mUseAllowWhileIdleShortTime.keyAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
mLog.writeToProto(proto, AlarmManagerServiceProto.RECENT_PROBLEMS);
|
||||
|
||||
final FilterStats[] topFilters = new FilterStats[10];
|
||||
@@ -2866,6 +2886,23 @@ class AlarmManagerService extends SystemService {
|
||||
private native int setKernelTime(long nativeData, long millis);
|
||||
private native int setKernelTimezone(long nativeData, int minuteswest);
|
||||
|
||||
private long getWhileIdleMinIntervalLocked(int uid) {
|
||||
final boolean dozing = mPendingIdleUntil != null;
|
||||
final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
|
||||
if (!dozing && !ebs) {
|
||||
return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
|
||||
}
|
||||
if (dozing) {
|
||||
return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
|
||||
}
|
||||
if (mUseAllowWhileIdleShortTime.get(uid)) {
|
||||
// if the last allow-while-idle went off while uid was fg, or the uid
|
||||
// recently came into fg, don't block the alarm for long.
|
||||
return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
|
||||
}
|
||||
return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
|
||||
}
|
||||
|
||||
boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
|
||||
final long nowRTC) {
|
||||
boolean hasWakeup = false;
|
||||
@@ -2891,20 +2928,7 @@ class AlarmManagerService extends SystemService {
|
||||
// If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
|
||||
// schedule such alarms.
|
||||
final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
|
||||
final boolean dozing = mPendingIdleUntil != null;
|
||||
final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
|
||||
final long minTime;
|
||||
if (!dozing && !ebs) {
|
||||
minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
|
||||
} else if (dozing) {
|
||||
minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
|
||||
} else if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) {
|
||||
// if the last allow-while-idle went off while uid was fg, or the uid
|
||||
// recently came into fg, don't block the alarm for long.
|
||||
minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
|
||||
} else {
|
||||
minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
|
||||
}
|
||||
final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
|
||||
if (nowELAPSED < minTime) {
|
||||
// Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
|
||||
// alarm went off for this app. Reschedule the alarm to be in the
|
||||
@@ -3641,6 +3665,7 @@ class AlarmManagerService extends SystemService {
|
||||
} else if (Intent.ACTION_UID_REMOVED.equals(action)) {
|
||||
if (uid >= 0) {
|
||||
mLastAllowWhileIdleDispatch.delete(uid);
|
||||
mUseAllowWhileIdleShortTime.delete(uid);
|
||||
}
|
||||
} else {
|
||||
if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
|
||||
@@ -3693,7 +3718,6 @@ class AlarmManagerService extends SystemService {
|
||||
|
||||
@Override public void onUidGone(int uid, boolean disabled) {
|
||||
synchronized (mLock) {
|
||||
mUseAllowWhileIdleShortTime.delete(uid);
|
||||
if (disabled) {
|
||||
removeForStoppedLocked(uid);
|
||||
}
|
||||
@@ -3701,9 +3725,6 @@ class AlarmManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override public void onUidActive(int uid) {
|
||||
synchronized (mLock) {
|
||||
mUseAllowWhileIdleShortTime.put(uid, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onUidIdle(int uid, boolean disabled) {
|
||||
@@ -3766,6 +3787,18 @@ class AlarmManagerService extends SystemService {
|
||||
sendPendingBackgroundAlarmsLocked(uid, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUidForeground(int uid, boolean foreground) {
|
||||
synchronized (mLock) {
|
||||
if (foreground) {
|
||||
mUseAllowWhileIdleShortTime.put(uid, true);
|
||||
|
||||
// Note we don't have to drain the pending while-idle alarms here, because
|
||||
// this event should coincide with unblockAlarmsForUid().
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastStats getStatsLocked(PendingIntent pi) {
|
||||
@@ -4026,7 +4059,7 @@ class AlarmManagerService extends SystemService {
|
||||
if (allowWhileIdle) {
|
||||
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
|
||||
mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
|
||||
if (mForceAppStandbyTracker.isInForeground(alarm.creatorUid)) {
|
||||
if (mForceAppStandbyTracker.isUidInForeground(alarm.creatorUid)) {
|
||||
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
|
||||
} else {
|
||||
mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.android.internal.app.IAppOpsCallback;
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.DeviceIdleController.LocalService;
|
||||
import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
|
||||
import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
|
||||
|
||||
@@ -64,18 +65,15 @@ import java.util.List;
|
||||
/**
|
||||
* Class to keep track of the information related to "force app standby", which includes:
|
||||
* - OP_RUN_ANY_IN_BACKGROUND for each package
|
||||
* - UID foreground state
|
||||
* - UID foreground/active state
|
||||
* - User+system power save whitelist
|
||||
* - Temporary power save whitelist
|
||||
* - Global "force all apps standby" mode enforced by battery saver.
|
||||
*
|
||||
* TODO: In general, we can reduce the number of callbacks by checking all signals before sending
|
||||
* each callback. For example, even when an UID comes into the foreground, if it wasn't
|
||||
* originally restricted, then there's no need to send an event.
|
||||
* Doing this would be error-prone, so we punt it for now, but we should revisit it later.
|
||||
* TODO: Make it a LocalService.
|
||||
*
|
||||
* Test:
|
||||
* atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
|
||||
atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
|
||||
*/
|
||||
public class ForceAppStandbyTracker {
|
||||
private static final String TAG = "ForceAppStandbyTracker";
|
||||
@@ -108,6 +106,11 @@ public class ForceAppStandbyTracker {
|
||||
@GuardedBy("mLock")
|
||||
final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
|
||||
|
||||
/** UIDs that are active. */
|
||||
@GuardedBy("mLock")
|
||||
final SparseBooleanArray mActiveUids = new SparseBooleanArray();
|
||||
|
||||
/** UIDs that are in the foreground. */
|
||||
@GuardedBy("mLock")
|
||||
final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
|
||||
|
||||
@@ -160,18 +163,20 @@ public class ForceAppStandbyTracker {
|
||||
boolean mForcedAppStandbyEnabled;
|
||||
|
||||
interface Stats {
|
||||
int UID_STATE_CHANGED = 0;
|
||||
int RUN_ANY_CHANGED = 1;
|
||||
int ALL_UNWHITELISTED = 2;
|
||||
int ALL_WHITELIST_CHANGED = 3;
|
||||
int TEMP_WHITELIST_CHANGED = 4;
|
||||
int EXEMPT_CHANGED = 5;
|
||||
int FORCE_ALL_CHANGED = 6;
|
||||
int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 7;
|
||||
int UID_FG_STATE_CHANGED = 0;
|
||||
int UID_ACTIVE_STATE_CHANGED = 1;
|
||||
int RUN_ANY_CHANGED = 2;
|
||||
int ALL_UNWHITELISTED = 3;
|
||||
int ALL_WHITELIST_CHANGED = 4;
|
||||
int TEMP_WHITELIST_CHANGED = 5;
|
||||
int EXEMPT_CHANGED = 6;
|
||||
int FORCE_ALL_CHANGED = 7;
|
||||
int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
|
||||
}
|
||||
|
||||
private final StatLogger mStatLogger = new StatLogger(new String[] {
|
||||
"UID_STATE_CHANGED",
|
||||
"UID_FG_STATE_CHANGED",
|
||||
"UID_ACTIVE_STATE_CHANGED",
|
||||
"RUN_ANY_CHANGED",
|
||||
"ALL_UNWHITELISTED",
|
||||
"ALL_WHITELIST_CHANGED",
|
||||
@@ -260,9 +265,16 @@ public class ForceAppStandbyTracker {
|
||||
* This is called when the foreground state changed for a UID.
|
||||
*/
|
||||
private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
|
||||
onUidForeground(uid, sender.isUidInForeground(uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the active/idle state changed for a UID.
|
||||
*/
|
||||
private void onUidActiveStateChanged(ForceAppStandbyTracker sender, int uid) {
|
||||
updateJobsForUid(uid);
|
||||
|
||||
if (sender.isInForeground(uid)) {
|
||||
if (sender.isUidActive(uid)) {
|
||||
unblockAlarmsForUid(uid);
|
||||
}
|
||||
}
|
||||
@@ -355,6 +367,14 @@ public class ForceAppStandbyTracker {
|
||||
*/
|
||||
public void unblockAlarmsForUidPackage(int uid, String packageName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a UID comes into the foreground or the background.
|
||||
*
|
||||
* @see #isUidInForeground(int)
|
||||
*/
|
||||
public void onUidForeground(int uid, boolean foreground) {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -404,8 +424,10 @@ public class ForceAppStandbyTracker {
|
||||
|
||||
try {
|
||||
mIActivityManager.registerUidObserver(new UidObserver(),
|
||||
ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
|
||||
| ActivityManager.UID_OBSERVER_ACTIVE,
|
||||
ActivityManager.UID_OBSERVER_GONE
|
||||
| ActivityManager.UID_OBSERVER_IDLE
|
||||
| ActivityManager.UID_OBSERVER_ACTIVE
|
||||
| ActivityManager.UID_OBSERVER_PROCSTATE,
|
||||
ActivityManager.PROCESS_STATE_UNKNOWN, null);
|
||||
mAppOpsService.startWatchingMode(TARGET_OP, null,
|
||||
new AppOpsWatcher());
|
||||
@@ -563,65 +585,77 @@ public class ForceAppStandbyTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a UID to {@link #mForegroundUids}.
|
||||
*/
|
||||
void uidToForeground(int uid) {
|
||||
synchronized (mLock) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return;
|
||||
}
|
||||
// TODO This can be optimized by calling indexOfKey and sharing the index for get and
|
||||
// put.
|
||||
if (mForegroundUids.get(uid)) {
|
||||
return;
|
||||
}
|
||||
mForegroundUids.put(uid, true);
|
||||
mHandler.notifyUidForegroundStateChanged(uid);
|
||||
private static boolean addUidToArray(SparseBooleanArray array, int uid) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return false;
|
||||
}
|
||||
if (array.get(uid)) {
|
||||
return false;
|
||||
}
|
||||
array.put(uid, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets false for a UID {@link #mForegroundUids}, or remove it when {@code remove} is true.
|
||||
*/
|
||||
void uidToBackground(int uid, boolean remove) {
|
||||
synchronized (mLock) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return;
|
||||
}
|
||||
// TODO This can be optimized by calling indexOfKey and sharing the index for get and
|
||||
// put.
|
||||
if (!mForegroundUids.get(uid)) {
|
||||
return;
|
||||
}
|
||||
if (remove) {
|
||||
mForegroundUids.delete(uid);
|
||||
} else {
|
||||
mForegroundUids.put(uid, false);
|
||||
}
|
||||
mHandler.notifyUidForegroundStateChanged(uid);
|
||||
private static boolean removeUidFromArray(SparseBooleanArray array, int uid, boolean remove) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return false;
|
||||
}
|
||||
if (!array.get(uid)) {
|
||||
return false;
|
||||
}
|
||||
if (remove) {
|
||||
array.delete(uid);
|
||||
} else {
|
||||
array.put(uid, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private final class UidObserver extends IUidObserver.Stub {
|
||||
@Override
|
||||
public void onUidStateChanged(int uid, int procState, long procStateSeq) {
|
||||
synchronized (mLock) {
|
||||
if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
|
||||
if (removeUidFromArray(mForegroundUids, uid, false)) {
|
||||
mHandler.notifyUidForegroundStateChanged(uid);
|
||||
}
|
||||
} else {
|
||||
if (addUidToArray(mForegroundUids, uid)) {
|
||||
mHandler.notifyUidForegroundStateChanged(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUidGone(int uid, boolean disabled) {
|
||||
uidToBackground(uid, /*remove=*/ true);
|
||||
removeUid(uid, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUidActive(int uid) {
|
||||
uidToForeground(uid);
|
||||
synchronized (mLock) {
|
||||
if (addUidToArray(mActiveUids, uid)) {
|
||||
mHandler.notifyUidActiveStateChanged(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUidIdle(int uid, boolean disabled) {
|
||||
// Just to avoid excessive memcpy, don't remove from the array in this case.
|
||||
uidToBackground(uid, /*remove=*/ false);
|
||||
removeUid(uid, false);
|
||||
}
|
||||
|
||||
private void removeUid(int uid, boolean remove) {
|
||||
synchronized (mLock) {
|
||||
if (removeUidFromArray(mActiveUids, uid, remove)) {
|
||||
mHandler.notifyUidActiveStateChanged(uid);
|
||||
}
|
||||
if (removeUidFromArray(mForegroundUids, uid, remove)) {
|
||||
mHandler.notifyUidForegroundStateChanged(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -695,22 +729,27 @@ public class ForceAppStandbyTracker {
|
||||
}
|
||||
|
||||
private class MyHandler extends Handler {
|
||||
private static final int MSG_UID_STATE_CHANGED = 1;
|
||||
private static final int MSG_RUN_ANY_CHANGED = 2;
|
||||
private static final int MSG_ALL_UNWHITELISTED = 3;
|
||||
private static final int MSG_ALL_WHITELIST_CHANGED = 4;
|
||||
private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
|
||||
private static final int MSG_FORCE_ALL_CHANGED = 6;
|
||||
private static final int MSG_USER_REMOVED = 7;
|
||||
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
|
||||
private static final int MSG_EXEMPT_CHANGED = 9;
|
||||
private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
|
||||
private static final int MSG_UID_FG_STATE_CHANGED = 1;
|
||||
private static final int MSG_RUN_ANY_CHANGED = 3;
|
||||
private static final int MSG_ALL_UNWHITELISTED = 4;
|
||||
private static final int MSG_ALL_WHITELIST_CHANGED = 5;
|
||||
private static final int MSG_TEMP_WHITELIST_CHANGED = 6;
|
||||
private static final int MSG_FORCE_ALL_CHANGED = 7;
|
||||
private static final int MSG_USER_REMOVED = 8;
|
||||
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
|
||||
private static final int MSG_EXEMPT_CHANGED = 10;
|
||||
|
||||
public MyHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
public void notifyUidActiveStateChanged(int uid) {
|
||||
obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyUidForegroundStateChanged(int uid) {
|
||||
obtainMessage(MSG_UID_STATE_CHANGED, uid, 0).sendToTarget();
|
||||
obtainMessage(MSG_UID_FG_STATE_CHANGED, uid, 0).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
|
||||
@@ -718,26 +757,32 @@ public class ForceAppStandbyTracker {
|
||||
}
|
||||
|
||||
public void notifyAllUnwhitelisted() {
|
||||
removeMessages(MSG_ALL_UNWHITELISTED);
|
||||
obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyAllWhitelistChanged() {
|
||||
removeMessages(MSG_ALL_WHITELIST_CHANGED);
|
||||
obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyTempWhitelistChanged() {
|
||||
removeMessages(MSG_TEMP_WHITELIST_CHANGED);
|
||||
obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyForceAllAppsStandbyChanged() {
|
||||
removeMessages(MSG_FORCE_ALL_CHANGED);
|
||||
obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyForcedAppStandbyFeatureFlagChanged() {
|
||||
removeMessages(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED);
|
||||
obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
public void notifyExemptChanged() {
|
||||
removeMessages(MSG_EXEMPT_CHANGED);
|
||||
obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
@@ -763,11 +808,18 @@ public class ForceAppStandbyTracker {
|
||||
|
||||
long start = mStatLogger.getTime();
|
||||
switch (msg.what) {
|
||||
case MSG_UID_STATE_CHANGED:
|
||||
case MSG_UID_ACTIVE_STATE_CHANGED:
|
||||
for (Listener l : cloneListeners()) {
|
||||
l.onUidActiveStateChanged(sender, msg.arg1);
|
||||
}
|
||||
mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
|
||||
return;
|
||||
|
||||
case MSG_UID_FG_STATE_CHANGED:
|
||||
for (Listener l : cloneListeners()) {
|
||||
l.onUidForegroundStateChanged(sender, msg.arg1);
|
||||
}
|
||||
mStatLogger.logDurationStat(Stats.UID_STATE_CHANGED, start);
|
||||
mStatLogger.logDurationStat(Stats.UID_FG_STATE_CHANGED, start);
|
||||
return;
|
||||
|
||||
case MSG_RUN_ANY_CHANGED:
|
||||
@@ -846,18 +898,23 @@ public class ForceAppStandbyTracker {
|
||||
mRunAnyRestrictedPackages.removeAt(i);
|
||||
}
|
||||
}
|
||||
for (int i = mForegroundUids.size() - 1; i >= 0; i--) {
|
||||
final int uid = mForegroundUids.keyAt(i);
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
|
||||
if (userId == removedUserId) {
|
||||
mForegroundUids.removeAt(i);
|
||||
}
|
||||
}
|
||||
cleanUpArrayForUser(mActiveUids, removedUserId);
|
||||
cleanUpArrayForUser(mForegroundUids, removedUserId);
|
||||
mExemptedPackages.remove(removedUserId);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanUpArrayForUser(SparseBooleanArray array, int removedUserId) {
|
||||
for (int i = array.size() - 1; i >= 0; i--) {
|
||||
final int uid = array.keyAt(i);
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
|
||||
if (userId == removedUserId) {
|
||||
array.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by device idle controller to update the power save whitelists.
|
||||
*/
|
||||
@@ -954,7 +1011,7 @@ public class ForceAppStandbyTracker {
|
||||
*/
|
||||
private boolean isRestricted(int uid, @NonNull String packageName,
|
||||
boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
|
||||
if (isInForeground(uid)) {
|
||||
if (isUidActive(uid)) {
|
||||
return false;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
@@ -981,6 +1038,22 @@ public class ForceAppStandbyTracker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether a UID is in active or not.
|
||||
*
|
||||
* Note this information is based on the UID proc state callback, meaning it's updated
|
||||
* asynchronously and may subtly be stale. If the fresh data is needed, use
|
||||
* {@link ActivityManagerInternal#getUidProcessState} instead.
|
||||
*/
|
||||
public boolean isUidActive(int uid) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return true;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
return mActiveUids.get(uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether a UID is in the foreground or not.
|
||||
*
|
||||
@@ -988,7 +1061,7 @@ public class ForceAppStandbyTracker {
|
||||
* asynchronously and may subtly be stale. If the fresh data is needed, use
|
||||
* {@link ActivityManagerInternal#getUidProcessState} instead.
|
||||
*/
|
||||
public boolean isInForeground(int uid) {
|
||||
public boolean isUidInForeground(int uid) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1062,17 +1135,12 @@ public class ForceAppStandbyTracker {
|
||||
pw.println(mIsPluggedIn);
|
||||
|
||||
pw.print(indent);
|
||||
pw.print("Foreground uids: [");
|
||||
pw.print("Active uids: ");
|
||||
dumpUids(pw, mActiveUids);
|
||||
|
||||
String sep = "";
|
||||
for (int i = 0; i < mForegroundUids.size(); i++) {
|
||||
if (mForegroundUids.valueAt(i)) {
|
||||
pw.print(sep);
|
||||
pw.print(UserHandle.formatUid(mForegroundUids.keyAt(i)));
|
||||
sep = " ";
|
||||
}
|
||||
}
|
||||
pw.println("]");
|
||||
pw.print(indent);
|
||||
pw.print("Foreground uids: ");
|
||||
dumpUids(pw, mForegroundUids);
|
||||
|
||||
pw.print(indent);
|
||||
pw.print("Whitelist appids: ");
|
||||
@@ -1114,6 +1182,20 @@ public class ForceAppStandbyTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpUids(PrintWriter pw, SparseBooleanArray array) {
|
||||
pw.print("[");
|
||||
|
||||
String sep = "";
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
if (array.valueAt(i)) {
|
||||
pw.print(sep);
|
||||
pw.print(UserHandle.formatUid(array.keyAt(i)));
|
||||
sep = " ";
|
||||
}
|
||||
}
|
||||
pw.println("]");
|
||||
}
|
||||
|
||||
public void dumpProto(ProtoOutputStream proto, long fieldId) {
|
||||
synchronized (mLock) {
|
||||
final long token = proto.start(fieldId);
|
||||
@@ -1125,6 +1207,13 @@ public class ForceAppStandbyTracker {
|
||||
mForceAllAppStandbyForSmallBattery);
|
||||
proto.write(ForceAppStandbyTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
|
||||
|
||||
for (int i = 0; i < mActiveUids.size(); i++) {
|
||||
if (mActiveUids.valueAt(i)) {
|
||||
proto.write(ForceAppStandbyTrackerProto.ACTIVE_UIDS,
|
||||
mActiveUids.keyAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mForegroundUids.size(); i++) {
|
||||
if (mForegroundUids.valueAt(i)) {
|
||||
proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
|
||||
|
||||
@@ -92,7 +92,7 @@ public final class BackgroundJobsController extends StateController {
|
||||
jobStatus.printUniqueId(pw);
|
||||
pw.print(" from ");
|
||||
UserHandle.formatUid(pw, uid);
|
||||
pw.print(mForceAppStandbyTracker.isInForeground(uid) ? " foreground" : " background");
|
||||
pw.print(mForceAppStandbyTracker.isUidActive(uid) ? " active" : " idle");
|
||||
if (mForceAppStandbyTracker.isUidPowerSaveWhitelisted(uid) ||
|
||||
mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(uid)) {
|
||||
pw.print(", whitelisted");
|
||||
@@ -136,7 +136,7 @@ public final class BackgroundJobsController extends StateController {
|
||||
proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
|
||||
|
||||
proto.write(TrackedJob.IS_IN_FOREGROUND,
|
||||
mForceAppStandbyTracker.isInForeground(sourceUid));
|
||||
mForceAppStandbyTracker.isUidActive(sourceUid));
|
||||
proto.write(TrackedJob.IS_WHITELISTED,
|
||||
mForceAppStandbyTracker.isUidPowerSaveWhitelisted(sourceUid) ||
|
||||
mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(sourceUid));
|
||||
|
||||
@@ -54,7 +54,6 @@ import android.os.PowerSaveState;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
@@ -64,7 +63,6 @@ import android.util.Pair;
|
||||
|
||||
import com.android.internal.app.IAppOpsCallback;
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.server.ForceAppStandbyTracker.Listener;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -83,6 +81,12 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Tests for {@link ForceAppStandbyTracker}
|
||||
*
|
||||
* Run with:
|
||||
atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ForceAppStandbyTrackerTest {
|
||||
@@ -236,7 +240,8 @@ public class ForceAppStandbyTrackerTest {
|
||||
verify(mMockIActivityManager).registerUidObserver(
|
||||
uidObserverArgumentCaptor.capture(),
|
||||
eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
|
||||
| ActivityManager.UID_OBSERVER_ACTIVE),
|
||||
| ActivityManager.UID_OBSERVER_ACTIVE
|
||||
| ActivityManager.UID_OBSERVER_PROCSTATE),
|
||||
eq(ActivityManager.PROCESS_STATE_UNKNOWN),
|
||||
isNull());
|
||||
verify(mMockIAppOpsService).startWatchingMode(
|
||||
@@ -333,23 +338,23 @@ public class ForceAppStandbyTrackerTest {
|
||||
mPowerSaveMode = true;
|
||||
mPowerSaveObserver.accept(getPowerSaveState());
|
||||
|
||||
assertFalse(instance.isInForeground(UID_1));
|
||||
assertFalse(instance.isInForeground(UID_2));
|
||||
assertTrue(instance.isInForeground(Process.SYSTEM_UID));
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
mIUidObserver.onUidActive(UID_1);
|
||||
areRestricted(instance, UID_1, PACKAGE_1, NONE);
|
||||
areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
|
||||
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
|
||||
assertTrue(instance.isInForeground(UID_1));
|
||||
assertFalse(instance.isInForeground(UID_2));
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
|
||||
mIUidObserver.onUidGone(UID_1, /*disable=*/ false);
|
||||
areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
|
||||
areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
|
||||
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
|
||||
assertFalse(instance.isInForeground(UID_1));
|
||||
assertFalse(instance.isInForeground(UID_2));
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
|
||||
mIUidObserver.onUidActive(UID_1);
|
||||
areRestricted(instance, UID_1, PACKAGE_1, NONE);
|
||||
@@ -360,8 +365,8 @@ public class ForceAppStandbyTrackerTest {
|
||||
areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
|
||||
areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
|
||||
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
|
||||
assertFalse(instance.isInForeground(UID_1));
|
||||
assertFalse(instance.isInForeground(UID_2));
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
|
||||
// Toggle the app ops.
|
||||
mPowerSaveMode = false;
|
||||
@@ -455,6 +460,88 @@ public class ForceAppStandbyTrackerTest {
|
||||
assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_10_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUidStateForeground() throws Exception {
|
||||
final ForceAppStandbyTrackerTestable instance = newInstance();
|
||||
callStart(instance);
|
||||
|
||||
mIUidObserver.onUidActive(UID_1);
|
||||
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertFalse(instance.isUidInForeground(UID_1));
|
||||
assertFalse(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
|
||||
mIUidObserver.onUidStateChanged(UID_2,
|
||||
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0);
|
||||
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertFalse(instance.isUidInForeground(UID_1));
|
||||
assertTrue(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
|
||||
mIUidObserver.onUidStateChanged(UID_1,
|
||||
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
|
||||
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertTrue(instance.isUidInForeground(UID_1));
|
||||
assertTrue(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
mIUidObserver.onUidGone(UID_1, true);
|
||||
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertFalse(instance.isUidInForeground(UID_1));
|
||||
assertTrue(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
mIUidObserver.onUidIdle(UID_2, true);
|
||||
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertFalse(instance.isUidInForeground(UID_1));
|
||||
assertFalse(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
mIUidObserver.onUidStateChanged(UID_1,
|
||||
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0);
|
||||
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertTrue(instance.isUidInForeground(UID_1));
|
||||
assertFalse(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
|
||||
mIUidObserver.onUidStateChanged(UID_1,
|
||||
ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0);
|
||||
|
||||
assertFalse(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_2));
|
||||
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
|
||||
|
||||
assertFalse(instance.isUidInForeground(UID_1));
|
||||
assertFalse(instance.isUidInForeground(UID_2));
|
||||
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExempt() throws Exception {
|
||||
final ForceAppStandbyTrackerTestable instance = newInstance();
|
||||
@@ -953,8 +1040,8 @@ public class ForceAppStandbyTrackerTest {
|
||||
setAppOps(UID_2, PACKAGE_2, true);
|
||||
setAppOps(UID_10_2, PACKAGE_2, true);
|
||||
|
||||
assertTrue(instance.isInForeground(UID_1));
|
||||
assertTrue(instance.isInForeground(UID_10_1));
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertTrue(instance.isUidActive(UID_10_1));
|
||||
|
||||
assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
|
||||
assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
|
||||
@@ -965,8 +1052,8 @@ public class ForceAppStandbyTrackerTest {
|
||||
|
||||
waitUntilMainHandlerDrain();
|
||||
|
||||
assertTrue(instance.isInForeground(UID_1));
|
||||
assertFalse(instance.isInForeground(UID_10_1));
|
||||
assertTrue(instance.isUidActive(UID_1));
|
||||
assertFalse(instance.isUidActive(UID_10_1));
|
||||
|
||||
assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
|
||||
assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
|
||||
|
||||
Reference in New Issue
Block a user