Merge "Reland "Track per-process freezable state in BroadcastQueue."" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
39ee232765
@@ -17311,6 +17311,12 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onProcessFreezableChangedLocked(ProcessRecord app) {
|
||||||
|
if (mEnableModernQueue) {
|
||||||
|
mBroadcastQueues[0].onProcessFreezableChangedLocked(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public final class LocalService extends ActivityManagerInternal
|
public final class LocalService extends ActivityManagerInternal
|
||||||
implements ActivityManagerLocal {
|
implements ActivityManagerLocal {
|
||||||
@@ -19022,25 +19028,27 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||||||
// too quickly in parallel below
|
// too quickly in parallel below
|
||||||
pingCount.incrementAndGet();
|
pingCount.incrementAndGet();
|
||||||
|
|
||||||
synchronized (mProcLock) {
|
synchronized (ActivityManagerService.this) {
|
||||||
final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
|
synchronized (mProcLock) {
|
||||||
mProcessList.getProcessNamesLOSP().getMap();
|
final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
|
||||||
final int numProc = pmap.size();
|
mProcessList.getProcessNamesLOSP().getMap();
|
||||||
for (int iProc = 0; iProc < numProc; iProc++) {
|
final int numProc = pmap.size();
|
||||||
final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
|
for (int iProc = 0; iProc < numProc; iProc++) {
|
||||||
for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
|
final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
|
||||||
final ProcessRecord app = apps.valueAt(iApp);
|
for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
|
||||||
final IApplicationThread thread = app.getOnewayThread();
|
final ProcessRecord app = apps.valueAt(iApp);
|
||||||
if (thread != null) {
|
final IApplicationThread thread = app.getOnewayThread();
|
||||||
mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
|
if (thread != null) {
|
||||||
CachedAppOptimizer.UNFREEZE_REASON_PING);
|
mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
|
||||||
pingCount.incrementAndGet();
|
CachedAppOptimizer.UNFREEZE_REASON_PING);
|
||||||
try {
|
pingCount.incrementAndGet();
|
||||||
thread.schedulePing(pongCallback);
|
try {
|
||||||
} catch (RemoteException ignored) {
|
thread.schedulePing(pongCallback);
|
||||||
// When we failed to ping remote process, pretend as
|
} catch (RemoteException ignored) {
|
||||||
// if we received the expected pong
|
// When we failed to ping remote process, pretend as
|
||||||
pongCallback.sendResult(null);
|
// if we received the expected pong
|
||||||
|
pongCallback.sendResult(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ class BroadcastProcessQueue {
|
|||||||
private boolean mLastDeferredStates;
|
private boolean mLastDeferredStates;
|
||||||
|
|
||||||
private boolean mUidForeground;
|
private boolean mUidForeground;
|
||||||
private boolean mUidCached;
|
private boolean mProcessFreezable;
|
||||||
private boolean mProcessInstrumented;
|
private boolean mProcessInstrumented;
|
||||||
private boolean mProcessPersistent;
|
private boolean mProcessPersistent;
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ class BroadcastProcessQueue {
|
|||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public boolean setProcessAndUidState(@Nullable ProcessRecord app, boolean uidForeground,
|
public boolean setProcessAndUidState(@Nullable ProcessRecord app, boolean uidForeground,
|
||||||
boolean uidCached) {
|
boolean processFreezable) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
|
||||||
// Since we may have just changed our PID, invalidate cached strings
|
// Since we may have just changed our PID, invalidate cached strings
|
||||||
@@ -449,13 +449,13 @@ class BroadcastProcessQueue {
|
|||||||
|
|
||||||
boolean didSomething = false;
|
boolean didSomething = false;
|
||||||
if (app != null) {
|
if (app != null) {
|
||||||
didSomething |= setUidCached(uidCached);
|
|
||||||
didSomething |= setUidForeground(uidForeground);
|
didSomething |= setUidForeground(uidForeground);
|
||||||
|
didSomething |= setProcessFreezable(processFreezable);
|
||||||
didSomething |= setProcessInstrumented(app.getActiveInstrumentation() != null);
|
didSomething |= setProcessInstrumented(app.getActiveInstrumentation() != null);
|
||||||
didSomething |= setProcessPersistent(app.isPersistent());
|
didSomething |= setProcessPersistent(app.isPersistent());
|
||||||
} else {
|
} else {
|
||||||
didSomething |= setUidCached(uidCached);
|
|
||||||
didSomething |= setUidForeground(false);
|
didSomething |= setUidForeground(false);
|
||||||
|
didSomething |= setProcessFreezable(false);
|
||||||
didSomething |= setProcessInstrumented(false);
|
didSomething |= setProcessInstrumented(false);
|
||||||
didSomething |= setProcessPersistent(false);
|
didSomething |= setProcessPersistent(false);
|
||||||
}
|
}
|
||||||
@@ -479,13 +479,13 @@ class BroadcastProcessQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update if this process is in the "cached" state, typically signaling that
|
* Update if this process is in the "freezable" state, typically signaling that
|
||||||
* broadcast dispatch should be paused or delayed.
|
* broadcast dispatch should be paused or delayed.
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
private boolean setUidCached(boolean uidCached) {
|
private boolean setProcessFreezable(boolean freezable) {
|
||||||
if (mUidCached != uidCached) {
|
if (mProcessFreezable != freezable) {
|
||||||
mUidCached = uidCached;
|
mProcessFreezable = freezable;
|
||||||
invalidateRunnableAt();
|
invalidateRunnableAt();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -1150,7 +1150,7 @@ class BroadcastProcessQueue {
|
|||||||
} else if (mCountManifest > 0) {
|
} else if (mCountManifest > 0) {
|
||||||
mRunnableAt = runnableAt;
|
mRunnableAt = runnableAt;
|
||||||
mRunnableAtReason = REASON_CONTAINS_MANIFEST;
|
mRunnableAtReason = REASON_CONTAINS_MANIFEST;
|
||||||
} else if (mUidCached) {
|
} else if (mProcessFreezable) {
|
||||||
if (r.deferUntilActive) {
|
if (r.deferUntilActive) {
|
||||||
// All enqueued broadcasts are deferrable, defer
|
// All enqueued broadcasts are deferrable, defer
|
||||||
if (mCountDeferred == mCountEnqueued) {
|
if (mCountDeferred == mCountEnqueued) {
|
||||||
@@ -1220,7 +1220,7 @@ class BroadcastProcessQueue {
|
|||||||
// When all we have pending is deferred broadcasts, and we're cached,
|
// When all we have pending is deferred broadcasts, and we're cached,
|
||||||
// then we want everything to be marked deferred
|
// then we want everything to be marked deferred
|
||||||
final boolean wantDeferredStates = (mCountDeferred > 0)
|
final boolean wantDeferredStates = (mCountDeferred > 0)
|
||||||
&& (mCountDeferred == mCountEnqueued) && mUidCached;
|
&& (mCountDeferred == mCountEnqueued) && mProcessFreezable;
|
||||||
|
|
||||||
if (mLastDeferredStates != wantDeferredStates) {
|
if (mLastDeferredStates != wantDeferredStates) {
|
||||||
mLastDeferredStates = wantDeferredStates;
|
mLastDeferredStates = wantDeferredStates;
|
||||||
@@ -1407,9 +1407,9 @@ class BroadcastProcessQueue {
|
|||||||
if (mUidForeground) {
|
if (mUidForeground) {
|
||||||
sb.append("FG");
|
sb.append("FG");
|
||||||
}
|
}
|
||||||
if (mUidCached) {
|
if (mProcessFreezable) {
|
||||||
if (sb.length() > 0) sb.append("|");
|
if (sb.length() > 0) sb.append("|");
|
||||||
sb.append("CACHED");
|
sb.append("FRZ");
|
||||||
}
|
}
|
||||||
if (mProcessInstrumented) {
|
if (mProcessInstrumented) {
|
||||||
if (sb.length() > 0) sb.append("|");
|
if (sb.length() > 0) sb.append("|");
|
||||||
|
|||||||
@@ -173,6 +173,13 @@ public abstract class BroadcastQueue {
|
|||||||
@GuardedBy("mService")
|
@GuardedBy("mService")
|
||||||
public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app);
|
public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal from OS internals that the given process is in a freezable state and will be
|
||||||
|
* frozen soon after.
|
||||||
|
*/
|
||||||
|
@GuardedBy("mService")
|
||||||
|
public abstract void onProcessFreezableChangedLocked(@NonNull ProcessRecord app);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal from OS internals that the given package (or some subset of that
|
* Signal from OS internals that the given package (or some subset of that
|
||||||
* package) has been disabled or uninstalled, and that any pending
|
* package) has been disabled or uninstalled, and that any pending
|
||||||
|
|||||||
@@ -466,6 +466,10 @@ public class BroadcastQueueImpl extends BroadcastQueue {
|
|||||||
skipCurrentOrPendingReceiverLocked(app);
|
skipCurrentOrPendingReceiverLocked(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onProcessFreezableChangedLocked(ProcessRecord app) {
|
||||||
|
// Not supported; ignore
|
||||||
|
}
|
||||||
|
|
||||||
public boolean sendPendingBroadcastsLocked(ProcessRecord app)
|
public boolean sendPendingBroadcastsLocked(ProcessRecord app)
|
||||||
throws BroadcastDeliveryFailedException {
|
throws BroadcastDeliveryFailedException {
|
||||||
boolean didSomething = false;
|
boolean didSomething = false;
|
||||||
|
|||||||
@@ -232,16 +232,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
@GuardedBy("mService")
|
@GuardedBy("mService")
|
||||||
private final SparseBooleanArray mUidForeground = new SparseBooleanArray();
|
private final SparseBooleanArray mUidForeground = new SparseBooleanArray();
|
||||||
|
|
||||||
/**
|
|
||||||
* Map from UID to its last known "cached" state.
|
|
||||||
* <p>
|
|
||||||
* We manually maintain this data structure since the lifecycle of
|
|
||||||
* {@link ProcessRecord} and {@link BroadcastProcessQueue} can be
|
|
||||||
* mismatched.
|
|
||||||
*/
|
|
||||||
@GuardedBy("mService")
|
|
||||||
private final SparseBooleanArray mUidCached = new SparseBooleanArray();
|
|
||||||
|
|
||||||
private final BroadcastConstants mConstants;
|
private final BroadcastConstants mConstants;
|
||||||
private final BroadcastConstants mFgConstants;
|
private final BroadcastConstants mFgConstants;
|
||||||
private final BroadcastConstants mBgConstants;
|
private final BroadcastConstants mBgConstants;
|
||||||
@@ -258,6 +248,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
private static final int MSG_BG_ACTIVITY_START_TIMEOUT = 4;
|
private static final int MSG_BG_ACTIVITY_START_TIMEOUT = 4;
|
||||||
private static final int MSG_CHECK_HEALTH = 5;
|
private static final int MSG_CHECK_HEALTH = 5;
|
||||||
private static final int MSG_CHECK_PENDING_COLD_START_VALIDITY = 6;
|
private static final int MSG_CHECK_PENDING_COLD_START_VALIDITY = 6;
|
||||||
|
private static final int MSG_PROCESS_FREEZABLE_CHANGED = 7;
|
||||||
|
|
||||||
private void enqueueUpdateRunningList() {
|
private void enqueueUpdateRunningList() {
|
||||||
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
|
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
|
||||||
@@ -298,6 +289,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
checkPendingColdStartValidity();
|
checkPendingColdStartValidity();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case MSG_PROCESS_FREEZABLE_CHANGED: {
|
||||||
|
synchronized (mService) {
|
||||||
|
refreshProcessQueueLocked((ProcessRecord) msg.obj);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -672,6 +669,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
enqueueUpdateRunningList();
|
enqueueUpdateRunningList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProcessFreezableChangedLocked(@NonNull ProcessRecord app) {
|
||||||
|
mLocalHandler.removeMessages(MSG_PROCESS_FREEZABLE_CHANGED, app);
|
||||||
|
mLocalHandler.sendMessage(mHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app) {
|
public int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app) {
|
||||||
final BroadcastProcessQueue queue = getProcessQueue(app);
|
final BroadcastProcessQueue queue = getProcessQueue(app);
|
||||||
@@ -1465,7 +1468,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
};
|
};
|
||||||
broadcastPredicate = BROADCAST_PREDICATE_ANY;
|
broadcastPredicate = BROADCAST_PREDICATE_ANY;
|
||||||
|
|
||||||
cleanupUserStateLocked(mUidCached, userId);
|
|
||||||
cleanupUserStateLocked(mUidForeground, userId);
|
cleanupUserStateLocked(mUidForeground, userId);
|
||||||
}
|
}
|
||||||
return forEachMatchingBroadcast(queuePredicate, broadcastPredicate,
|
return forEachMatchingBroadcast(queuePredicate, broadcastPredicate,
|
||||||
@@ -1611,22 +1613,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
}, ActivityManager.UID_OBSERVER_PROCSTATE,
|
}, ActivityManager.UID_OBSERVER_PROCSTATE,
|
||||||
ActivityManager.PROCESS_STATE_TOP, "android");
|
ActivityManager.PROCESS_STATE_TOP, "android");
|
||||||
|
|
||||||
mService.registerUidObserver(new UidObserver() {
|
|
||||||
@Override
|
|
||||||
public void onUidStateChanged(int uid, int procState, long procStateSeq,
|
|
||||||
int capability) {
|
|
||||||
synchronized (mService) {
|
|
||||||
if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
|
|
||||||
mUidCached.put(uid, true);
|
|
||||||
} else {
|
|
||||||
mUidCached.delete(uid);
|
|
||||||
}
|
|
||||||
refreshProcessQueuesLocked(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, ActivityManager.UID_OBSERVER_PROCSTATE,
|
|
||||||
ActivityManager.PROCESS_STATE_LAST_ACTIVITY, "android");
|
|
||||||
|
|
||||||
// Kick off periodic health checks
|
// Kick off periodic health checks
|
||||||
mLocalHandler.sendEmptyMessage(MSG_CHECK_HEALTH);
|
mLocalHandler.sendEmptyMessage(MSG_CHECK_HEALTH);
|
||||||
}
|
}
|
||||||
@@ -1814,10 +1800,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
// warm via this operation, we're going to immediately promote it to
|
// warm via this operation, we're going to immediately promote it to
|
||||||
// be running, and any side effect of this operation will then apply
|
// be running, and any side effect of this operation will then apply
|
||||||
// after it's finished and is returned to the runnable list.
|
// after it's finished and is returned to the runnable list.
|
||||||
queue.setProcessAndUidState(
|
final ProcessRecord app = mService.getProcessRecordLocked(queue.processName, queue.uid);
|
||||||
mService.getProcessRecordLocked(queue.processName, queue.uid),
|
queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
|
||||||
mUidForeground.get(queue.uid, false),
|
isProcessFreezable(app));
|
||||||
mUidCached.get(queue.uid, false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1829,11 +1814,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
private void setQueueProcess(@NonNull BroadcastProcessQueue queue,
|
private void setQueueProcess(@NonNull BroadcastProcessQueue queue,
|
||||||
@Nullable ProcessRecord app) {
|
@Nullable ProcessRecord app) {
|
||||||
if (queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
|
if (queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
|
||||||
mUidCached.get(queue.uid, false))) {
|
isProcessFreezable(app))) {
|
||||||
updateRunnableList(queue);
|
updateRunnableList(queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mService")
|
||||||
|
private boolean isProcessFreezable(@Nullable ProcessRecord app) {
|
||||||
|
if (app == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
synchronized (mService.mProcLock) {
|
||||||
|
return app.mOptRecord.isPendingFreeze() || app.mOptRecord.isFrozen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the process queues with the latest process state so that runnableAt
|
* Refresh the process queues with the latest process state so that runnableAt
|
||||||
* can be updated.
|
* can be updated.
|
||||||
@@ -1850,6 +1845,20 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
enqueueUpdateRunningList();
|
enqueueUpdateRunningList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the process queue corresponding to {@code app} with the latest process state
|
||||||
|
* so that runnableAt can be updated.
|
||||||
|
*/
|
||||||
|
@GuardedBy("mService")
|
||||||
|
private void refreshProcessQueueLocked(@NonNull ProcessRecord app) {
|
||||||
|
final BroadcastProcessQueue queue = getProcessQueue(app.processName, app.uid);
|
||||||
|
if (queue == null || queue.app == null || queue.app.getPid() != app.getPid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setQueueProcess(queue, queue.app);
|
||||||
|
enqueueUpdateRunningList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inform other parts of OS that the given broadcast queue has started
|
* Inform other parts of OS that the given broadcast queue has started
|
||||||
* running, typically for internal bookkeeping.
|
* running, typically for internal bookkeeping.
|
||||||
@@ -2176,12 +2185,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
ipw.decreaseIndent();
|
ipw.decreaseIndent();
|
||||||
ipw.println();
|
ipw.println();
|
||||||
|
|
||||||
ipw.println("Cached UIDs:");
|
|
||||||
ipw.increaseIndent();
|
|
||||||
ipw.println(mUidCached);
|
|
||||||
ipw.decreaseIndent();
|
|
||||||
ipw.println();
|
|
||||||
|
|
||||||
ipw.println("Foreground UIDs:");
|
ipw.println("Foreground UIDs:");
|
||||||
ipw.increaseIndent();
|
ipw.increaseIndent();
|
||||||
ipw.println(mUidForeground);
|
ipw.println(mUidForeground);
|
||||||
|
|||||||
@@ -1402,6 +1402,7 @@ public final class CachedAppOptimizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
reportProcessFreezableChangedLocked(app);
|
||||||
app.mOptRecord.setLastUsedTimeout(delayMillis);
|
app.mOptRecord.setLastUsedTimeout(delayMillis);
|
||||||
mFreezeHandler.sendMessageDelayed(
|
mFreezeHandler.sendMessageDelayed(
|
||||||
mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
|
mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
|
||||||
@@ -1440,6 +1441,7 @@ public final class CachedAppOptimizer {
|
|||||||
uidRec.setFrozen(false);
|
uidRec.setFrozen(false);
|
||||||
postUidFrozenMessage(uidRec.getUid(), false);
|
postUidFrozenMessage(uidRec.getUid(), false);
|
||||||
}
|
}
|
||||||
|
reportProcessFreezableChangedLocked(app);
|
||||||
|
|
||||||
opt.setFreezerOverride(false);
|
opt.setFreezerOverride(false);
|
||||||
if (pid == 0 || !opt.isFrozen()) {
|
if (pid == 0 || !opt.isFrozen()) {
|
||||||
@@ -2121,6 +2123,11 @@ public final class CachedAppOptimizer {
|
|||||||
0, uidObj));
|
0, uidObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mAm")
|
||||||
|
private void reportProcessFreezableChangedLocked(ProcessRecord app) {
|
||||||
|
mAm.onProcessFreezableChangedLocked(app);
|
||||||
|
}
|
||||||
|
|
||||||
private final class FreezeHandler extends Handler implements
|
private final class FreezeHandler extends Handler implements
|
||||||
ProcLocksReader.ProcLocksReaderCallback {
|
ProcLocksReader.ProcLocksReaderCallback {
|
||||||
private FreezeHandler() {
|
private FreezeHandler() {
|
||||||
@@ -2130,7 +2137,7 @@ public final class CachedAppOptimizer {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case SET_FROZEN_PROCESS_MSG:
|
case SET_FROZEN_PROCESS_MSG: {
|
||||||
ProcessRecord proc = (ProcessRecord) msg.obj;
|
ProcessRecord proc = (ProcessRecord) msg.obj;
|
||||||
synchronized (mAm) {
|
synchronized (mAm) {
|
||||||
freezeProcess(proc);
|
freezeProcess(proc);
|
||||||
@@ -2140,8 +2147,8 @@ public final class CachedAppOptimizer {
|
|||||||
removeMessages(DEADLOCK_WATCHDOG_MSG);
|
removeMessages(DEADLOCK_WATCHDOG_MSG);
|
||||||
sendEmptyMessageDelayed(DEADLOCK_WATCHDOG_MSG, FREEZE_DEADLOCK_TIMEOUT_MS);
|
sendEmptyMessageDelayed(DEADLOCK_WATCHDOG_MSG, FREEZE_DEADLOCK_TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
case REPORT_UNFREEZE_MSG:
|
case REPORT_UNFREEZE_MSG: {
|
||||||
int pid = msg.arg1;
|
int pid = msg.arg1;
|
||||||
int frozenDuration = msg.arg2;
|
int frozenDuration = msg.arg2;
|
||||||
Pair<String, Integer> obj = (Pair<String, Integer>) msg.obj;
|
Pair<String, Integer> obj = (Pair<String, Integer>) msg.obj;
|
||||||
@@ -2149,13 +2156,13 @@ public final class CachedAppOptimizer {
|
|||||||
int reason = obj.second;
|
int reason = obj.second;
|
||||||
|
|
||||||
reportUnfreeze(pid, frozenDuration, processName, reason);
|
reportUnfreeze(pid, frozenDuration, processName, reason);
|
||||||
break;
|
} break;
|
||||||
case UID_FROZEN_STATE_CHANGED_MSG:
|
case UID_FROZEN_STATE_CHANGED_MSG: {
|
||||||
final boolean frozen = (msg.arg1 == 1);
|
final boolean frozen = (msg.arg1 == 1);
|
||||||
final int uid = (int) msg.obj;
|
final int uid = (int) msg.obj;
|
||||||
reportOneUidFrozenStateChanged(uid, frozen);
|
reportOneUidFrozenStateChanged(uid, frozen);
|
||||||
break;
|
} break;
|
||||||
case DEADLOCK_WATCHDOG_MSG:
|
case DEADLOCK_WATCHDOG_MSG: {
|
||||||
try {
|
try {
|
||||||
// post-check to prevent deadlock
|
// post-check to prevent deadlock
|
||||||
if (DEBUG_FREEZER) {
|
if (DEBUG_FREEZER) {
|
||||||
@@ -2165,7 +2172,7 @@ public final class CachedAppOptimizer {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Slog.w(TAG_AM, "Unable to check file locks");
|
Slog.w(TAG_AM, "Unable to check file locks");
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1197,6 +1197,9 @@ class ProcessRecord implements WindowProcessListener {
|
|||||||
"Killing " + toShortString() + " (adj " + mState.getSetAdj()
|
"Killing " + toShortString() + " (adj " + mState.getSetAdj()
|
||||||
+ "): " + reason, info.uid);
|
+ "): " + reason, info.uid);
|
||||||
}
|
}
|
||||||
|
// Since the process is getting killed, reset the freezable related state.
|
||||||
|
mOptRecord.setPendingFreeze(false);
|
||||||
|
mOptRecord.setFrozen(false);
|
||||||
if (mPid > 0) {
|
if (mPid > 0) {
|
||||||
mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
|
mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
|
||||||
EventLog.writeEvent(EventLogTags.AM_KILL,
|
EventLog.writeEvent(EventLogTags.AM_KILL,
|
||||||
|
|||||||
@@ -410,9 +410,9 @@ public final class BroadcastQueueModernImplTest {
|
|||||||
List.of(makeMockRegisteredReceiver()), false);
|
List.of(makeMockRegisteredReceiver()), false);
|
||||||
enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
|
enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
|
||||||
|
|
||||||
queue.setProcessAndUidState(null, false, false);
|
queue.setProcessAndUidState(mProcess, false, false);
|
||||||
final long notCachedRunnableAt = queue.getRunnableAt();
|
final long notCachedRunnableAt = queue.getRunnableAt();
|
||||||
queue.setProcessAndUidState(null, false, true);
|
queue.setProcessAndUidState(mProcess, false, true);
|
||||||
final long cachedRunnableAt = queue.getRunnableAt();
|
final long cachedRunnableAt = queue.getRunnableAt();
|
||||||
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
|
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
|
||||||
assertFalse(queue.isRunnable());
|
assertFalse(queue.isRunnable());
|
||||||
@@ -437,9 +437,9 @@ public final class BroadcastQueueModernImplTest {
|
|||||||
List.of(makeMockRegisteredReceiver()), false);
|
List.of(makeMockRegisteredReceiver()), false);
|
||||||
enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
|
enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
|
||||||
|
|
||||||
queue.setProcessAndUidState(null, false, false);
|
queue.setProcessAndUidState(mProcess, false, false);
|
||||||
final long notCachedRunnableAt = queue.getRunnableAt();
|
final long notCachedRunnableAt = queue.getRunnableAt();
|
||||||
queue.setProcessAndUidState(null, false, true);
|
queue.setProcessAndUidState(mProcess, false, true);
|
||||||
final long cachedRunnableAt = queue.getRunnableAt();
|
final long cachedRunnableAt = queue.getRunnableAt();
|
||||||
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
|
assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
|
||||||
assertTrue(queue.isRunnable());
|
assertTrue(queue.isRunnable());
|
||||||
|
|||||||
@@ -421,6 +421,12 @@ public class BroadcastQueueTest {
|
|||||||
UserHandle.USER_SYSTEM);
|
UserHandle.USER_SYSTEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProcessRecord makeActiveProcessRecord(String packageName, String processName)
|
||||||
|
throws Exception {
|
||||||
|
return makeActiveProcessRecord(packageName, processName, ProcessBehavior.NORMAL,
|
||||||
|
UserHandle.USER_SYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
private ProcessRecord makeActiveProcessRecord(String packageName,
|
private ProcessRecord makeActiveProcessRecord(String packageName,
|
||||||
ProcessBehavior behavior) throws Exception {
|
ProcessBehavior behavior) throws Exception {
|
||||||
return makeActiveProcessRecord(packageName, packageName, behavior, UserHandle.USER_SYSTEM);
|
return makeActiveProcessRecord(packageName, packageName, behavior, UserHandle.USER_SYSTEM);
|
||||||
@@ -623,6 +629,11 @@ public class BroadcastQueueTest {
|
|||||||
BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
|
BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen) {
|
||||||
|
app.mOptRecord.setPendingFreeze(pendingFreeze);
|
||||||
|
app.mOptRecord.setFrozen(frozen);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertHealth() {
|
private void assertHealth() {
|
||||||
if (mImpl == Impl.MODERN) {
|
if (mImpl == Impl.MODERN) {
|
||||||
// If this fails, it'll throw a clear reason message
|
// If this fails, it'll throw a clear reason message
|
||||||
@@ -1769,12 +1780,10 @@ public class BroadcastQueueTest {
|
|||||||
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
|
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
|
||||||
final ProcessRecord receiverOrangeApp = makeActiveProcessRecord(PACKAGE_ORANGE);
|
final ProcessRecord receiverOrangeApp = makeActiveProcessRecord(PACKAGE_ORANGE);
|
||||||
|
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_GREEN),
|
setProcessFreezable(receiverGreenApp, true, false);
|
||||||
ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 0,
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
setProcessFreezable(receiverBlueApp, false, true);
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_BLUE),
|
mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
|
||||||
ActivityManager.PROCESS_STATE_CACHED_EMPTY, 0,
|
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
|
||||||
|
|
||||||
final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
|
final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
|
||||||
final BroadcastOptions opts = BroadcastOptions.makeBasic()
|
final BroadcastOptions opts = BroadcastOptions.makeBasic()
|
||||||
@@ -1818,16 +1827,14 @@ public class BroadcastQueueTest {
|
|||||||
eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any());
|
eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any());
|
||||||
|
|
||||||
// Shift blue to be active and confirm that deferred broadcast is delivered
|
// Shift blue to be active and confirm that deferred broadcast is delivered
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_BLUE),
|
setProcessFreezable(receiverBlueApp, false, false);
|
||||||
ActivityManager.PROCESS_STATE_TOP, 0,
|
mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, timeTick);
|
verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, timeTick);
|
||||||
|
|
||||||
// Shift green to be active and confirm that deferred broadcast is delivered
|
// Shift green to be active and confirm that deferred broadcast is delivered
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_GREEN),
|
setProcessFreezable(receiverGreenApp, false, false);
|
||||||
ActivityManager.PROCESS_STATE_SERVICE, 0,
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, timeTick);
|
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, timeTick);
|
||||||
}
|
}
|
||||||
@@ -2252,15 +2259,12 @@ public class BroadcastQueueTest {
|
|||||||
final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
|
final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
|
||||||
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
|
final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
|
||||||
|
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_GREEN),
|
setProcessFreezable(receiverGreenApp, true, true);
|
||||||
ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 0,
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
setProcessFreezable(receiverBlueApp, true, false);
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_BLUE),
|
mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
|
||||||
ActivityManager.PROCESS_STATE_CACHED_EMPTY, 0,
|
setProcessFreezable(receiverYellowApp, false, false);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
mQueue.onProcessFreezableChangedLocked(receiverYellowApp);
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_YELLOW),
|
|
||||||
ActivityManager.PROCESS_STATE_SERVICE, 0,
|
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
|
||||||
|
|
||||||
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||||
final BroadcastOptions opts = BroadcastOptions.makeBasic()
|
final BroadcastOptions opts = BroadcastOptions.makeBasic()
|
||||||
@@ -2283,13 +2287,50 @@ public class BroadcastQueueTest {
|
|||||||
verifyScheduleRegisteredReceiver(times(1), receiverYellowApp, airplane);
|
verifyScheduleRegisteredReceiver(times(1), receiverYellowApp, airplane);
|
||||||
|
|
||||||
// Shift green to be active and confirm that deferred broadcast is delivered
|
// Shift green to be active and confirm that deferred broadcast is delivered
|
||||||
mUidCachedStateObserver.onUidStateChanged(getUidForPackage(PACKAGE_GREEN),
|
setProcessFreezable(receiverGreenApp, false, false);
|
||||||
ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
|
||||||
ActivityManager.PROCESS_CAPABILITY_NONE);
|
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);
|
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify broadcasts to a runtime receiver in cached process is deferred even when a different
|
||||||
|
* process in the same package is not cached.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDeferralPolicy_UntilActive_WithMultiProcessUid() throws Exception {
|
||||||
|
// Legacy stack doesn't support deferral
|
||||||
|
Assume.assumeTrue(mImpl == Impl.MODERN);
|
||||||
|
|
||||||
|
final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
|
||||||
|
final ProcessRecord receiverGreenApp1 = makeActiveProcessRecord(PACKAGE_GREEN);
|
||||||
|
final ProcessRecord receiverGreenApp2 = makeActiveProcessRecord(PACKAGE_GREEN,
|
||||||
|
PACKAGE_GREEN + "_proc2");
|
||||||
|
|
||||||
|
setProcessFreezable(receiverGreenApp1, true, true);
|
||||||
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp1);
|
||||||
|
|
||||||
|
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||||
|
final BroadcastOptions opts = BroadcastOptions.makeBasic()
|
||||||
|
.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
|
||||||
|
enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, opts,
|
||||||
|
List.of(makeRegisteredReceiver(receiverGreenApp1),
|
||||||
|
makeRegisteredReceiver(receiverGreenApp2))));
|
||||||
|
waitForIdle();
|
||||||
|
|
||||||
|
// 1st process in Green package is ignored since it is in a cached state
|
||||||
|
// but the 2nd process should still receive the broadcast.
|
||||||
|
verifyScheduleRegisteredReceiver(never(), receiverGreenApp1, airplane);
|
||||||
|
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp2, airplane);
|
||||||
|
|
||||||
|
// Shift the 1st process in Green package to be active and confirm that deferred broadcast
|
||||||
|
// is delivered
|
||||||
|
setProcessFreezable(receiverGreenApp1, false, false);
|
||||||
|
mQueue.onProcessFreezableChangedLocked(receiverGreenApp1);
|
||||||
|
waitForIdle();
|
||||||
|
verifyScheduleRegisteredReceiver(times(1), receiverGreenApp1, airplane);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBroadcastDelivery_uidForeground() throws Exception {
|
public void testBroadcastDelivery_uidForeground() throws Exception {
|
||||||
// Legacy stack doesn't support prioritization to foreground app.
|
// Legacy stack doesn't support prioritization to foreground app.
|
||||||
|
|||||||
Reference in New Issue
Block a user