mAllowedAssociations;
/**
* Tracks association information for a particular package along with debuggability.
@@ -755,24 +824,24 @@ public class ActivityManagerService extends IActivityManager.Stub
return mPidMap.indexOfKey(key);
}
- void doAddInternal(ProcessRecord app) {
- mPidMap.put(app.pid, app);
+ void doAddInternal(int pid, ProcessRecord app) {
+ mPidMap.put(pid, app);
}
- boolean doRemoveInternal(ProcessRecord app) {
- final ProcessRecord existingApp = mPidMap.get(app.pid);
- if (existingApp != null && existingApp.startSeq == app.startSeq) {
- mPidMap.remove(app.pid);
+ boolean doRemoveInternal(int pid, ProcessRecord app) {
+ final ProcessRecord existingApp = mPidMap.get(pid);
+ if (existingApp != null && existingApp.getStartSeq() == app.getStartSeq()) {
+ mPidMap.remove(pid);
return true;
}
return false;
}
- boolean doRemoveIfNoThreadInternal(ProcessRecord app) {
- if (app == null || app.thread != null) {
+ boolean doRemoveIfNoThreadInternal(int pid, ProcessRecord app) {
+ if (app == null || app.getThread() != null) {
return false;
}
- return doRemoveInternal(app);
+ return doRemoveInternal(pid, app);
}
}
@@ -783,18 +852,20 @@ public class ActivityManagerService extends IActivityManager.Stub
* NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
* method.
*/
+ @GuardedBy("this")
void addPidLocked(ProcessRecord app) {
+ final int pid = app.getPid();
synchronized (mPidsSelfLocked) {
- mPidsSelfLocked.doAddInternal(app);
+ mPidsSelfLocked.doAddInternal(pid, app);
}
synchronized (sActiveProcessInfoSelfLocked) {
if (app.processInfo != null) {
- sActiveProcessInfoSelfLocked.put(app.pid, app.processInfo);
+ sActiveProcessInfoSelfLocked.put(pid, app.processInfo);
} else {
- sActiveProcessInfoSelfLocked.remove(app.pid);
+ sActiveProcessInfoSelfLocked.remove(pid);
}
}
- mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController());
+ mAtmInternal.onProcessMapped(pid, app.getWindowProcessController());
}
/**
@@ -802,16 +873,17 @@ public class ActivityManagerService extends IActivityManager.Stub
*
NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
* method.
*/
- void removePidLocked(ProcessRecord app) {
+ @GuardedBy("this")
+ void removePidLocked(int pid, ProcessRecord app) {
final boolean removed;
synchronized (mPidsSelfLocked) {
- removed = mPidsSelfLocked.doRemoveInternal(app);
+ removed = mPidsSelfLocked.doRemoveInternal(pid, app);
}
if (removed) {
synchronized (sActiveProcessInfoSelfLocked) {
- sActiveProcessInfoSelfLocked.remove(app.pid);
+ sActiveProcessInfoSelfLocked.remove(pid);
}
- mAtmInternal.onProcessUnMapped(app.pid);
+ mAtmInternal.onProcessUnMapped(pid);
}
}
@@ -820,16 +892,18 @@ public class ActivityManagerService extends IActivityManager.Stub
*
NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
* method.
*/
- boolean removePidIfNoThread(ProcessRecord app) {
+ @GuardedBy("this")
+ private boolean removePidIfNoThreadLocked(ProcessRecord app) {
final boolean removed;
+ final int pid = app.getPid();
synchronized (mPidsSelfLocked) {
- removed = mPidsSelfLocked.doRemoveIfNoThreadInternal(app);
+ removed = mPidsSelfLocked.doRemoveIfNoThreadInternal(pid, app);
}
if (removed) {
synchronized (sActiveProcessInfoSelfLocked) {
- sActiveProcessInfoSelfLocked.remove(app.pid);
+ sActiveProcessInfoSelfLocked.remove(pid);
}
- mAtmInternal.onProcessUnMapped(app.pid);
+ mAtmInternal.onProcessUnMapped(pid);
}
return removed;
}
@@ -866,6 +940,7 @@ public class ActivityManagerService extends IActivityManager.Stub
proto.end(pToken);
}
}
+ @GuardedBy("this")
final SparseArray mImportantProcesses = new SparseArray();
/**
@@ -873,12 +948,14 @@ public class ActivityManagerService extends IActivityManager.Stub
* system was ready. We don't start them at that point, but ensure they
* are started by the time booting is complete.
*/
+ @GuardedBy("this")
final ArrayList mProcessesOnHold = new ArrayList();
/**
* List of persistent applications that are in the process
* of being started.
*/
+ @GuardedBy("this")
final ArrayList mPersistentStartingProcesses = new ArrayList();
private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
@@ -926,6 +1003,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* Keeps track of all IIntentReceivers that have been registered for broadcasts.
* Hash keys are the receiver IBinder, hash value is a ReceiverList.
*/
+ @GuardedBy("this")
final HashMap mRegisteredReceivers = new HashMap<>();
/**
@@ -978,6 +1056,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* by the user ID the sticky is for, and can include UserHandle.USER_ALL
* for stickies that are sent to all users.
*/
+ @GuardedBy("this")
final SparseArray>> mStickyBroadcasts =
new SparseArray>>();
@@ -1017,6 +1096,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* have seen. Mapping is target uid -> target component -> source uid -> source process name
* -> association data.
*/
+ @GuardedBy("this")
final SparseArray>>>
mAssociations = new SparseArray<>();
boolean mTrackingAssociations;
@@ -1068,16 +1148,19 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* Power-save whitelisted app-ids (not including except-idle-whitelisted ones).
*/
+ @CompositeRWLock({"this", "mProcLock"})
int[] mDeviceIdleAllowlist = new int[0];
/**
* Power-save whitelisted app-ids (including except-idle-whitelisted ones).
*/
+ @CompositeRWLock({"this", "mProcLock"})
int[] mDeviceIdleExceptIdleAllowlist = new int[0];
/**
* Set of app ids that are temporarily allowed to escape bg check due to high-pri message
*/
+ @CompositeRWLock({"this", "mProcLock"})
int[] mDeviceIdleTempAllowlist = new int[0];
static final class PendingTempAllowlist {
@@ -1103,11 +1186,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ @CompositeRWLock({"this", "mProcLock"})
final PendingTempAllowlists mPendingTempAllowlist = new PendingTempAllowlists(this);
/**
* The temp-allowlist that is allowed to start FGS from background.
*/
+ @CompositeRWLock({"this", "mProcLock"})
final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList();
/**
@@ -1123,11 +1208,6 @@ public class ActivityManagerService extends IActivityManager.Stub
ArrayMap mAppBindArgs;
ArrayMap mIsolatedAppBindArgs;
- /**
- * Temporary to avoid allocations. Protected by main lock.
- */
- final StringBuilder mStringBuilder = new StringBuilder(256);
-
volatile boolean mProcessesReady = false;
volatile boolean mSystemReady = false;
volatile boolean mOnBattery = false;
@@ -1148,6 +1228,7 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* Last time (in uptime) at which we checked for power usage.
*/
+ @GuardedBy("mProcLock")
long mLastPowerCheckUptime;
/**
@@ -1163,10 +1244,14 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* The uptime of the last time we performed idle maintenance.
*/
+ @GuardedBy("mProcLock")
long mLastIdleTime = SystemClock.uptimeMillis();
/**
* For reporting to battery stats the current top application.
+ *
+ * It has its own lock to avoid from the need of double locking if using the global
+ * ActivityManagerService lock and proc lock to guard it.
*/
@GuardedBy("mCurResumedAppLock")
private String mCurResumedPackage = null;
@@ -1184,22 +1269,38 @@ public class ActivityManagerService extends IActivityManager.Stub
* service. The ProcessMap is package/uid tuples; each of these contain
* an array of the currently foreground processes.
*/
+ @GuardedBy("this")
final ProcessMap> mForegroundPackages
= new ProcessMap>();
/**
* Set if the systemServer made a call to enterSafeMode.
*/
+ @GuardedBy("this")
boolean mSafeMode;
- String mDebugApp = null;
- boolean mWaitForDebugger = false;
- boolean mDebugTransient = false;
- String mOrigDebugApp = null;
- boolean mOrigWaitForDebugger = false;
+ @GuardedBy("this")
+ private String mDebugApp = null;
+
+ @GuardedBy("this")
+ private boolean mWaitForDebugger = false;
+
+ @GuardedBy("this")
+ private boolean mDebugTransient = false;
+
+ @GuardedBy("this")
+ private String mOrigDebugApp = null;
+
+ @GuardedBy("this")
+ private boolean mOrigWaitForDebugger = false;
+
+ @GuardedBy("this")
boolean mAlwaysFinishActivities = false;
- String mTrackAllocationApp = null;
+ @GuardedBy("mProcLock")
+ private String mTrackAllocationApp = null;
+
+ @GuardedBy("this")
String mNativeDebuggingApp = null;
final Injector mInjector;
@@ -1344,10 +1445,12 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* Whether to force background check on all apps (for battery saver) or not.
*/
- boolean mForceBackgroundCheck;
+ @CompositeRWLock({"this", "mProcLock"})
+ private boolean mForceBackgroundCheck;
private static String sTheRealBuildSerial = Build.UNKNOWN;
+ @GuardedBy("mProcLock")
private ParcelFileDescriptor[] mLifeMonitorFds;
static final HostingRecord sNullHostingRecord = new HostingRecord(null);
@@ -1369,6 +1472,7 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* The last time when the binder heavy hitter auto sampler started.
*/
+ @GuardedBy("mProcLock")
private long mLastBinderHeavyHitterAutoSamplerStart = 0L;
final AppProfiler mAppProfiler;
@@ -1406,19 +1510,19 @@ public class ActivityManagerService extends IActivityManager.Stub
} break;
case SHOW_STRICT_MODE_VIOLATION_UI_MSG: {
HashMap data = (HashMap) msg.obj;
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
ProcessRecord proc = (ProcessRecord) data.get("app");
if (proc == null) {
Slog.e(TAG, "App not found when showing strict mode dialog.");
break;
}
- if (proc.getDialogController().hasViolationDialogs()) {
+ if (proc.mErrorState.getDialogController().hasViolationDialogs()) {
Slog.e(TAG, "App already has strict mode dialog: " + proc);
return;
}
AppErrorResult res = (AppErrorResult) data.get("result");
if (mAtmInternal.showStrictModeViolationDialog()) {
- proc.getDialogController().showViolationDialogs(res);
+ proc.mErrorState.getDialogController().showViolationDialogs(res);
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
@@ -1428,15 +1532,15 @@ public class ActivityManagerService extends IActivityManager.Stub
ensureBootCompleted();
} break;
case WAIT_FOR_DEBUGGER_UI_MSG: {
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
ProcessRecord app = (ProcessRecord) msg.obj;
if (msg.arg1 != 0) {
- if (!app.waitedForDebugger) {
- app.getDialogController().showDebugWaitingDialogs();
- app.waitedForDebugger = true;
+ if (!app.hasWaitedForDebugger()) {
+ app.mErrorState.getDialogController().showDebugWaitingDialogs();
+ app.setWaitedForDebugger(true);
}
} else {
- app.getDialogController().clearWaitingDialog();
+ app.mErrorState.getDialogController().clearWaitingDialog();
}
}
} break;
@@ -1487,23 +1591,23 @@ public class ActivityManagerService extends IActivityManager.Stub
msg.getData().getCharSequence(SERVICE_RECORD_KEY));
} break;
case UPDATE_TIME_ZONE: {
- synchronized (ActivityManagerService.this) {
- for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord r = mProcessList.mLruProcesses.get(i);
- if (r.thread != null) {
+ synchronized (mProcLock) {
+ mProcessList.forEachLruProcessesLOSP(false, app -> {
+ final IApplicationThread thread = app.getThread();
+ if (thread != null) {
try {
- r.thread.updateTimeZone();
+ thread.updateTimeZone();
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to update time zone for: "
- + r.info.processName);
+ + app.info.processName);
}
- }
+ }
+ });
}
- }
} break;
case CLEAR_DNS_CACHE_MSG: {
- synchronized (ActivityManagerService.this) {
- mProcessList.clearAllDnsCacheLocked();
+ synchronized (mProcLock) {
+ mProcessList.clearAllDnsCacheLOSP();
}
} break;
case UPDATE_HTTP_PROXY_MSG: {
@@ -1558,8 +1662,8 @@ public class ActivityManagerService extends IActivityManager.Stub
case UPDATE_TIME_PREFERENCE_MSG: {
// The user's time format preference might have changed.
// For convenience we re-use the Intent extra values.
- synchronized (ActivityManagerService.this) {
- mProcessList.updateAllTimePrefsLocked(msg.arg1);
+ synchronized (mProcLock) {
+ mProcessList.updateAllTimePrefsLOSP(msg.arg1);
}
break;
}
@@ -1567,19 +1671,21 @@ public class ActivityManagerService extends IActivityManager.Stub
final int uid = msg.arg1;
final byte[] firstPacket = (byte[]) msg.obj;
- synchronized (mPidsSelfLocked) {
- for (int i = 0; i < mPidsSelfLocked.size(); i++) {
- final ProcessRecord p = mPidsSelfLocked.valueAt(i);
- if (p.uid == uid && p.thread != null) {
- try {
- p.thread.notifyCleartextNetwork(firstPacket);
- } catch (RemoteException ignored) {
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ for (int i = 0; i < mPidsSelfLocked.size(); i++) {
+ final ProcessRecord p = mPidsSelfLocked.valueAt(i);
+ final IApplicationThread thread = p.getThread();
+ if (p.uid == uid && thread != null) {
+ try {
+ thread.notifyCleartextNetwork(firstPacket);
+ } catch (RemoteException ignored) {
+ }
}
}
}
}
- break;
- }
+ } break;
case POST_DUMP_HEAP_NOTIFICATION_MSG: {
mAppProfiler.handlePostDumpHeapNotification();
} break;
@@ -1601,8 +1707,8 @@ public class ActivityManagerService extends IActivityManager.Stub
idleUids();
} break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
- synchronized (ActivityManagerService.this) {
- mProcessList.handleAllTrustStorageUpdateLocked();
+ synchronized (mProcLock) {
+ mProcessList.handleAllTrustStorageUpdateLOSP();
}
} break;
case BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG: {
@@ -1642,12 +1748,12 @@ public class ActivityManagerService extends IActivityManager.Stub
0,
new HostingRecord("system"));
app.setPersistent(true);
- app.pid = MY_PID;
+ app.mPid = MY_PID;
app.getWindowProcessController().setPid(MY_PID);
- app.maxAdj = ProcessList.SYSTEM_ADJ;
+ app.mState.setMaxAdj(ProcessList.SYSTEM_ADJ);
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
addPidLocked(app);
- mProcessList.updateLruProcessLocked(app, false, null);
+ updateLruProcessLocked(app, false, null);
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
}
} catch (PackageManager.NameNotFoundException e) {
@@ -2297,16 +2403,18 @@ public class ActivityManagerService extends IActivityManager.Stub
if (code == SYSPROPS_TRANSACTION) {
// We need to tell all apps about the system property change.
ArrayList procs = new ArrayList();
- synchronized (this) {
- final int NP = mProcessList.mProcessNames.getMap().size();
- for (int ip = 0; ip < NP; ip++) {
- SparseArray apps =
- mProcessList.mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia = 0; ia < NA; ia++) {
+ synchronized (mProcLock) {
+ final ArrayMap> pmap =
+ mProcessList.getProcessNamesLOSP().getMap();
+ final int numOfNames = pmap.size();
+ for (int ip = 0; ip < numOfNames; ip++) {
+ SparseArray apps = pmap.valueAt(ip);
+ final int numOfApps = apps.size();
+ for (int ia = 0; ia < numOfApps; ia++) {
ProcessRecord app = apps.valueAt(ia);
- if (app.thread != null) {
- procs.add(app.thread.asBinder());
+ final IApplicationThread thread = app.getThread();
+ if (thread != null) {
+ procs.add(thread.asBinder());
}
}
}
@@ -2358,10 +2466,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// When plugging in, update the CPU stats first before changing
// the plug state.
updateCpuStatsNow();
- synchronized (this) {
- synchronized(mPidsSelfLocked) {
- mOnBattery = DEBUG_POWER ? true : onBattery;
- }
+ synchronized (mProcLock) {
+ mOnBattery = DEBUG_POWER ? true : onBattery;
mOomAdjProfiler.batteryPowerChanged(onBattery);
}
}
@@ -2456,21 +2562,25 @@ public class ActivityManagerService extends IActivityManager.Stub
mActivityTaskManager.unregisterTaskStackListener(listener);
}
+ @GuardedBy("this")
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
ProcessRecord client) {
mProcessList.updateLruProcessLocked(app, activityChange, client);
}
+ @GuardedBy("this")
final void removeLruProcessLocked(ProcessRecord app) {
mProcessList.removeLruProcessLocked(app);
}
+ @GuardedBy("this")
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
return mProcessList.getProcessRecordLocked(processName, uid, keepIfLarge);
}
- final ProcessMap getProcessNames() {
- return mProcessList.mProcessNames;
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ final ProcessMap getProcessNamesLOSP() {
+ return mProcessList.getProcessNamesLOSP();
}
void notifyPackageUse(String packageName, int reason) {
@@ -2553,7 +2663,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (mUsageStatsService != null) {
mUsageStatsService.reportEvent(activity, userId, event, appToken.hashCode(), taskRoot);
}
- final ContentCaptureManagerInternal contentCaptureService = mContentCaptureService;
+ ContentCaptureManagerInternal contentCaptureService = mContentCaptureService;
if (contentCaptureService != null && (event == Event.ACTIVITY_PAUSED
|| event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED
|| event == Event.ACTIVITY_DESTROYED)) {
@@ -2627,19 +2737,18 @@ public class ActivityManagerService extends IActivityManager.Stub
"getPackageProcessState");
}
- int procState = PROCESS_STATE_NONEXISTENT;
- synchronized (this) {
- for (int i=mProcessList.mLruProcesses.size()-1; i>=0; i--) {
- final ProcessRecord proc = mProcessList.mLruProcesses.get(i);
- if (procState > proc.setProcState) {
- if (proc.getPkgList().containsKey(packageName)
- || (proc.pkgDeps != null && proc.pkgDeps.contains(packageName))) {
- procState = proc.setProcState;
+ final int[] procState = {PROCESS_STATE_NONEXISTENT};
+ synchronized (mProcLock) {
+ mProcessList.forEachLruProcessesLOSP(false, proc -> {
+ if (procState[0] > proc.mState.getSetProcState()) {
+ if (proc.getPkgList().containsKey(packageName) || (proc.getPkgDeps() != null
+ && proc.getPkgDeps().contains(packageName))) {
+ procState[0] = proc.mState.getSetProcState();
}
}
- }
+ });
}
- return procState;
+ return procState[0];
}
@Override
@@ -2649,11 +2758,12 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new SecurityException("Only shell can call it");
}
synchronized (this) {
- final ProcessRecord app = findProcessLocked(process, userId, "setProcessMemoryTrimLevel");
+ final ProcessRecord app = findProcessLOSP(process, userId, "setProcessMemoryTrimLevel");
if (app == null) {
throw new IllegalArgumentException("Unknown process: " + process);
}
- if (app.thread == null) {
+ final IApplicationThread thread = app.getThread();
+ if (thread == null) {
throw new IllegalArgumentException("Process has no app thread");
}
if (app.mProfile.getTrimMemoryLevel() >= level) {
@@ -2661,12 +2771,14 @@ public class ActivityManagerService extends IActivityManager.Stub
"Unable to set a higher trim level than current level");
}
if (!(level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN ||
- app.getCurProcState() > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)) {
+ app.mState.getCurProcState() > PROCESS_STATE_IMPORTANT_FOREGROUND)) {
throw new IllegalArgumentException("Unable to set a background trim level "
+ "on a foreground process");
}
- app.thread.scheduleTrimMemory(level);
- app.mProfile.setTrimMemoryLevel(level);
+ thread.scheduleTrimMemory(level);
+ synchronized (mProcLock) {
+ app.mProfile.setTrimMemoryLevel(level);
+ }
return true;
}
}
@@ -2823,10 +2935,9 @@ public class ActivityManagerService extends IActivityManager.Stub
* to the process.
*/
@GuardedBy("this")
- final void handleAppDiedLocked(ProcessRecord app,
+ final void handleAppDiedLocked(ProcessRecord app, int pid,
boolean restarting, boolean allowRestart) {
- int pid = app.pid;
- boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
+ boolean kept = cleanUpApplicationRecordLocked(app, pid, restarting, allowRestart, -1,
false /*replacingPid*/);
if (!kept && !restarting) {
removeLruProcessLocked(app);
@@ -2846,24 +2957,26 @@ public class ActivityManagerService extends IActivityManager.Stub
});
}
- ProcessRecord getRecordForAppLocked(IApplicationThread thread) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ ProcessRecord getRecordForAppLOSP(IApplicationThread thread) {
if (thread == null) {
return null;
}
- ProcessRecord record = mProcessList.getLRURecordForAppLocked(thread);
+ ProcessRecord record = mProcessList.getLRURecordForAppLOSP(thread);
if (record != null) return record;
// Validation: if it isn't in the LRU list, it shouldn't exist, but let's
// double-check that.
final IBinder threadBinder = thread.asBinder();
final ArrayMap> pmap =
- mProcessList.mProcessNames.getMap();
+ mProcessList.getProcessNamesLOSP().getMap();
for (int i = pmap.size()-1; i >= 0; i--) {
final SparseArray procs = pmap.valueAt(i);
for (int j = procs.size()-1; j >= 0; j--) {
final ProcessRecord proc = procs.valueAt(j);
- if (proc.thread != null && proc.thread.asBinder() == threadBinder) {
+ final IApplicationThread procThread = proc.getThread();
+ if (procThread != null && procThread.asBinder() == threadBinder) {
Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
+ proc);
return proc;
@@ -2876,7 +2989,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@GuardedBy("this")
final void appDiedLocked(ProcessRecord app, String reason) {
- appDiedLocked(app, app.pid, app.thread, false, reason);
+ appDiedLocked(app, app.getPid(), app.getThread(), false, reason);
}
@GuardedBy("this")
@@ -2893,26 +3006,31 @@ public class ActivityManagerService extends IActivityManager.Stub
mBatteryStatsService.noteProcessDied(app.info.uid, pid);
- if (!app.killed) {
+ if (!app.isKilled()) {
if (!fromBinderDied) {
killProcessQuiet(pid);
mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_UNKNOWN, reason);
}
ProcessList.killProcessGroup(app.uid, pid);
- app.killed = true;
+ synchronized (mProcLock) {
+ app.setKilled(true);
+ }
}
// Clean up already done if the process has been re-started.
- if (app.pid == pid && app.thread != null &&
- app.thread.asBinder() == thread.asBinder()) {
+ IApplicationThread appThread;
+ final int setAdj = app.mState.getSetAdj();
+ final int setProcState = app.mState.getSetProcState();
+ if (app.getPid() == pid && (appThread = app.getThread()) != null
+ && appThread.asBinder() == thread.asBinder()) {
boolean doLowMem = app.getActiveInstrumentation() == null;
boolean doOomAdj = doLowMem;
- if (!app.killedByAm) {
+ if (!app.isKilledByAm()) {
reportUidInfoMessageLocked(TAG,
"Process " + app.processName + " (pid " + pid + ") has died: "
- + ProcessList.makeOomAdjString(app.setAdj, true) + " "
- + ProcessList.makeProcStateString(app.setProcState), app.info.uid);
+ + ProcessList.makeOomAdjString(setAdj, true) + " "
+ + ProcessList.makeProcStateString(setProcState), app.info.uid);
mAppProfiler.setAllowLowerMemLevelLocked(true);
} else {
// Note that we always want to do oom adj to update our state with the
@@ -2920,11 +3038,10 @@ public class ActivityManagerService extends IActivityManager.Stub
mAppProfiler.setAllowLowerMemLevelLocked(false);
doLowMem = false;
}
- EventLogTags.writeAmProcDied(app.userId, app.pid, app.processName, app.setAdj,
- app.setProcState);
+ EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj, setProcState);
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
- handleAppDiedLocked(app, false, true);
+ handleAppDiedLocked(app, pid, false, true);
if (doOomAdj) {
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
@@ -2932,14 +3049,14 @@ public class ActivityManagerService extends IActivityManager.Stub
if (doLowMem) {
mAppProfiler.doLowMemReportIfNeededLocked(app);
}
- } else if (app.pid != pid) {
+ } else if (app.getPid() != pid) {
// A new process has already been started.
reportUidInfoMessageLocked(TAG,
"Process " + app.processName + " (pid " + pid
- + ") has died and restarted (pid " + app.pid + ").", app.info.uid);
+ + ") has died and restarted (pid " + app.getPid() + ").", app.info.uid);
- EventLogTags.writeAmProcDied(app.userId, app.pid, app.processName, app.setAdj,
- app.setProcState);
+ EventLogTags.writeAmProcDied(app.userId, app.getPid(), app.processName,
+ setAdj, setProcState);
} else if (DEBUG_PROCESSES) {
Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
+ thread.asBinder());
@@ -3387,9 +3504,11 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
synchronized (this) {
- mProcessList.killPackageProcessesLocked(packageName, appId, targetUserId,
- ProcessList.SERVICE_ADJ, ApplicationExitInfo.REASON_USER_REQUESTED,
- ApplicationExitInfo.SUBREASON_UNKNOWN, "kill background");
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(packageName, appId, targetUserId,
+ ProcessList.SERVICE_ADJ, ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN, "kill background");
+ }
}
}
} finally {
@@ -3414,11 +3533,13 @@ public class ActivityManagerService extends IActivityManager.Stub
// Allow memory level to go down (the flag needs to be set before updating oom adj)
// because this method is also used to simulate low memory.
mAppProfiler.setAllowLowerMemLevelLocked(true);
- mProcessList.killPackageProcessesLocked(null /* packageName */, -1 /* appId */,
- UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ,
- ApplicationExitInfo.REASON_USER_REQUESTED,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- "kill all background");
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(null /* packageName */, -1 /* appId */,
+ UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ,
+ ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "kill all background");
+ }
mAppProfiler.doLowMemReportIfNeededLocked(null);
}
@@ -3449,7 +3570,9 @@ public class ActivityManagerService extends IActivityManager.Stub
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mProcessList.killAllBackgroundProcessesExceptLocked(minTargetSdk, maxProcState);
+ synchronized (mProcLock) {
+ mProcessList.killAllBackgroundProcessesExceptLSP(minTargetSdk, maxProcState);
+ }
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -3524,11 +3647,14 @@ public class ActivityManagerService extends IActivityManager.Stub
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
if (proc != null) {
+ ArraySet pkgDeps = proc.getPkgDeps();
synchronized (this) {
- if (proc.pkgDeps == null) {
- proc.pkgDeps = new ArraySet(1);
+ synchronized (mProcLock) {
+ if (pkgDeps == null) {
+ proc.setPkgDeps(pkgDeps = new ArraySet(1));
+ }
+ pkgDeps.add(packageName);
}
- proc.pkgDeps.add(packageName);
}
}
}
@@ -3588,12 +3714,14 @@ public class ActivityManagerService extends IActivityManager.Stub
// Check if the caller is actually instrumented and from shell, if it's true, we may lift
// the throttle of PSS info sampling.
boolean isCallerInstrumentedFromShell = false;
- synchronized (mPidsSelfLocked) {
- ProcessRecord caller = mPidsSelfLocked.get(callingPid);
- if (caller != null) {
- final ActiveInstrumentation instr = caller.getActiveInstrumentation();
- isCallerInstrumentedFromShell = instr != null
- && (instr.mSourceUid == SHELL_UID || instr.mSourceUid == ROOT_UID);
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ ProcessRecord caller = mPidsSelfLocked.get(callingPid);
+ if (caller != null) {
+ final ActiveInstrumentation instr = caller.getActiveInstrumentation();
+ isCallerInstrumentedFromShell = instr != null
+ && (instr.mSourceUid == SHELL_UID || instr.mSourceUid == ROOT_UID);
+ }
}
}
@@ -3688,10 +3816,10 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i=pids.length-1; i>=0; i--) {
ProcessRecord proc;
int oomAdj;
- synchronized (this) {
+ synchronized (mProcLock) {
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(pids[i]);
- oomAdj = proc != null ? proc.setAdj : 0;
+ oomAdj = proc != null ? proc.mState.getSetAdj() : 0;
}
}
if (!allUids || (!allUsers && UserHandle.getUserId(proc.uid) != userId)) {
@@ -3740,9 +3868,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (callerUid == SYSTEM_UID) {
synchronized (this) {
ProcessRecord app = getProcessRecordLocked(processName, uid, true);
- if (app != null && app.thread != null) {
+ IApplicationThread thread;
+ if (app != null && (thread = app.getThread()) != null) {
try {
- app.thread.scheduleSuicide();
+ thread.scheduleSuicide();
} catch (RemoteException e) {
// If the other end already died, then our work here is done.
}
@@ -3904,6 +4033,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ boolean didSomething;
if (doit) {
if (packageName != null) {
Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId
@@ -3915,20 +4045,22 @@ public class ActivityManagerService extends IActivityManager.Stub
mAppErrors.resetProcessCrashTime(packageName == null, appId, userId);
}
- // Notify first that the package is stopped, so its process won't be restarted unexpectedly
- // if there is an activity of the package without attached process becomes visible when
- // killing its other processes with visible activities.
- boolean didSomething =
- mAtmInternal.onForceStopPackage(packageName, doit, evenPersistent, userId);
+ synchronized (mProcLock) {
+ // Notify first that the package is stopped, so its process won't be restarted
+ // unexpectedly if there is an activity of the package without attached process
+ // becomes visible when killing its other processes with visible activities.
+ didSomething = mAtmInternal.onForceStopPackage(
+ packageName, doit, evenPersistent, userId);
- didSomething |= mProcessList.killPackageProcessesLocked(packageName, appId, userId,
- ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
- evenPersistent, true /* setRemoved */,
- packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
- : ApplicationExitInfo.REASON_USER_REQUESTED,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- (packageName == null ? ("stop user " + userId) : ("stop " + packageName))
- + " due to " + reason);
+ didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
+ ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
+ evenPersistent, true /* setRemoved */,
+ packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
+ : ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ (packageName == null ? ("stop user " + userId) : ("stop " + packageName))
+ + " due to " + reason);
+ }
if (mServices.bringDownDisabledPackageServicesLocked(
packageName, null /* filterByClasses */, userId, evenPersistent, doit)) {
@@ -3987,26 +4119,29 @@ public class ActivityManagerService extends IActivityManager.Stub
@GuardedBy("this")
private final void processStartTimedOutLocked(ProcessRecord app) {
- final int pid = app.pid;
- boolean gone = removePidIfNoThread(app);
+ final int pid = app.getPid();
+ boolean gone = removePidIfNoThreadLocked(app);
if (gone) {
Slog.w(TAG, "Process " + app + " failed to attach");
EventLogTags.writeAmProcessStartTimeout(app.userId, pid, app.uid, app.processName);
- mProcessList.removeProcessNameLocked(app.processName, app.uid);
- mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
- mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
- // Take care of any launching providers waiting for this process.
- mCpHelper.cleanupAppInLaunchingProvidersLocked(app, true);
- // Take care of any services that are waiting for the process.
- mServices.processStartTimedOutLocked(app);
- app.kill("start timeout", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
- if (app.isolated) {
- mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ synchronized (mProcLock) {
+ mProcessList.removeProcessNameLocked(app.processName, app.uid);
+ mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
+ mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
+ // Take care of any launching providers waiting for this process.
+ mCpHelper.cleanupAppInLaunchingProvidersLocked(app, true);
+ // Take care of any services that are waiting for the process.
+ mServices.processStartTimedOutLocked(app);
+ app.killLocked("start timeout", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+ true);
+ if (app.isolated) {
+ mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+ }
+ removeLruProcessLocked(app);
}
- removeLruProcessLocked(app);
final BackupRecord backupTarget = mBackupTargets.get(app.userId);
- if (backupTarget != null && backupTarget.app.pid == pid) {
+ if (backupTarget != null && backupTarget.app.getPid() == pid) {
Slog.w(TAG, "Unattached app died before backup, skipping");
mHandler.post(new Runnable() {
@Override
@@ -4044,7 +4179,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
- if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) {
+ if (app != null && (app.getStartUid() != callingUid || app.getStartSeq() != startSeq)) {
String processName = null;
final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
if (pending != null) {
@@ -4054,14 +4189,14 @@ public class ActivityManagerService extends IActivityManager.Stub
+ " startSeq:" + startSeq
+ " pid:" + pid
+ " belongs to another existing app:" + app.processName
- + " startSeq:" + app.startSeq;
+ + " startSeq:" + app.getStartSeq();
Slog.wtf(TAG, msg);
// SafetyNet logging for b/131105245.
- EventLog.writeEvent(0x534e4554, "131105245", app.startUid, msg);
+ EventLog.writeEvent(0x534e4554, "131105245", app.getStartUid(), msg);
// If there is already an app occupying that pid that hasn't been cleaned up
- cleanUpApplicationRecordLocked(app, false, false, -1,
- true /*replacingPid*/);
- removePidLocked(app);
+ cleanUpApplicationRecordLocked(app, pid, false, false, -1,
+ true /*replacingPid*/);
+ removePidLocked(pid, app);
app = null;
}
} else {
@@ -4072,10 +4207,10 @@ public class ActivityManagerService extends IActivityManager.Stub
// update the internal state.
if (app == null && startSeq > 0) {
final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
- if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq
- && mProcessList.handleProcessStartedLocked(pending, pid, pending
- .isUsingWrapper(),
- startSeq, true)) {
+ if (pending != null && pending.getStartUid() == callingUid
+ && pending.getStartSeq() == startSeq
+ && mProcessList.handleProcessStartedLocked(pending, pid,
+ pending.isUsingWrapper(), startSeq, true)) {
app = pending;
}
}
@@ -4101,8 +4236,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// If this application record is still attached to a previous
// process, clean it up now.
- if (app.thread != null) {
- handleAppDiedLocked(app, true, true);
+ if (app.getThread() != null) {
+ handleAppDiedLocked(app, pid, true, true);
}
// Tell the process all about itself.
@@ -4115,7 +4250,7 @@ public class ActivityManagerService extends IActivityManager.Stub
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
- app.deathRecipient = adr;
+ app.setDeathRecipient(adr);
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,
@@ -4124,23 +4259,25 @@ public class ActivityManagerService extends IActivityManager.Stub
return false;
}
- EventLogTags.writeAmProcBound(app.userId, app.pid, app.processName);
+ EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
- app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
- mOomAdjuster.setAttachingSchedGroupLocked(app);
- app.forcingToImportant = null;
- updateProcessForegroundLocked(app, false, 0, false);
- app.hasShownUi = false;
- app.setDebugging(false);
- app.setCached(false);
- app.killedByAm = false;
- app.killed = false;
-
-
- // We carefully use the same state that PackageManager uses for
- // filtering, since we use this flag to decide if we need to install
- // providers when user is unlocked later
- app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
+ synchronized (mProcLock) {
+ app.mState.setCurAdj(ProcessList.INVALID_ADJ);
+ app.mState.setSetAdj(ProcessList.INVALID_ADJ);
+ app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);
+ mOomAdjuster.setAttachingSchedGroupLSP(app);
+ app.mState.setForcingToImportant(null);
+ updateProcessForegroundLocked(app, false, 0, false);
+ app.mState.setHasShownUi(false);
+ app.mState.setCached(false);
+ app.setDebugging(false);
+ app.setKilledByAm(false);
+ app.setKilled(false);
+ // We carefully use the same state that PackageManager uses for
+ // filtering, since we use this flag to decide if we need to install
+ // providers when user is unlocked later
+ app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));
+ }
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
@@ -4180,9 +4317,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
boolean enableTrackAllocation = false;
- if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
- enableTrackAllocation = true;
- mTrackAllocationApp = null;
+ synchronized (mProcLock) {
+ if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
+ enableTrackAllocation = true;
+ mTrackAllocationApp = null;
+ }
}
// If the app is being launched for restore or full backup, set it up specially
@@ -4203,7 +4342,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Binding proc %s with config %s",
processName, app.getWindowProcessController().getConfiguration());
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
- app.compat = compatibilityInfoForPackage(appInfo);
+ app.setCompat(compatibilityInfoForPackage(appInfo));
ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);
@@ -4247,10 +4386,11 @@ public class ActivityManagerService extends IActivityManager.Stub
mPlatformCompat.resetReporting(app.info);
}
final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
- if (app.isolatedEntryPoint != null) {
+ if (app.getIsolatedEntryPoint() != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
- thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
+ thread.runIsolatedEntryPoint(
+ app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
} else if (instr2 != null) {
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
@@ -4260,20 +4400,20 @@ public class ActivityManagerService extends IActivityManager.Stub
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
- app.compat, getCommonServicesLocked(app.isolated),
+ app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- app.mDisabledCompatChanges, serializedSystemFontMap);
+ app.getDisabledCompatChanges(), serializedSystemFontMap);
} else {
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
- app.compat, getCommonServicesLocked(app.isolated),
+ app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- app.mDisabledCompatChanges, serializedSystemFontMap);
+ app.getDisabledCompatChanges(), serializedSystemFontMap);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
@@ -4282,9 +4422,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
- app.makeActive(thread, mProcessStats);
- checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
- mProcessList.updateLruProcessLocked(app, false, null);
+ synchronized (mProcLock) {
+ app.makeActive(thread, mProcessStats);
+ checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
+ }
+ updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
final long now = SystemClock.uptimeMillis();
synchronized (mAppProfiler.mProfilerLock) {
@@ -4296,8 +4438,9 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
- app.kill("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
- handleAppDiedLocked(app, false, true);
+ app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+ true);
+ handleAppDiedLocked(app, pid, false, true);
return false;
}
@@ -4360,8 +4503,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (badApp) {
- app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
- handleAppDiedLocked(app, false, true);
+ app.killLocked("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+ true);
+ handleAppDiedLocked(app, pid, false, true);
return false;
}
@@ -4373,14 +4517,14 @@ public class ActivityManagerService extends IActivityManager.Stub
FrameworkStatsLog.write(
FrameworkStatsLog.PROCESS_START_TIME,
app.info.uid,
- app.pid,
+ pid,
app.info.packageName,
FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,
- app.startTime,
- (int) (bindApplicationTimeMillis - app.startTime),
- (int) (SystemClock.elapsedRealtime() - app.startTime),
- app.hostingRecord.getType(),
- (app.hostingRecord.getName() != null ? app.hostingRecord.getName() : ""));
+ app.getStartTime(),
+ (int) (bindApplicationTimeMillis - app.getStartTime()),
+ (int) (SystemClock.elapsedRealtime() - app.getStartTime()),
+ app.getHostingRecord().getType(),
+ (app.getHostingRecord().getName() != null ? app.getHostingRecord().getName() : ""));
return true;
}
@@ -4473,11 +4617,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// up.
final int NP = mProcessesOnHold.size();
if (NP > 0) {
- ArrayList procs =
- new ArrayList(mProcessesOnHold);
- for (int ip=0; ip procs = new ArrayList(mProcessesOnHold);
+ for (int ip = 0; ip < NP; ip++) {
+ if (DEBUG_PROCESSES) {
+ Slog.v(TAG_PROCESSES, "Starting process on hold: " + procs.get(ip));
+ }
mProcessList.startProcessLocked(procs.get(ip),
new HostingRecord("on-hold"),
ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
@@ -4509,8 +4653,8 @@ public class ActivityManagerService extends IActivityManager.Stub
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
- synchronized (ActivityManagerService.this) {
- mAppProfiler.requestPssAllProcsLocked(
+ synchronized (mProcLock) {
+ mAppProfiler.requestPssAllProcsLPr(
SystemClock.uptimeMillis(), true, false);
}
}
@@ -4945,7 +5089,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (pr == null) {
return;
}
- pr.forcingToImportant = null;
+ pr.mState.setForcingToImportant(null);
updateProcessForegroundLocked(pr, false, 0, false);
}
updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
@@ -4971,7 +5115,7 @@ public class ActivityManagerService extends IActivityManager.Stub
oldToken.token.unlinkToDeath(oldToken, 0);
mImportantProcesses.remove(pid);
if (pr != null) {
- pr.forcingToImportant = null;
+ pr.mState.setForcingToImportant(null);
}
changed = true;
}
@@ -4985,7 +5129,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
token.linkToDeath(newToken, 0);
mImportantProcesses.put(pid, newToken);
- pr.forcingToImportant = newToken;
+ pr.mState.setForcingToImportant(newToken);
changed = true;
} catch (RemoteException e) {
// If the process died while doing this, we will later
@@ -5001,13 +5145,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private boolean isAppForeground(int uid) {
- synchronized (this) {
+ synchronized (mProcLock) {
UidRecord uidRec = mProcessList.mActiveUids.get(uid);
- if (uidRec == null || uidRec.idle) {
+ if (uidRec == null || uidRec.isIdle()) {
return false;
}
- return uidRec.getCurProcState()
- <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+ return uidRec.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND;
}
}
@@ -5018,11 +5161,16 @@ public class ActivityManagerService extends IActivityManager.Stub
// NOTE: this is an internal method used by the OnShellCommand implementation only and should
// be guarded by permission checking.
int getUidState(int uid) {
- synchronized (this) {
- return mProcessList.getUidProcStateLocked(uid);
+ synchronized (mProcLock) {
+ return mProcessList.getUidProcStateLOSP(uid);
}
}
+ @GuardedBy("this")
+ int getUidStateLocked(int uid) {
+ return mProcessList.getUidProcStateLOSP(uid);
+ }
+
// =========================================================
// PROCESS INFO
// =========================================================
@@ -5071,20 +5219,23 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("pids and scores arrays have different lengths!");
}
- synchronized (mPidsSelfLocked) {
- for (int i = 0; i < pids.length; i++) {
- ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
- if (pr != null) {
- final boolean isPendingTop =
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ for (int i = 0; i < pids.length; i++) {
+ ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
+ if (pr != null) {
+ final boolean isPendingTop =
mPendingStartActivityUids.isPendingTopPid(pr.uid, pids[i]);
- states[i] = isPendingTop ? PROCESS_STATE_TOP : pr.getCurProcState();
- if (scores != null) {
- scores[i] = isPendingTop ? (ProcessList.FOREGROUND_APP_ADJ - 1) : pr.curAdj;
- }
- } else {
- states[i] = PROCESS_STATE_NONEXISTENT;
- if (scores != null) {
- scores[i] = ProcessList.INVALID_ADJ;
+ states[i] = isPendingTop ? PROCESS_STATE_TOP : pr.mState.getCurProcState();
+ if (scores != null) {
+ scores[i] = isPendingTop
+ ? (ProcessList.FOREGROUND_APP_ADJ - 1) : pr.mState.getCurAdj();
+ }
+ } else {
+ states[i] = PROCESS_STATE_NONEXISTENT;
+ if (scores != null) {
+ scores[i] = ProcessList.INVALID_ADJ;
+ }
}
}
}
@@ -5262,8 +5413,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
public boolean isAppStartModeDisabled(int uid, String packageName) {
- synchronized (this) {
- return getAppStartModeLocked(uid, packageName, 0, -1, false, true, false)
+ synchronized (mProcLock) {
+ return getAppStartModeLOSP(uid, packageName, 0, -1, false, true, false)
== ActivityManager.APP_START_MODE_DISABLED;
}
}
@@ -5274,7 +5425,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Unified app-op and target sdk check
- int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ int appRestrictedInBackgroundLOSP(int uid, String packageName, int packageTargetSdk) {
// Apps that target O+ are always subject to background check
if (packageTargetSdk >= Build.VERSION_CODES.O) {
if (DEBUG_BACKGROUND_CHECK) {
@@ -5303,7 +5455,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// If force-background-check is enabled, restrict all apps that aren't whitelisted.
if (mForceBackgroundCheck &&
!UserHandle.isCore(uid) &&
- !isOnDeviceIdleAllowlistLocked(uid, /*allowExceptIdleToo=*/ true)) {
+ !isOnDeviceIdleAllowlistLOSP(uid, /*allowExceptIdleToo=*/ true)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Force background check: " +
uid + "/" + packageName + " restricted");
@@ -5321,7 +5473,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// Service launch is available to apps with run-in-background exemptions but
// some other background operations are not. If we're doing a check
// of service-launch policy, allow those callers to proceed unrestricted.
- int appServicesRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ int appServicesRestrictedInBackgroundLOSP(int uid, String packageName, int packageTargetSdk) {
// Persistent app?
if (mPackageManagerInt.isPackagePersistent(packageName)) {
if (DEBUG_BACKGROUND_CHECK) {
@@ -5332,7 +5485,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Non-persistent but background whitelisted?
- if (uidOnBackgroundAllowlist(uid)) {
+ if (uidOnBackgroundAllowlistLOSP(uid)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName
+ " on background whitelist; not restricted in background");
@@ -5341,7 +5494,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Is this app on the battery whitelist?
- if (isOnDeviceIdleAllowlistLocked(uid, /*allowExceptIdleToo=*/ false)) {
+ if (isOnDeviceIdleAllowlistLOSP(uid, /*allowExceptIdleToo=*/ false)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName
+ " on idle whitelist; not restricted in background");
@@ -5350,25 +5503,26 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// None of the service-policy criteria apply, so we apply the common criteria
- return appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk);
+ return appRestrictedInBackgroundLOSP(uid, packageName, packageTargetSdk);
}
- int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ int getAppStartModeLOSP(int uid, String packageName, int packageTargetSdk,
int callingPid, boolean alwaysRestrict, boolean disabledOnly, boolean forcedStandby) {
if (mInternal.isPendingTopUid(uid)) {
return ActivityManager.APP_START_MODE_NORMAL;
}
- UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
+ UidRecord uidRec = mProcessList.getUidRecordLOSP(uid);
if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
+ packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
- + (uidRec != null ? uidRec.idle : false));
- if (uidRec == null || alwaysRestrict || forcedStandby || uidRec.idle) {
+ + (uidRec != null ? uidRec.isIdle() : false));
+ if (uidRec == null || alwaysRestrict || forcedStandby || uidRec.isIdle()) {
boolean ephemeral;
if (uidRec == null) {
ephemeral = getPackageManagerInternal().isPackageEphemeral(
UserHandle.getUserId(uid), packageName);
} else {
- ephemeral = uidRec.ephemeral;
+ ephemeral = uidRec.isEphemeral();
}
if (ephemeral) {
@@ -5383,14 +5537,14 @@ public class ActivityManagerService extends IActivityManager.Stub
return ActivityManager.APP_START_MODE_NORMAL;
}
final int startMode = (alwaysRestrict)
- ? appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk)
- : appServicesRestrictedInBackgroundLocked(uid, packageName,
+ ? appRestrictedInBackgroundLOSP(uid, packageName, packageTargetSdk)
+ : appServicesRestrictedInBackgroundLOSP(uid, packageName,
packageTargetSdk);
if (DEBUG_BACKGROUND_CHECK) {
Slog.d(TAG, "checkAllowBackground: uid=" + uid
+ " pkg=" + packageName + " startMode=" + startMode
- + " onallowlist=" + isOnDeviceIdleAllowlistLocked(uid, false)
- + " onallowlist(ei)=" + isOnDeviceIdleAllowlistLocked(uid, true));
+ + " onallowlist=" + isOnDeviceIdleAllowlistLOSP(uid, false)
+ + " onallowlist(ei)=" + isOnDeviceIdleAllowlistLOSP(uid, true));
}
if (startMode == ActivityManager.APP_START_MODE_DELAYED) {
// This is an old app that has been forced into a "compatible as possible"
@@ -5401,8 +5555,8 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(callingPid);
}
- if (proc != null &&
- !ActivityManager.isProcStateBackground(proc.getCurProcState())) {
+ if (proc != null && !ActivityManager.isProcStateBackground(
+ proc.mState.getCurProcState())) {
// Whoever is instigating this is in the foreground, so we will allow it
// to go through.
return ActivityManager.APP_START_MODE_NORMAL;
@@ -5418,7 +5572,8 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* @return whether a UID is in the system, user or temp doze allowlist.
*/
- boolean isOnDeviceIdleAllowlistLocked(int uid, boolean allowExceptIdleToo) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ boolean isOnDeviceIdleAllowlistLOSP(int uid, boolean allowExceptIdleToo) {
final int appId = UserHandle.getAppId(uid);
final int[] allowlist = allowExceptIdleToo
@@ -5430,7 +5585,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|| mPendingTempAllowlist.indexOfKey(uid) >= 0;
}
- boolean isAllowlistedForFgsStartLocked(int uid) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ boolean isAllowlistedForFgsStartLOSP(int uid) {
return Arrays.binarySearch(mDeviceIdleExceptIdleAllowlist, UserHandle.getAppId(uid)) >= 0
|| mFgsStartTempAllowList.isAllowed(uid);
}
@@ -5439,7 +5595,8 @@ public class ActivityManagerService extends IActivityManager.Stub
* @return allowlist tag for a uid from mPendingTempAllowlist, null if not currently on
* the allowlist
*/
- String getPendingTempAllowlistTagForUidLocked(int uid) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ String getPendingTempAllowlistTagForUidLOSP(int uid) {
final PendingTempAllowlist ptw = mPendingTempAllowlist.get(uid);
return ptw != null ? ptw.tag : null;
}
@@ -5484,8 +5641,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final int modeFlags, int userId) {
enforceNotIsolatedCaller("grantUriPermission");
GrantUri grantUri = new GrantUri(userId, uri, modeFlags);
- synchronized(this) {
- final ProcessRecord r = getRecordForAppLocked(caller);
+ synchronized (mProcLock) {
+ final ProcessRecord r = getRecordForAppLOSP(caller);
if (r == null) {
throw new SecurityException("Unable to find app for caller "
+ caller
@@ -5518,8 +5675,8 @@ public class ActivityManagerService extends IActivityManager.Stub
public void revokeUriPermission(IApplicationThread caller, String targetPackage, Uri uri,
final int modeFlags, int userId) {
enforceNotIsolatedCaller("revokeUriPermission");
- synchronized(this) {
- final ProcessRecord r = getRecordForAppLocked(caller);
+ synchronized (mProcLock) {
+ final ProcessRecord r = getRecordForAppLOSP(caller);
if (r == null) {
throw new SecurityException("Unable to find app for caller "
+ caller
@@ -5550,9 +5707,8 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
- synchronized (this) {
- ProcessRecord app =
- who != null ? getRecordForAppLocked(who) : null;
+ synchronized (mProcLock) {
+ final ProcessRecord app = who != null ? getRecordForAppLOSP(who) : null;
if (app == null) return;
Message msg = Message.obtain();
@@ -5851,7 +6007,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// GLOBAL MANAGEMENT
// =========================================================
- private boolean uidOnBackgroundAllowlist(final int uid) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ private boolean uidOnBackgroundAllowlistLOSP(final int uid) {
final int appId = UserHandle.getAppId(uid);
final int[] allowlist = mBackgroundAppIdAllowlist;
for (int i = 0, len = allowlist.length; i < len; i++) {
@@ -5895,11 +6052,13 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.i(TAG, "Adding uid " + uid + " to bg uid whitelist");
}
synchronized (this) {
- final int num = mBackgroundAppIdAllowlist.length;
- int[] newList = new int[num + 1];
- System.arraycopy(mBackgroundAppIdAllowlist, 0, newList, 0, num);
- newList[num] = UserHandle.getAppId(uid);
- mBackgroundAppIdAllowlist = newList;
+ synchronized (mProcLock) {
+ final int num = mBackgroundAppIdAllowlist.length;
+ int[] newList = new int[num + 1];
+ System.arraycopy(mBackgroundAppIdAllowlist, 0, newList, 0, num);
+ newList[num] = UserHandle.getAppId(uid);
+ mBackgroundAppIdAllowlist = newList;
+ }
}
}
@@ -5925,8 +6084,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (app == null) {
app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
new HostingRecord("added application",
- customProcess != null ? customProcess : info.processName));
- mProcessList.updateLruProcessLocked(app, false, null);
+ customProcess != null ? customProcess : info.processName));
+ updateLruProcessLocked(app, false, null);
updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
}
@@ -5942,9 +6101,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.setPersistent(true);
- app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
+ app.mState.setMaxAdj(ProcessList.PERSISTENT_PROC_ADJ);
}
- if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
+ if (app.getThread() == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
@@ -6015,7 +6174,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
void onWakefulnessChanged(int wakefulness) {
- synchronized(this) {
+ synchronized (this) {
boolean wasAwake = mWakefulness.getAndSet(wakefulness)
== PowerManagerInternal.WAKEFULNESS_AWAKE;
boolean isAwake = wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -6142,13 +6301,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
void setTrackAllocationApp(ApplicationInfo app, String processName) {
- synchronized (this) {
- if (!Build.IS_DEBUGGABLE) {
- if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
- throw new SecurityException("Process not debuggable: " + app.packageName);
- }
+ if (!Build.IS_DEBUGGABLE) {
+ if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+ throw new SecurityException("Process not debuggable: " + app.packageName);
}
+ }
+ synchronized (mProcLock) {
mTrackAllocationApp = processName;
}
}
@@ -6205,7 +6364,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void setUserIsMonkey(boolean userIsMonkey) {
- synchronized (this) {
+ synchronized (mProcLock) {
synchronized (mPidsSelfLocked) {
final int callingPid = Binder.getCallingPid();
ProcessRecord proc = mPidsSelfLocked.get(callingPid);
@@ -6224,7 +6383,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean isUserAMonkey() {
- synchronized (this) {
+ synchronized (mProcLock) {
// If there is a controller also implies the user is a monkey.
return mUserIsMonkey || mActivityTaskManager.isControllerAMonkey();
}
@@ -6445,8 +6604,8 @@ public class ActivityManagerService extends IActivityManager.Stub
"getUidProcessState");
}
- synchronized (this) {
- return mProcessList.getUidProcStateLocked(uid);
+ synchronized (mProcLock) {
+ return mProcessList.getUidProcStateLOSP(uid);
}
}
@@ -6472,17 +6631,18 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
"isUidActive");
}
- synchronized (this) {
- if (isUidActiveLocked(uid)) {
+ synchronized (mProcLock) {
+ if (isUidActiveLOSP(uid)) {
return true;
}
}
return mInternal.isPendingTopUid(uid);
}
- boolean isUidActiveLocked(int uid) {
- final UidRecord uidRecord = mProcessList.getUidRecordLocked(uid);
- return uidRecord != null && !uidRecord.setIdle;
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ boolean isUidActiveLOSP(int uid) {
+ final UidRecord uidRecord = mProcessList.getUidRecordLOSP(uid);
+ return uidRecord != null && !uidRecord.isSetIdle();
}
@Override
@@ -6540,7 +6700,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void setRenderThread(int tid) {
- synchronized (this) {
+ synchronized (mProcLock) {
ProcessRecord proc;
int pid = Binder.getCallingPid();
if (pid == Process.myPid()) {
@@ -6549,33 +6709,32 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(pid);
- if (proc != null && proc.renderThreadTid == 0 && tid > 0) {
- // ensure the tid belongs to the process
- if (!isThreadInProcess(pid, tid)) {
- throw new IllegalArgumentException(
+ }
+ if (proc != null && proc.getRenderThreadTid() == 0 && tid > 0) {
+ // ensure the tid belongs to the process
+ if (!isThreadInProcess(pid, tid)) {
+ throw new IllegalArgumentException(
"Render thread does not belong to process");
- }
- proc.renderThreadTid = tid;
- if (DEBUG_OOM_ADJ) {
- Slog.d("UI_FIFO", "Set RenderThread tid " + tid + " for pid " + pid);
- }
- // promote to FIFO now
- if (proc.getCurrentSchedulingGroup() == ProcessList.SCHED_GROUP_TOP_APP) {
- if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
- if (mUseFifoUiScheduling) {
- setThreadScheduler(proc.renderThreadTid,
+ }
+ proc.setRenderThreadTid(tid);
+ if (DEBUG_OOM_ADJ) {
+ Slog.d("UI_FIFO", "Set RenderThread tid " + tid + " for pid " + pid);
+ }
+ // promote to FIFO now
+ if (proc.mState.getCurrentSchedulingGroup() == ProcessList.SCHED_GROUP_TOP_APP) {
+ if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
+ if (mUseFifoUiScheduling) {
+ setThreadScheduler(proc.getRenderThreadTid(),
SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
- } else {
- setThreadPriority(proc.renderThreadTid, TOP_APP_PRIORITY_BOOST);
- }
- }
- } else {
- if (DEBUG_OOM_ADJ) {
- Slog.d("UI_FIFO", "Didn't set thread from setRenderThread? " +
- "PID: " + pid + ", TID: " + tid + " FIFO: " +
- mUseFifoUiScheduling);
+ } else {
+ setThreadPriority(proc.getRenderThreadTid(), TOP_APP_PRIORITY_BOOST);
}
}
+ } else {
+ if (DEBUG_OOM_ADJ) {
+ Slog.d("UI_FIFO", "Didn't set thread from setRenderThread? "
+ + "PID: " + pid + ", TID: " + tid + " FIFO: " + mUseFifoUiScheduling);
+ }
}
}
}
@@ -6631,11 +6790,11 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.w(TAG, "setHasTopUi called on unknown pid: " + pid);
return;
}
- if (pr.hasTopUi() != hasTopUi) {
+ if (pr.mState.hasTopUi() != hasTopUi) {
if (DEBUG_OOM_ADJ) {
Slog.d(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid);
}
- pr.setHasTopUi(hasTopUi);
+ pr.mState.setHasTopUi(hasTopUi);
changed = true;
}
}
@@ -6815,42 +6974,46 @@ public class ActivityManagerService extends IActivityManager.Stub
// manager calls in with its locks held.
boolean killed = false;
- synchronized (mPidsSelfLocked) {
- int worstType = 0;
- for (int i=0; i worstType) {
- worstType = type;
+ synchronized (this) {
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ int worstType = 0;
+ for (int i = 0; i < pids.length; i++) {
+ ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+ if (proc != null) {
+ int type = proc.mState.getSetAdj();
+ if (type > worstType) {
+ worstType = type;
+ }
+ }
}
- }
- }
- // If the worst oom_adj is somewhere in the cached proc LRU range,
- // then constrain it so we will kill all cached procs.
- if (worstType < ProcessList.CACHED_APP_MAX_ADJ
- && worstType > ProcessList.CACHED_APP_MIN_ADJ) {
- worstType = ProcessList.CACHED_APP_MIN_ADJ;
- }
+ // If the worst oom_adj is somewhere in the cached proc LRU range,
+ // then constrain it so we will kill all cached procs.
+ if (worstType < ProcessList.CACHED_APP_MAX_ADJ
+ && worstType > ProcessList.CACHED_APP_MIN_ADJ) {
+ worstType = ProcessList.CACHED_APP_MIN_ADJ;
+ }
- // If this is not a secure call, don't let it kill processes that
- // are important.
- if (!secure && worstType < ProcessList.SERVICE_ADJ) {
- worstType = ProcessList.SERVICE_ADJ;
- }
+ // If this is not a secure call, don't let it kill processes that
+ // are important.
+ if (!secure && worstType < ProcessList.SERVICE_ADJ) {
+ worstType = ProcessList.SERVICE_ADJ;
+ }
- Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
- for (int i=0; i= worstType && !proc.killedByAm) {
- proc.kill(reason, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_KILL_PID, true);
- killed = true;
+ Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
+ for (int i = 0; i < pids.length; i++) {
+ ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+ if (proc == null) {
+ continue;
+ }
+ int adj = proc.mState.getSetAdj();
+ if (adj >= worstType && !proc.isKilledByAm()) {
+ proc.killLocked(reason, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_PID, true);
+ killed = true;
+ }
+ }
}
}
}
@@ -6863,13 +7026,15 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
try {
- mProcessList.killPackageProcessesLocked(null /* packageName */, appId, userId,
- ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
- true /* callerWillRestart */, true /* doit */, true /* evenPersistent */,
- false /* setRemoved */,
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_KILL_UID,
- reason != null ? reason : "kill uid");
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(null /* packageName */, appId, userId,
+ ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
+ true /* callerWillRestart */, true /* doit */,
+ true /* evenPersistent */, false /* setRemoved */,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_UID,
+ reason != null ? reason : "kill uid");
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6882,13 +7047,15 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
try {
- mProcessList.killPackageProcessesLocked(null /* packageName */, appId, userId,
- ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
- true /* callerWillRestart */, true /* doit */, true /* evenPersistent */,
- false /* setRemoved */,
- ApplicationExitInfo.REASON_PERMISSION_CHANGE,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- reason != null ? reason : "kill uid");
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(null /* packageName */, appId, userId,
+ ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
+ true /* callerWillRestart */, true /* doit */,
+ true /* evenPersistent */, false /* setRemoved */,
+ ApplicationExitInfo.REASON_PERMISSION_CHANGE,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ reason != null ? reason : "kill uid");
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6910,17 +7077,22 @@ public class ActivityManagerService extends IActivityManager.Stub
}
boolean killed = false;
- synchronized (mPidsSelfLocked) {
- final int size = mPidsSelfLocked.size();
- for (int i = 0; i < size; i++) {
- final int pid = mPidsSelfLocked.keyAt(i);
- final ProcessRecord proc = mPidsSelfLocked.valueAt(i);
- if (proc == null) continue;
+ synchronized (this) {
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ final int size = mPidsSelfLocked.size();
+ for (int i = 0; i < size; i++) {
+ final int pid = mPidsSelfLocked.keyAt(i);
+ final ProcessRecord proc = mPidsSelfLocked.valueAt(i);
+ if (proc == null) continue;
- final int adj = proc.setAdj;
- if (adj > belowAdj && !proc.killedByAm) {
- proc.kill(reason, ApplicationExitInfo.REASON_PERMISSION_CHANGE, true);
- killed = true;
+ final int adj = proc.mState.getSetAdj();
+ if (adj > belowAdj && !proc.isKilledByAm()) {
+ proc.killLocked(reason, ApplicationExitInfo.REASON_PERMISSION_CHANGE,
+ true);
+ killed = true;
+ }
+ }
}
}
}
@@ -7026,16 +7198,16 @@ public class ActivityManagerService extends IActivityManager.Stub
+ android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
- synchronized (this) {
+ synchronized (mProcLock) {
final long now = SystemClock.uptimeMillis();
final long timeSinceLastIdle = now - mLastIdleTime;
// Compact all non-zygote processes to freshen up the page cache.
mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
- final long lowRamSinceLastIdle = mAppProfiler.getLowRamTimeSinceIdleLocked(now);
+ final long lowRamSinceLastIdle = mAppProfiler.getLowRamTimeSinceIdleLPr(now);
mLastIdleTime = now;
- mAppProfiler.updateLowRamTimestampLocked(now);
+ mAppProfiler.updateLowRamTimestampLPr(now);
StringBuilder sb = new StringBuilder(128);
sb.append("Idle maintenance over ");
@@ -7052,13 +7224,13 @@ public class ActivityManagerService extends IActivityManager.Stub
final long totalMemoryInKb = getTotalMemory() / 1000;
final long memoryGrowthThreshold =
Math.max(totalMemoryInKb / 100, MINIMUM_MEMORY_GROWTH_THRESHOLD);
-
- for (int i = mProcessList.mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord proc = mProcessList.mLruProcesses.get(i);
+ mProcessList.forEachLruProcessesLOSP(false, proc -> {
final ProcessProfileRecord pr = proc.mProfile;
- if (proc.notCachedSinceIdle) {
- if (proc.setProcState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- && proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
+ final ProcessStateRecord state = proc.mState;
+ final int setProcState = state.getSetProcState();
+ if (state.isNotCachedSinceIdle()) {
+ if (setProcState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+ && setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
final long initialIdlePss, lastPss, lastSwapPss;
synchronized (mAppProfiler.mProfilerLock) {
initialIdlePss = pr.getInitialIdlePss();
@@ -7066,39 +7238,43 @@ public class ActivityManagerService extends IActivityManager.Stub
lastSwapPss = pr.getLastSwapPss();
}
if (doKilling && initialIdlePss != 0
- && lastPss > ((initialIdlePss * 3) / 2)
+ && lastPss > (initialIdlePss * 3 / 2)
&& lastPss > (initialIdlePss + memoryGrowthThreshold)) {
- sb = new StringBuilder(128);
- sb.append("Kill");
- sb.append(proc.processName);
- sb.append(" in idle maint: pss=");
- sb.append(lastPss);
- sb.append(", swapPss=");
- sb.append(lastSwapPss);
- sb.append(", initialPss=");
- sb.append(initialIdlePss);
- sb.append(", period=");
- TimeUtils.formatDuration(timeSinceLastIdle, sb);
- sb.append(", lowRamPeriod=");
- TimeUtils.formatDuration(lowRamSinceLastIdle, sb);
- Slog.wtfQuiet(TAG, sb.toString());
- proc.kill("idle maint (pss " + lastPss
- + " from " + initialIdlePss + ")",
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_MEMORY_PRESSURE,
- true);
+ final StringBuilder sb2 = new StringBuilder(128);
+ sb2.append("Kill");
+ sb2.append(proc.processName);
+ sb2.append(" in idle maint: pss=");
+ sb2.append(lastPss);
+ sb2.append(", swapPss=");
+ sb2.append(lastSwapPss);
+ sb2.append(", initialPss=");
+ sb2.append(initialIdlePss);
+ sb2.append(", period=");
+ TimeUtils.formatDuration(timeSinceLastIdle, sb2);
+ sb2.append(", lowRamPeriod=");
+ TimeUtils.formatDuration(lowRamSinceLastIdle, sb2);
+ Slog.wtfQuiet(TAG, sb2.toString());
+ mHandler.post(() -> {
+ synchronized (ActivityManagerService.this) {
+ proc.killLocked("idle maint (pss " + lastPss
+ + " from " + initialIdlePss + ")",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_MEMORY_PRESSURE,
+ true);
+ }
+ });
}
}
- } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME
- && proc.setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
- proc.notCachedSinceIdle = true;
+ } else if (setProcState < ActivityManager.PROCESS_STATE_HOME
+ && setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
+ state.setNotCachedSinceIdle(true);
synchronized (mAppProfiler.mProfilerLock) {
pr.setInitialIdlePss(0);
mAppProfiler.updateNextPssTimeLPf(
- proc.setProcState, proc.mProfile, now, true);
+ state.getSetProcState(), proc.mProfile, now, true);
}
}
- }
+ });
}
}
@@ -7209,7 +7385,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
if (procsToKill != null) {
- for (int i=procsToKill.size()-1; i>=0; i--) {
+ for (int i = procsToKill.size() - 1; i >= 0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
mProcessList.removeProcessLocked(proc, true, false,
@@ -7436,16 +7612,18 @@ public class ActivityManagerService extends IActivityManager.Stub
private void updateForceBackgroundCheck(boolean enabled) {
synchronized (this) {
- if (mForceBackgroundCheck != enabled) {
- mForceBackgroundCheck = enabled;
+ synchronized (mProcLock) {
+ if (mForceBackgroundCheck != enabled) {
+ mForceBackgroundCheck = enabled;
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.i(TAG, "Force background check " + (enabled ? "enabled" : "disabled"));
- }
+ if (DEBUG_BACKGROUND_CHECK) {
+ Slog.i(TAG, "Force background check " + (enabled ? "enabled" : "disabled"));
+ }
- if (mForceBackgroundCheck) {
- // Stop background services for idle UIDs.
- mProcessList.doStopUidForIdleUidsLocked();
+ if (mForceBackgroundCheck) {
+ // Stop background services for idle UIDs.
+ mProcessList.doStopUidForIdleUidsLocked();
+ }
}
}
}
@@ -7510,7 +7688,7 @@ public class ActivityManagerService extends IActivityManager.Stub
(r != null) ? r.uid : -1,
eventType,
processName,
- (r != null) ? r.pid : -1,
+ (r != null) ? r.getPid() : -1,
(r != null && r.info != null) ? r.info.packageName : "",
(r != null && r.info != null) ? (r.info.isInstantApp()
? FrameworkStatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__TRUE
@@ -7756,8 +7934,8 @@ public class ActivityManagerService extends IActivityManager.Stub
return null;
}
- synchronized (this) {
- return mProcessList.findAppProcessLocked(app, reason);
+ synchronized (mProcLock) {
+ return mProcessList.findAppProcessLOSP(app, reason);
}
}
@@ -7766,7 +7944,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* to append various headers to the dropbox log text.
*/
void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
- StringBuilder sb) {
+ final StringBuilder sb) {
// Watchdog thread ends up invoking this function (with
// a null ProcessRecord) to add the stack file to dropbox.
// Do not acquire a lock on this (am) in such cases, as it
@@ -7780,17 +7958,18 @@ public class ActivityManagerService extends IActivityManager.Stub
// Note: ProcessRecord 'process' is guarded by the service
// instance. (notably process.pkgList, which could otherwise change
// concurrently during execution of this method)
- synchronized (this) {
+ synchronized (mProcLock) {
sb.append("Process: ").append(processName).append("\n");
- sb.append("PID: ").append(process.pid).append("\n");
+ sb.append("PID: ").append(process.getPid()).append("\n");
sb.append("UID: ").append(process.uid).append("\n");
int flags = process.info.flags;
- IPackageManager pm = AppGlobals.getPackageManager();
+ final IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
+ final int callingUserId = UserHandle.getCallingUserId();
process.getPkgList().forEachPackage(pkg -> {
sb.append("Package: ").append(pkg);
try {
- PackageInfo pi = pm.getPackageInfo(pkg, 0, UserHandle.getCallingUserId());
+ final PackageInfo pi = pm.getPackageInfo(pkg, 0, callingUserId);
if (pi != null) {
sb.append(" v").append(pi.getLongVersionCode());
if (pi.versionName != null) {
@@ -7809,7 +7988,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private static String processClass(ProcessRecord process) {
- if (process == null || process.pid == MY_PID) {
+ if (process == null || process.getPid() == MY_PID) {
return "system_server";
} else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return "system_app";
@@ -7871,8 +8050,8 @@ public class ActivityManagerService extends IActivityManager.Stub
sb.append("Foreground: ")
.append(process.isInterestingToUserLocked() ? "Yes" : "No")
.append("\n");
- if (process.startTime > 0) {
- long runtimeMillis = SystemClock.elapsedRealtime() - process.startTime;
+ if (process.getStartTime() > 0) {
+ long runtimeMillis = SystemClock.elapsedRealtime() - process.getStartTime();
sb.append("Process-Runtime: ").append(runtimeMillis).append("\n");
}
}
@@ -7880,7 +8059,7 @@ public class ActivityManagerService extends IActivityManager.Stub
sb.append("Activity: ").append(activityShortComponentName).append("\n");
}
if (parentShortComponentName != null) {
- if (parentProcess != null && parentProcess.pid != process.pid) {
+ if (parentProcess != null && parentProcess.getPid() != process.getPid()) {
sb.append("Parent-Process: ").append(parentProcess.processName).append("\n");
}
if (!parentShortComponentName.equals(activityShortComponentName)) {
@@ -7976,47 +8155,46 @@ public class ActivityManagerService extends IActivityManager.Stub
public List getProcessesInErrorState() {
enforceNotIsolatedCaller("getProcessesInErrorState");
// assume our apps are happy - lazy create the list
- List errList = null;
+ final List[] errList = new List[1];
final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
int userId = UserHandle.getUserId(Binder.getCallingUid());
- synchronized (this) {
-
+ synchronized (mProcLock) {
// iterate across all processes
- for (int i=mProcessList.mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
+ mProcessList.forEachLruProcessesLOSP(false, app -> {
if (!allUsers && app.userId != userId) {
- continue;
+ return;
}
- final boolean crashing = app.isCrashing();
- final boolean notResponding = app.isNotResponding();
- if ((app.thread != null) && (crashing || notResponding)) {
+ final ProcessErrorStateRecord errState = app.mErrorState;
+ final boolean crashing = errState.isCrashing();
+ final boolean notResponding = errState.isNotResponding();
+ if ((app.getThread() != null) && (crashing || notResponding)) {
// This one's in trouble, so we'll generate a report for it
// crashes are higher priority (in case there's a crash *and* an anr)
ActivityManager.ProcessErrorStateInfo report = null;
if (crashing) {
- report = app.crashingReport;
+ report = errState.getCrashingReport();
} else if (notResponding) {
- report = app.notRespondingReport;
+ report = errState.getNotRespondingReport();
}
if (report != null) {
- if (errList == null) {
- errList = new ArrayList<>(1);
+ if (errList[0] == null) {
+ errList[0] = new ArrayList<>(1);
}
- errList.add(report);
+ errList[0].add(report);
} else {
Slog.w(TAG, "Missing app error report, app = " + app.processName +
" crashing = " + crashing +
" notResponding = " + notResponding);
}
}
- }
+ });
}
- return errList;
+ return errList[0];
}
@Override
@@ -8032,9 +8210,9 @@ public class ActivityManagerService extends IActivityManager.Stub
final boolean allUids = mAtmInternal.isGetTasksAllowed(
"getRunningAppProcesses", Binder.getCallingPid(), callingUid);
- synchronized (this) {
+ synchronized (mProcLock) {
// Iterate across all processes
- return mProcessList.getRunningAppProcessesLocked(allUsers, userId, allUids,
+ return mProcessList.getRunningAppProcessesLOSP(allUsers, userId, allUids,
callingUid, clientTargetSdk);
}
}
@@ -8145,13 +8323,13 @@ public class ActivityManagerService extends IActivityManager.Stub
final int callingUid = Binder.getCallingUid();
final int clientTargetSdk = mPackageManagerInt.getUidTargetSdkVersion(callingUid);
- synchronized (this) {
+ synchronized (mProcLock) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
if (proc != null) {
- mProcessList.fillInProcMemInfoLocked(proc, outState, clientTargetSdk);
+ mProcessList.fillInProcMemInfoLOSP(proc, outState, clientTargetSdk);
}
}
}
@@ -8197,7 +8375,9 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
mConstants.dump(pw);
- mOomAdjuster.dumpCachedAppOptimizerSettings(pw);
+ synchronized (mProcLock) {
+ mOomAdjuster.dumpCachedAppOptimizerSettings(pw);
+ }
mOomAdjuster.dumpCacheOomRankerSettings(pw);
pw.println();
if (dumpAll) {
@@ -8329,7 +8509,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- mProcessList.dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
+ synchronized (mProcLock) {
+ mProcessList.dumpProcessesLSP(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
+ }
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -8433,7 +8615,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// output proto is ProcessProto
synchronized (this) {
- mProcessList.writeProcessesToProtoLocked(proto, dumpPackage);
+ synchronized (mProcLock) {
+ mProcessList.writeProcessesToProtoLSP(proto, dumpPackage);
+ }
}
} else {
// default option, dump everything, output is ActivityManagerServiceProto
@@ -8452,7 +8636,9 @@ public class ActivityManagerService extends IActivityManager.Stub
proto.end(serviceToken);
long processToken = proto.start(ActivityManagerServiceProto.PROCESSES);
- mProcessList.writeProcessesToProtoLocked(proto, dumpPackage);
+ synchronized (mProcLock) {
+ mProcessList.writeProcessesToProtoLSP(proto, dumpPackage);
+ }
proto.end(processToken);
}
}
@@ -8526,8 +8712,10 @@ public class ActivityManagerService extends IActivityManager.Stub
opti++;
}
synchronized (this) {
- mProcessList.dumpProcessesLocked(
- fd, pw, args, opti, true, dumpPackage, dumpAppId);
+ synchronized (mProcLock) {
+ mProcessList.dumpProcessesLSP(
+ fd, pw, args, opti, true, dumpPackage, dumpAppId);
+ }
}
} else if ("oom".equals(cmd) || "o".equals(cmd)) {
synchronized (this) {
@@ -8615,6 +8803,8 @@ public class ActivityManagerService extends IActivityManager.Stub
} else if ("settings".equals(cmd)) {
synchronized (this) {
mConstants.dump(pw);
+ }
+ synchronized (mProcLock) {
mOomAdjuster.dumpCachedAppOptimizerSettings(pw);
mOomAdjuster.dumpCacheOomRankerSettings(pw);
}
@@ -8864,8 +9054,8 @@ public class ActivityManagerService extends IActivityManager.Stub
return needSep;
}
- @GuardedBy("this")
- void dumpOtherProcessesInfoLocked(FileDescriptor fd, PrintWriter pw,
+ @GuardedBy({"this", "mProcLock"})
+ void dumpOtherProcessesInfoLSP(FileDescriptor fd, PrintWriter pw,
boolean dumpAll, String dumpPackage, int dumpAppId, int numPers, boolean needSep) {
if (dumpAll || dumpPackage != null) {
final SparseArray pidToProcess = new SparseArray<>();
@@ -8873,7 +9063,7 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean printed = false;
for (int i = 0, size = mPidsSelfLocked.size(); i < size; i++) {
ProcessRecord r = mPidsSelfLocked.valueAt(i);
- pidToProcess.put(r.pid, r);
+ pidToProcess.put(r.getPid(), r);
if (dumpPackage != null && !r.getPkgList().containsKey(dumpPackage)) {
continue;
}
@@ -8884,7 +9074,7 @@ public class ActivityManagerService extends IActivityManager.Stub
printed = true;
}
pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
- pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
+ pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
}
}
@@ -8924,8 +9114,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
boolean printed = false;
for (int i = 0, size = mImportantProcesses.size(); i < size; i++) {
- ProcessRecord r = mPidsSelfLocked.get(
- mImportantProcesses.valueAt(i).pid);
+ ProcessRecord r = mPidsSelfLocked.get(mImportantProcesses.valueAt(i).pid);
if (dumpPackage != null && (r == null
|| !r.getPkgList().containsKey(dumpPackage))) {
continue;
@@ -8966,7 +9155,7 @@ public class ActivityManagerService extends IActivityManager.Stub
"OnHold Norm", "OnHold PERS", dumpPackage);
}
- needSep = mAppErrors.dumpLocked(fd, pw, needSep, dumpPackage);
+ needSep = mAppErrors.dumpLPr(fd, pw, needSep, dumpPackage);
needSep = mAtmInternal.dumpForProcesses(fd, pw, dumpAll, dumpPackage, dumpAppId, needSep,
mAppProfiler.getTestPssMode(), mWakefulness.get());
@@ -9061,7 +9250,7 @@ public class ActivityManagerService extends IActivityManager.Stub
TimeUtils.formatDuration(now, mLastIdleTime, pw);
pw.print(" mLowRamSinceLastIdle=");
TimeUtils.formatDuration(
- mAppProfiler.getLowRamTimeSinceIdleLocked(now), pw);
+ mAppProfiler.getLowRamTimeSinceIdleLPr(now), pw);
pw.println();
pw.println();
@@ -9078,8 +9267,8 @@ public class ActivityManagerService extends IActivityManager.Stub
mUserController.dump(pw);
}
- @GuardedBy("this")
- void writeOtherProcessesInfoToProtoLocked(ProtoOutputStream proto, String dumpPackage,
+ @GuardedBy({"this", "mProcLock"})
+ void writeOtherProcessesInfoToProtoLSP(ProtoOutputStream proto, String dumpPackage,
int dumpAppId, int numPers) {
for (int i = 0, size = mActiveInstrumentation.size(); i < size; i++) {
ActiveInstrumentation ai = mActiveInstrumentation.get(i);
@@ -9096,7 +9285,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpPackage != null) {
synchronized (mPidsSelfLocked) {
- for (int i=0; i=0; i--) {
- ProcessRecord r = (ProcessRecord)list.get(i);
+ for (int i = list.size() - 1; i >= 0; i--) {
+ ProcessRecord r = (ProcessRecord) list.get(i);
if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
continue;
}
@@ -9595,8 +9783,8 @@ public class ActivityManagerService extends IActivityManager.Stub
ArrayList collectProcesses(PrintWriter pw, int start, boolean allPkgs,
String[] args) {
- synchronized (this) {
- return mProcessList.collectProcessesLocked(start, allPkgs, args);
+ synchronized (mProcLock) {
+ return mProcessList.collectProcessesLOSP(start, allPkgs, args);
}
}
@@ -9615,13 +9803,15 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = procs.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = procs.get(i);
- if (r.thread != null) {
- pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
+ final int pid = r.getPid();
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
+ pw.println("\n** Graphics info for pid " + pid + " [" + r.processName + "] **");
pw.flush();
try {
TransferPipe tp = new TransferPipe();
try {
- r.thread.dumpGfxInfo(tp.getWriteFd(), args);
+ thread.dumpGfxInfo(tp.getWriteFd(), args);
tp.go(fd);
} finally {
tp.kill();
@@ -9648,13 +9838,15 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = procs.size() - 1; i >= 0; i--) {
ProcessRecord r = procs.get(i);
- if (r.thread != null) {
- pw.println("\n\n** Cache info for pid " + r.pid + " [" + r.processName + "] **");
+ final int pid = r.getPid();
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
+ pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **");
pw.flush();
try {
TransferPipe tp = new TransferPipe();
try {
- r.thread.dumpCacheInfo(tp.getWriteFd(), args);
+ thread.dumpCacheInfo(tp.getWriteFd(), args);
tp.go(fd);
} finally {
tp.kill();
@@ -9681,13 +9873,15 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = procs.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = procs.get(i);
- if (r.thread != null) {
- pw.println("\n** Database info for pid " + r.pid + " [" + r.processName + "] **");
+ final int pid = r.getPid();
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
+ pw.println("\n** Database info for pid " + pid + " [" + r.processName + "] **");
pw.flush();
try {
TransferPipe tp = new TransferPipe();
try {
- r.thread.dumpDbInfo(tp.getWriteFd(), args);
+ thread.dumpDbInfo(tp.getWriteFd(), args);
tp.go(fd);
} finally {
tp.kill();
@@ -10150,10 +10344,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final int pid;
final int oomAdj;
final boolean hasActivities;
- synchronized (this) {
- thread = r.thread;
- pid = r.pid;
- oomAdj = r.getSetAdjWithServices();
+ synchronized (mProcLock) {
+ thread = r.getThread();
+ pid = r.getPid();
+ oomAdj = r.mState.getSetAdjWithServices();
hasActivities = r.hasActivities();
}
if (thread != null) {
@@ -10224,8 +10418,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final long myTotalRss = mi.getTotalRss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
- synchronized (this) {
- if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
+ synchronized (mProcLock) {
+ if (r.getThread() != null && oomAdj == r.mState.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
r.mProfile.addPss(myTotalPss, myTotalUss, myTotalRss, true,
reportType, endTime - startTime);
@@ -10735,10 +10929,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final int pid;
final int oomAdj;
final boolean hasActivities;
- synchronized (this) {
- thread = r.thread;
- pid = r.pid;
- oomAdj = r.getSetAdjWithServices();
+ synchronized (mProcLock) {
+ thread = r.getThread();
+ pid = r.getPid();
+ oomAdj = r.mState.getSetAdjWithServices();
hasActivities = r.hasActivities();
}
if (thread == null) {
@@ -10804,8 +10998,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final long myTotalRss = mi.getTotalRss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
- synchronized (this) {
- if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
+ synchronized (mProcLock) {
+ if (r.getThread() != null && oomAdj == r.mState.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
r.mProfile.addPss(myTotalPss, myTotalUss, myTotalRss, true,
reportType, endTime - startTime);
@@ -11144,96 +11338,26 @@ public class ActivityManagerService extends IActivityManager.Stub
* app that was passed in must remain on the process lists.
*/
@GuardedBy("this")
- final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
+ final boolean cleanUpApplicationRecordLocked(ProcessRecord app, int pid,
boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
- if (index >= 0) {
- removeLruProcessLocked(app);
- ProcessList.remove(app.pid);
- }
+ boolean restart;
+ synchronized (mProcLock) {
+ if (index >= 0) {
+ removeLruProcessLocked(app);
+ ProcessList.remove(pid);
+ }
+ restart = app.onCleanupApplicationRecordLSP(mProcessStats, allowRestart);
+ }
mAppProfiler.onCleanupApplicationRecordLocked(app);
-
- // Dismiss any open dialogs.
- app.getDialogController().clearAllErrorDialogs();
-
- app.setCrashing(false);
- app.setNotResponding(false);
-
- app.resetPackageList(mProcessStats);
- app.unlinkDeathRecipient();
- app.makeInactive(mProcessStats);
- app.waitingToKill = null;
- app.forcingToImportant = null;
- updateProcessForegroundLocked(app, false, 0, false);
- app.setHasForegroundActivities(false);
- app.hasShownUi = false;
- app.treatLikeActivity = false;
- app.hasAboveClient = false;
- app.setHasClientActivities(false);
-
- mServices.killServicesLocked(app, allowRestart);
- mPhantomProcessList.onAppDied(app.pid);
-
- boolean restart = false;
-
- // Remove published content providers.
- for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
- ContentProviderRecord cpr = app.pubProviders.valueAt(i);
- if (cpr.proc != app) {
- // If the hosting process record isn't really us, bail out
- continue;
- }
- final boolean alwaysRemove = app.bad || !allowRestart;
- final boolean inLaunching = mCpHelper.removeDyingProviderLocked(app, cpr, alwaysRemove);
- if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) {
- // We left the provider in the launching list, need to
- // restart it.
- restart = true;
- }
-
- cpr.provider = null;
- cpr.setProcess(null);
- }
- app.pubProviders.clear();
-
- // Take care of any launching providers waiting for this process.
- if (mCpHelper.cleanupAppInLaunchingProvidersLocked(app, false)) {
- mProcessList.noteProcessDiedLocked(app);
- restart = true;
- }
-
- // Unregister from connected content providers.
- if (!app.conProviders.isEmpty()) {
- for (int i = app.conProviders.size() - 1; i >= 0; i--) {
- ContentProviderConnection conn = app.conProviders.get(i);
- conn.provider.connections.remove(conn);
- stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
- conn.provider.appInfo.longVersionCode, conn.provider.name,
- conn.provider.info.processName);
- }
- app.conProviders.clear();
- }
-
- // At this point there may be remaining entries in mLaunchingProviders
- // where we were the only one waiting, so they are no longer of use.
- // Look for these and clean up if found.
- // XXX Commented out for now. Trying to figure out a way to reproduce
- // the actual situation to identify what is actually going on.
- if (false) {
- mCpHelper.cleanupLaunchingProvidersLocked();
- }
-
skipCurrentReceiverLocked(app);
-
- // Unregister any receivers.
- for (int i = app.receivers.size() - 1; i >= 0; i--) {
- removeReceiverLocked(app.receivers.valueAt(i));
- }
- app.receivers.clear();
+ updateProcessForegroundLocked(app, false, 0, false);
+ mServices.killServicesLocked(app, allowRestart);
+ mPhantomProcessList.onAppDied(pid);
// If the app is undergoing backup, tell the backup manager about it
final BackupRecord backupTarget = mBackupTargets.get(app.userId);
- if (backupTarget != null && app.pid == backupTarget.app.pid) {
+ if (backupTarget != null && pid == backupTarget.app.getPid()) {
if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
+ backupTarget.appInfo + " died during backup");
mHandler.post(new Runnable() {
@@ -11250,9 +11374,9 @@ public class ActivityManagerService extends IActivityManager.Stub
});
}
- mProcessList.scheduleDispatchProcessDiedLocked(app.pid, app.info.uid);
+ mProcessList.scheduleDispatchProcessDiedLocked(pid, app.info.uid);
- // If this is a precede instance of another process instance
+ // If this is a preceding instance of another process instance
allowRestart = true;
synchronized (app) {
if (app.mSuccessor != null) {
@@ -11260,13 +11384,13 @@ public class ActivityManagerService extends IActivityManager.Stub
// because we have created a new one already.
allowRestart = false;
// If it's persistent, add the successor to mPersistentStartingProcesses
- if (app.isPersistent() && !app.removed) {
+ if (app.isPersistent() && !app.isRemoved()) {
if (mPersistentStartingProcesses.indexOf(app.mSuccessor) < 0) {
mPersistentStartingProcesses.add(app.mSuccessor);
}
}
// clean up the field so the successor's proc starter could proceed.
- app.mSuccessor.mPrecedence = null;
+ app.mSuccessor.mPredecessor = null;
app.mSuccessor = null;
// Notify if anyone is waiting for it.
app.notifyAll();
@@ -11286,7 +11410,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mProcessList.removeProcessNameLocked(app.processName, app.uid, app);
}
mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
- } else if (!app.removed) {
+ } else if (!app.isRemoved()) {
// This app is persistent, so we need to keep its record around.
// If it is not already on the pending app list, add it there
// and start a new process for it.
@@ -11306,7 +11430,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// We have components that still need to be running in the
// process, so re-launch it.
if (index < 0) {
- ProcessList.remove(app.pid);
+ ProcessList.remove(pid);
}
// Remove provider publish timeout because we will start a new timeout when the
@@ -11314,14 +11438,13 @@ public class ActivityManagerService extends IActivityManager.Stub
mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, app);
mProcessList.addProcessNameLocked(app);
- app.pendingStart = false;
- mProcessList.startProcessLocked(app,
- new HostingRecord("restart", app.processName),
+ app.setPendingStart(false);
+ mProcessList.startProcessLocked(app, new HostingRecord("restart", app.processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return true;
- } else if (app.pid > 0 && app.pid != MY_PID) {
+ } else if (pid > 0 && pid != MY_PID) {
// Goodbye!
- removePidLocked(app);
+ removePidLocked(pid, app);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
if (app.isolated) {
@@ -11660,12 +11783,12 @@ public class ActivityManagerService extends IActivityManager.Stub
// process after the full backup is done and the ProcessRecord will vaporize anyway.
if (UserHandle.isApp(app.uid) &&
backupMode == ApplicationThreadConstants.BACKUP_MODE_FULL) {
- proc.inFullBackup = true;
+ proc.setInFullBackup(true);
}
r.app = proc;
final BackupRecord backupTarget = mBackupTargets.get(targetUserId);
oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
- newBackupUid = proc.inFullBackup ? r.appInfo.uid : -1;
+ newBackupUid = proc.isInFullBackup() ? r.appInfo.uid : -1;
mBackupTargets.put(targetUserId, r);
// Try not to kill the process during backup
@@ -11673,10 +11796,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// If the process is already attached, schedule the creation of the backup agent now.
// If it is not yet live, this will be done when it attaches to the framework.
- if (proc.thread != null) {
+ final IApplicationThread thread = proc.getThread();
+ if (thread != null) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "Agent proc already running: " + proc);
try {
- proc.thread.scheduleCreateBackupAgent(app,
+ thread.scheduleCreateBackupAgent(app,
compatibilityInfoForPackage(app), backupMode, targetUserId,
operationType);
} catch (RemoteException e) {
@@ -11786,14 +11910,15 @@ public class ActivityManagerService extends IActivityManager.Stub
// Not backing this app up any more; reset its OOM adjustment
final ProcessRecord proc = backupTarget.app;
updateOomAdjLocked(proc, true, OomAdjuster.OOM_ADJ_REASON_NONE);
- proc.inFullBackup = false;
+ proc.setInFullBackup(false);
oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
// If the app crashed during backup, 'thread' will be null here
- if (proc.thread != null) {
+ final IApplicationThread thread = proc.getThread();
+ if (thread != null) {
try {
- proc.thread.scheduleDestroyBackupAgent(appInfo,
+ thread.scheduleDestroyBackupAgent(appInfo,
compatibilityInfoForPackage(appInfo), userId);
} catch (Exception e) {
Slog.e(TAG, "Exception when unbinding backup agent:");
@@ -11888,7 +12013,7 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean instantApp;
synchronized(this) {
if (caller != null) {
- callerApp = getRecordForAppLocked(caller);
+ callerApp = getRecordForAppLOSP(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
@@ -11902,7 +12027,7 @@ public class ActivityManagerService extends IActivityManager.Stub
+ " is not running in process " + callerApp);
}
callingUid = callerApp.info.uid;
- callingPid = callerApp.pid;
+ callingPid = callerApp.getPid();
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
@@ -11971,8 +12096,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (this) {
- if (callerApp != null && (callerApp.thread == null
- || callerApp.thread.asBinder() != caller.asBinder())) {
+ IApplicationThread thread;
+ if (callerApp != null && ((thread = callerApp.getThread()) == null
+ || thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
@@ -11981,13 +12107,13 @@ public class ActivityManagerService extends IActivityManager.Stub
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
- final int totalReceiversForApp = rl.app.receivers.size();
+ final int totalReceiversForApp = rl.app.mReceivers.numberOfReceivers();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
- rl.app.receivers.add(rl);
+ rl.app.mReceivers.addReceiver(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
@@ -12073,7 +12199,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (rl.app != null) {
- rl.app.receivers.remove(rl);
+ rl.app.mReceivers.removeReceiver(rl);
}
removeReceiverLocked(rl);
if (rl.linkedToDeath) {
@@ -12372,7 +12498,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
if (brOptions.isDontSendToRestrictedApps()
- && !isUidActiveLocked(callingUid)
+ && !isUidActiveLOSP(callingUid)
&& isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
+ " has background restrictions");
@@ -12579,12 +12705,14 @@ public class ActivityManagerService extends IActivityManager.Stub
if (killProcess) {
final int extraUid = intent.getIntExtra(Intent.EXTRA_UID,
-1);
- mProcessList.killPackageProcessesLocked(ssp,
- UserHandle.getAppId(extraUid),
- userId, ProcessList.INVALID_ADJ,
- ApplicationExitInfo.REASON_USER_REQUESTED,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- "change " + ssp);
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(ssp,
+ UserHandle.getAppId(extraUid),
+ userId, ProcessList.INVALID_ADJ,
+ ApplicationExitInfo.REASON_USER_REQUESTED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "change " + ssp);
+ }
}
cleanupDisabledPackageComponentsLocked(ssp, userId,
intent.getStringArrayExtra(
@@ -12728,7 +12856,7 @@ public class ActivityManagerService extends IActivityManager.Stub
Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
final int uid = getUidFromIntent(intent);
if (uid != -1) {
- final UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
+ final UidRecord uidRec = mProcessList.getUidRecordLOSP(uid);
if (uidRec != null) {
uidRec.updateHasInternetPermission();
}
@@ -13113,7 +13241,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
intent = verifyBroadcastLocked(intent);
- final ProcessRecord callerApp = getRecordForAppLocked(caller);
+ final ProcessRecord callerApp = getRecordForAppLOSP(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
@@ -13353,27 +13481,29 @@ public class ActivityManagerService extends IActivityManager.Stub
final long origId = Binder.clearCallingIdentity();
ProcessRecord app;
- if (noRestart) {
- app = getProcessRecordLocked(ai.processName, ai.uid, true);
- } else {
- // Instrumentation can kill and relaunch even persistent processes
- forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId,
- "start instr");
- // Inform usage stats to make the target package active
- if (mUsageStatsService != null) {
- mUsageStatsService.reportEvent(ii.targetPackage, userId,
- UsageEvents.Event.SYSTEM_INTERACTION);
+ synchronized (mProcLock) {
+ if (noRestart) {
+ app = getProcessRecordLocked(ai.processName, ai.uid, true);
+ } else {
+ // Instrumentation can kill and relaunch even persistent processes
+ forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false,
+ userId, "start instr");
+ // Inform usage stats to make the target package active
+ if (mUsageStatsService != null) {
+ mUsageStatsService.reportEvent(ii.targetPackage, userId,
+ UsageEvents.Event.SYSTEM_INTERACTION);
+ }
+ app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, abiOverride,
+ ZYGOTE_POLICY_FLAG_EMPTY);
}
- app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, abiOverride,
- ZYGOTE_POLICY_FLAG_EMPTY);
- }
- app.setActiveInstrumentation(activeInstr);
- activeInstr.mFinished = false;
- activeInstr.mSourceUid = callingUid;
- activeInstr.mRunningProcesses.add(app);
- if (!mActiveInstrumentation.contains(activeInstr)) {
- mActiveInstrumentation.add(activeInstr);
+ app.setActiveInstrumentation(activeInstr);
+ activeInstr.mFinished = false;
+ activeInstr.mSourceUid = callingUid;
+ activeInstr.mRunningProcesses.add(app);
+ if (!mActiveInstrumentation.contains(activeInstr)) {
+ mActiveInstrumentation.add(activeInstr);
+ }
}
if ((flags & INSTR_FLAG_DISABLE_ISOLATED_STORAGE) != 0) {
@@ -13400,7 +13530,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
try {
- pr.thread.instrumentWithoutRestart(
+ pr.getThread().instrumentWithoutRestart(
activeInstr.mClass,
activeInstr.mArguments,
activeInstr.mWatcher,
@@ -13460,7 +13590,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized(this) {
- ProcessRecord app = getRecordForAppLocked(target);
+ ProcessRecord app = getRecordForAppLOSP(target);
if (app == null) {
Slog.w(TAG, "addInstrumentationResults: no app for " + target);
return;
@@ -13482,36 +13612,38 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
- if (!instr.mFinished) {
- if (instr.mWatcher != null) {
- Bundle finalResults = instr.mCurResults;
- if (finalResults != null) {
- if (instr.mCurResults != null && results != null) {
- finalResults.putAll(results);
+ synchronized (mProcLock) {
+ if (!instr.mFinished) {
+ if (instr.mWatcher != null) {
+ Bundle finalResults = instr.mCurResults;
+ if (finalResults != null) {
+ if (instr.mCurResults != null && results != null) {
+ finalResults.putAll(results);
+ }
+ } else {
+ finalResults = results;
}
- } else {
- finalResults = results;
+ mInstrumentationReporter.reportFinished(instr.mWatcher,
+ instr.mClass, resultCode, finalResults);
}
- mInstrumentationReporter.reportFinished(instr.mWatcher,
- instr.mClass, resultCode, finalResults);
+
+ // Can't call out of the system process with a lock held, so post a message.
+ if (instr.mUiAutomationConnection != null) {
+ // Go back to the default mode of denying OP_NO_ISOLATED_STORAGE app op.
+ mAppOpsService.setMode(AppOpsManager.OP_NO_ISOLATED_STORAGE, app.uid,
+ app.info.packageName, AppOpsManager.MODE_ERRORED);
+ mAppOpsService.setAppOpsServiceDelegate(null);
+ getPermissionManagerInternal().stopShellPermissionIdentityDelegation();
+ mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
+ instr.mUiAutomationConnection).sendToTarget();
+ }
+ instr.mFinished = true;
}
- // Can't call out of the system process with a lock held, so post a message.
- if (instr.mUiAutomationConnection != null) {
- // Go back to the default mode of denying OP_NO_ISOLATED_STORAGE app op.
- mAppOpsService.setMode(AppOpsManager.OP_NO_ISOLATED_STORAGE, app.uid,
- app.info.packageName, AppOpsManager.MODE_ERRORED);
- mAppOpsService.setAppOpsServiceDelegate(null);
- getPermissionManagerInternal().stopShellPermissionIdentityDelegation();
- mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
- instr.mUiAutomationConnection).sendToTarget();
- }
- instr.mFinished = true;
+ instr.removeProcess(app);
+ app.setActiveInstrumentation(null);
}
- instr.removeProcess(app);
- app.setActiveInstrumentation(null);
-
if (!instr.mNoRestart) {
forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false,
app.userId,
@@ -13547,7 +13679,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized(this) {
- ProcessRecord app = getRecordForAppLocked(target);
+ ProcessRecord app = getRecordForAppLOSP(target);
if (app == null) {
Slog.w(TAG, "finishInstrumentation: no app for " + target);
return;
@@ -13653,10 +13785,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// the current [or imminent] receiver on.
boolean isReceivingBroadcastLocked(ProcessRecord app,
ArraySet receivingQueues) {
- final int N = app.curReceivers.size();
- if (N > 0) {
- for (int i = 0; i < N; i++) {
- receivingQueues.add(app.curReceivers.valueAt(i).queue);
+ final ProcessReceiverRecord prr = app.mReceivers;
+ final int numOfReceivers = prr.numberOfCurReceivers();
+ if (numOfReceivers > 0) {
+ for (int i = 0; i < numOfReceivers; i++) {
+ receivingQueues.add(prr.getCurReceiverAt(i).queue);
}
return true;
}
@@ -13775,6 +13908,7 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* Returns true if things are idle enough to perform GCs.
*/
+ @GuardedBy("this")
final boolean canGcNowLocked() {
for (BroadcastQueue q : mBroadcastQueues) {
if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isEmpty()) {
@@ -13787,77 +13921,91 @@ public class ActivityManagerService extends IActivityManager.Stub
private void checkExcessivePowerUsage() {
updateCpuStatsNow();
- synchronized (this) {
- boolean doCpuKills = true;
- if (mLastPowerCheckUptime == 0) {
- doCpuKills = false;
- }
+ synchronized (mProcLock) {
+ final boolean doCpuKills = mLastPowerCheckUptime != 0;
final long curUptime = SystemClock.uptimeMillis();
final long uptimeSince = curUptime - mLastPowerCheckUptime;
mLastPowerCheckUptime = curUptime;
- int i = mProcessList.mLruProcesses.size();
- while (i > 0) {
- i--;
- final ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
+ mProcessList.forEachLruProcessesLOSP(false, app -> {
+ if (app.mState.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
int cpuLimit;
- long checkDur = curUptime - app.getWhenUnimportant();
+ long checkDur = curUptime - app.mState.getWhenUnimportant();
if (checkDur <= mConstants.POWER_CHECK_INTERVAL) {
cpuLimit = mConstants.POWER_CHECK_MAX_CPU_1;
} else if (checkDur <= (mConstants.POWER_CHECK_INTERVAL * 2)
- || app.setProcState <= ActivityManager.PROCESS_STATE_HOME) {
+ || app.mState.getSetProcState() <= ActivityManager.PROCESS_STATE_HOME) {
cpuLimit = mConstants.POWER_CHECK_MAX_CPU_2;
} else if (checkDur <= (mConstants.POWER_CHECK_INTERVAL * 3)) {
cpuLimit = mConstants.POWER_CHECK_MAX_CPU_3;
} else {
cpuLimit = mConstants.POWER_CHECK_MAX_CPU_4;
}
- synchronized (mAppProfiler.mProfilerLock) {
- final ProcessProfileRecord profile = app.mProfile;
- final long curCpuTime = profile.mCurCpuTime.get();
- final long lastCpuTime = profile.mLastCpuTime.get();
- if (lastCpuTime > 0) {
- final long cputimeUsed = curCpuTime - lastCpuTime;
- if (checkExcessivePowerUsageLocked(uptimeSince, doCpuKills, cputimeUsed,
- app.processName, app.toShortString(), cpuLimit, app)) {
- app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
- + " dur=" + checkDur + " limit=" + cpuLimit,
- ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
- ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
- true);
- profile.reportExcessiveCpu();
- }
- }
- profile.mLastCpuTime.set(curCpuTime);
- }
+ updateAppProcessCpuTimeLPr(uptimeSince, doCpuKills, checkDur, cpuLimit, app);
// Also check the phantom processes if there is any
- final long chkDur = checkDur;
- final int cpuLmt = cpuLimit;
- final boolean doKill = doCpuKills;
- mPhantomProcessList.forEachPhantomProcessOfApp(app, r -> {
- if (r.mLastCputime > 0) {
- final long cputimeUsed = r.mCurrentCputime - r.mLastCputime;
- if (checkExcessivePowerUsageLocked(uptimeSince, doKill, cputimeUsed,
- app.processName, r.toString(), cpuLimit, app)) {
- mPhantomProcessList.killPhantomProcessGroupLocked(app, r,
- ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
- ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
- "excessive cpu " + cputimeUsed + " during "
- + uptimeSince + " dur=" + chkDur + " limit=" + cpuLmt);
- return false;
- }
- }
- r.mLastCputime = r.mCurrentCputime;
- return true;
- });
+ updatePhantomProcessCpuTimeLPr(
+ uptimeSince, doCpuKills, checkDur, cpuLimit, app);
}
- }
+ });
}
}
- private boolean checkExcessivePowerUsageLocked(final long uptimeSince, boolean doCpuKills,
+ @GuardedBy("mProcLock")
+ private void updateAppProcessCpuTimeLPr(final long uptimeSince, final boolean doCpuKills,
+ final long checkDur, final int cpuLimit, final ProcessRecord app) {
+ synchronized (mAppProfiler.mProfilerLock) {
+ final ProcessProfileRecord profile = app.mProfile;
+ final long curCpuTime = profile.mCurCpuTime.get();
+ final long lastCpuTime = profile.mLastCpuTime.get();
+ if (lastCpuTime > 0) {
+ final long cpuTimeUsed = curCpuTime - lastCpuTime;
+ if (checkExcessivePowerUsageLPr(uptimeSince, doCpuKills, cpuTimeUsed,
+ app.processName, app.toShortString(), cpuLimit, app)) {
+ mHandler.post(() -> {
+ synchronized (ActivityManagerService.this) {
+ app.killLocked("excessive cpu " + cpuTimeUsed + " during "
+ + uptimeSince + " dur=" + checkDur + " limit=" + cpuLimit,
+ ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+ ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
+ true);
+ }
+ });
+ profile.reportExcessiveCpu();
+ }
+ }
+
+ profile.mLastCpuTime.set(curCpuTime);
+ }
+ }
+
+ @GuardedBy("mProcLock")
+ private void updatePhantomProcessCpuTimeLPr(final long uptimeSince, final boolean doCpuKills,
+ final long checkDur, final int cpuLimit, final ProcessRecord app) {
+ mPhantomProcessList.forEachPhantomProcessOfApp(app, r -> {
+ if (r.mLastCputime > 0) {
+ final long cpuTimeUsed = r.mCurrentCputime - r.mLastCputime;
+ if (checkExcessivePowerUsageLPr(uptimeSince, doCpuKills, cpuTimeUsed,
+ app.processName, r.toString(), cpuLimit, app)) {
+ mHandler.post(() -> {
+ synchronized (ActivityManagerService.this) {
+ mPhantomProcessList.killPhantomProcessGroupLocked(app, r,
+ ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+ ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
+ "excessive cpu " + cpuTimeUsed + " during "
+ + uptimeSince + " dur=" + checkDur + " limit=" + cpuLimit);
+ }
+ });
+ return false;
+ }
+ }
+ r.mLastCputime = r.mCurrentCputime;
+ return true;
+ });
+ }
+
+ @GuardedBy("mProcLock")
+ private boolean checkExcessivePowerUsageLPr(final long uptimeSince, boolean doCpuKills,
final long cputimeUsed, final String processName, final String description,
final int cpuLimit, final ProcessRecord app) {
if (DEBUG_POWER) {
@@ -13902,19 +14050,20 @@ public class ActivityManagerService extends IActivityManager.Stub
UserHandle.getUserId(uid), packages[0]);
}
+ @GuardedBy("this")
void enqueueUidChangeLocked(UidRecord uidRec, int uid, int change) {
- uid = uidRec != null ? uidRec.uid : uid;
+ uid = uidRec != null ? uidRec.getUid() : uid;
if (uid < 0) {
throw new IllegalArgumentException("No UidRecord or uid");
}
final int procState = uidRec != null
- ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT;
+ ? uidRec.getSetProcState() : PROCESS_STATE_NONEXISTENT;
final long procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
- final int capability = uidRec != null ? uidRec.setCapability : 0;
- final boolean ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid);
+ final int capability = uidRec != null ? uidRec.getSetCapability() : 0;
+ final boolean ephemeral = uidRec != null ? uidRec.isEphemeral() : isEphemeralLocked(uid);
- if (uidRec != null && !uidRec.idle && (change & UidRecord.CHANGE_GONE) != 0) {
+ if (uidRec != null && !uidRec.isIdle() && (change & UidRecord.CHANGE_GONE) != 0) {
// If this uid is going away, and we haven't yet reported it is gone,
// then do so now.
change |= UidRecord.CHANGE_IDLE;
@@ -13923,7 +14072,7 @@ public class ActivityManagerService extends IActivityManager.Stub
uidRec == null ? null : uidRec.pendingChange,
uid, change, procState, procStateSeq, capability, ephemeral);
if (uidRec != null) {
- uidRec.lastReportedChange = enqueuedChange;
+ uidRec.setLastReportedChange(enqueuedChange);
uidRec.updateLastDispatchedProcStateSeq(enqueuedChange);
}
@@ -13946,21 +14095,21 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
- synchronized (mProcessStats.mLock) {
- if (proc.thread != null) {
- proc.mProfile.setProcessTrackerState(
- proc.getReportedProcState(), memFactor, now);
- }
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ final void setProcessTrackerStateLOSP(ProcessRecord proc, int memFactor, long now) {
+ if (proc.getThread() != null) {
+ proc.mProfile.setProcessTrackerState(
+ proc.mState.getReportedProcState(), memFactor, now);
}
}
@GuardedBy("this")
final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
int fgServiceTypes, boolean oomAdj) {
- if (isForeground != proc.hasForegroundServices()
- || proc.getForegroundServiceTypes() != fgServiceTypes) {
- proc.setHasForegroundServices(isForeground, fgServiceTypes);
+ final ProcessServiceRecord psr = proc.mServices;
+ if (isForeground != psr.hasForegroundServices()
+ || psr.getForegroundServiceTypes() != fgServiceTypes) {
+ psr.setHasForegroundServices(isForeground, fgServiceTypes);
ArrayList curProcs = mForegroundPackages.get(proc.info.packageName,
proc.info.uid);
if (isForeground) {
@@ -13986,9 +14135,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- proc.setReportedForegroundServiceTypes(fgServiceTypes);
+ psr.setReportedForegroundServiceTypes(fgServiceTypes);
ProcessChangeItem item = mProcessList.enqueueProcessChangeItemLocked(
- proc.pid, proc.info.uid);
+ proc.getPid(), proc.info.uid);
item.changes |= ProcessChangeItem.CHANGE_FOREGROUND_SERVICES;
item.foregroundServiceTypes = fgServiceTypes;
}
@@ -14031,7 +14180,6 @@ public class ActivityManagerService extends IActivityManager.Stub
} finally {
Binder.restoreCallingIdentity(identity);
}
-
}
}
return r;
@@ -14141,17 +14289,20 @@ public class ActivityManagerService extends IActivityManager.Stub
final int appId = UserHandle.getAppId(pkgUid);
for (int i = mProcessList.mActiveUids.size() - 1; i >= 0; i--) {
final UidRecord uidRec = mProcessList.mActiveUids.valueAt(i);
- final long bgTime = uidRec.lastBackgroundTime;
- if (bgTime > 0 && !uidRec.idle) {
- if (UserHandle.getAppId(uidRec.uid) == appId) {
+ final long bgTime = uidRec.getLastBackgroundTime();
+ if (bgTime > 0 && !uidRec.isIdle()) {
+ final int uid = uidRec.getUid();
+ if (UserHandle.getAppId(uid) == appId) {
if (userId == UserHandle.USER_ALL
- || userId == UserHandle.getUserId(uidRec.uid)) {
- EventLogTags.writeAmUidIdle(uidRec.uid);
- uidRec.idle = true;
- uidRec.setIdle = true;
- Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uidRec.uid)
+ || userId == UserHandle.getUserId(uid)) {
+ EventLogTags.writeAmUidIdle(uid);
+ synchronized (mProcLock) {
+ uidRec.setIdle(true);
+ uidRec.setSetIdle(true);
+ }
+ Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uid)
+ " from package " + packageName + " user " + userId);
- doStopUidLocked(uidRec.uid, uidRec);
+ doStopUidLocked(uid, uidRec);
}
}
}
@@ -14176,11 +14327,11 @@ public class ActivityManagerService extends IActivityManager.Stub
final void runInBackgroundDisabled(int uid) {
synchronized (this) {
- UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
+ UidRecord uidRec = mProcessList.getUidRecordLOSP(uid);
if (uidRec != null) {
// This uid is actually running... should it be considered background now?
- if (uidRec.idle) {
- doStopUidLocked(uidRec.uid, uidRec);
+ if (uidRec.isIdle()) {
+ doStopUidLocked(uidRec.getUid(), uidRec);
}
} else {
// This uid isn't actually running... still send a report about it being "stopped".
@@ -14234,7 +14385,7 @@ public class ActivityManagerService extends IActivityManager.Stub
+ callerPid);
return;
}
- if (!pr.mAllowlistManager) {
+ if (!pr.mServices.mAllowlistManager) {
if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
!= PackageManager.PERMISSION_GRANTED
&& checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callerPid, callerUid)
@@ -14258,13 +14409,15 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
@GuardedBy("this")
void tempAllowlistUidLocked(int targetUid, long duration, String tag, int type) {
- mPendingTempAllowlist.put(targetUid,
- new PendingTempAllowlist(targetUid, duration, tag, type));
- setUidTempAllowlistStateLocked(targetUid, true);
- mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget();
+ synchronized (mProcLock) {
+ mPendingTempAllowlist.put(targetUid,
+ new PendingTempAllowlist(targetUid, duration, tag, type));
+ setUidTempAllowlistStateLSP(targetUid, true);
+ mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget();
- if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
- mFgsStartTempAllowList.add(targetUid, duration);
+ if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+ mFgsStartTempAllowList.add(targetUid, duration);
+ }
}
}
@@ -14274,7 +14427,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// First copy out the pending changes... we need to leave them in the map for now,
// in case someone needs to check what is coming up while we don't have the lock held.
- synchronized(this) {
+ synchronized (mProcLock) {
N = mPendingTempAllowlist.size();
list = new PendingTempAllowlist[N];
for (int i = 0; i < N; i++) {
@@ -14294,25 +14447,27 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// And now we can safely remove them from the map.
- synchronized(this) {
- for (int i = 0; i < N; i++) {
- PendingTempAllowlist ptw = list[i];
- int index = mPendingTempAllowlist.indexOfKey(ptw.targetUid);
- if (index >= 0 && mPendingTempAllowlist.valueAt(index) == ptw) {
- mPendingTempAllowlist.removeAt(index);
+ synchronized (this) {
+ synchronized (mProcLock) {
+ for (int i = 0; i < N; i++) {
+ PendingTempAllowlist ptw = list[i];
+ int index = mPendingTempAllowlist.indexOfKey(ptw.targetUid);
+ if (index >= 0 && mPendingTempAllowlist.valueAt(index) == ptw) {
+ mPendingTempAllowlist.removeAt(index);
+ }
}
}
}
}
- @GuardedBy("this")
- final void setAppIdTempAllowlistStateLocked(int uid, boolean onAllowlist) {
- mOomAdjuster.setAppIdTempAllowlistStateLocked(uid, onAllowlist);
+ @GuardedBy({"this", "mProcLock"})
+ final void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
+ mOomAdjuster.setAppIdTempAllowlistStateLSP(uid, onAllowlist);
}
- @GuardedBy("this")
- final void setUidTempAllowlistStateLocked(int uid, boolean onAllowlist) {
- mOomAdjuster.setUidTempAllowlistStateLocked(uid, onAllowlist);
+ @GuardedBy({"this", "mProcLock"})
+ final void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
+ mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
}
private void trimApplications(boolean forceFullOomAdj, String oomAdjReason) {
@@ -14329,26 +14484,28 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = mProcessList.mRemovedProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mProcessList.mRemovedProcesses.get(i);
if (!app.hasActivitiesOrRecentTasks()
- && app.curReceivers.isEmpty() && app.numberOfRunningServices() == 0) {
- Slog.i(
- TAG, "Exiting empty application process "
- + app.toShortString() + " ("
- + (app.thread != null ? app.thread.asBinder() : null)
- + ")\n");
- if (app.pid > 0 && app.pid != MY_PID) {
- app.kill("empty",
+ && app.mReceivers.numberOfCurReceivers() == 0
+ && app.mServices.numberOfRunningServices() == 0) {
+ final IApplicationThread thread = app.getThread();
+ Slog.i(TAG, "Exiting empty application process "
+ + app.toShortString() + " ("
+ + (thread != null ? thread.asBinder() : null)
+ + ")\n");
+ final int pid = app.getPid();
+ if (pid > 0 && pid != MY_PID) {
+ app.killLocked("empty",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
false);
- } else if (app.thread != null) {
+ } else if (thread != null) {
try {
- app.thread.scheduleExit();
+ thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
didSomething = true;
- cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
+ cleanUpApplicationRecordLocked(app, pid, false, true, -1, false /*replacingPid*/);
mProcessList.mRemovedProcesses.remove(i);
if (app.isPersistent()) {
@@ -14369,7 +14526,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/** This method sends the specified signal to each of the persistent apps */
- public void signalPersistentProcesses(int sig) throws RemoteException {
+ public void signalPersistentProcesses(final int sig) throws RemoteException {
if (sig != SIGNAL_USR1) {
throw new SecurityException("Only SIGNAL_USR1 is allowed");
}
@@ -14380,13 +14537,12 @@ public class ActivityManagerService extends IActivityManager.Stub
+ android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
}
- synchronized (this) {
- for (int i = mProcessList.mLruProcesses.size() - 1 ; i >= 0 ; i--) {
- ProcessRecord r = mProcessList.mLruProcesses.get(i);
- if (r.thread != null && r.isPersistent()) {
- sendSignal(r.pid, sig);
+ synchronized (mProcLock) {
+ mProcessList.forEachLruProcessesLOSP(false, app -> {
+ if (app.getThread() != null && app.isPersistent()) {
+ sendSignal(app.getPid(), sig);
}
- }
+ });
}
}
@@ -14405,21 +14561,23 @@ public class ActivityManagerService extends IActivityManager.Stub
}
ProcessRecord proc = null;
- synchronized (this) {
+ synchronized (mProcLock) {
if (process != null) {
- proc = findProcessLocked(process, userId, "profileControl");
+ proc = findProcessLOSP(process, userId, "profileControl");
}
- if (start && (proc == null || proc.thread == null)) {
+ if (start && (proc == null || proc.getThread() == null)) {
throw new IllegalArgumentException("Unknown process: " + process);
}
}
+
synchronized (mAppProfiler.mProfilerLock) {
return mAppProfiler.profileControlLPf(proc, start, profilerInfo, profileType);
}
}
- private ProcessRecord findProcessLocked(String process, int userId, String callName) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ private ProcessRecord findProcessLOSP(String process, int userId, String callName) {
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, ALLOW_FULL_ONLY, callName, null);
ProcessRecord proc = null;
@@ -14432,8 +14590,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
if (proc == null) {
- ArrayMap> all
- = mProcessList.mProcessNames.getMap();
+ ArrayMap> all =
+ mProcessList.getProcessNamesLOSP().getMap();
SparseArray procs = all.get(process);
if (procs != null && procs.size() > 0) {
proc = procs.valueAt(0);
@@ -14455,7 +14613,6 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
-
try {
// note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
// its own permission (same as profileControl).
@@ -14469,9 +14626,10 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("null fd");
}
- synchronized (this) {
- ProcessRecord proc = findProcessLocked(process, userId, "dumpHeap");
- if (proc == null || proc.thread == null) {
+ synchronized (mProcLock) {
+ ProcessRecord proc = findProcessLOSP(process, userId, "dumpHeap");
+ IApplicationThread thread;
+ if (proc == null || (thread = proc.getThread()) == null) {
throw new IllegalArgumentException("Unknown process: " + process);
}
@@ -14493,7 +14651,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}, null);
- proc.thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
+ thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
fd = null;
return true;
}
@@ -14548,8 +14706,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
void onCoreSettingsChange(Bundle settings) {
- synchronized (this) {
- mProcessList.updateCoreSettingsLocked(settings);
+ synchronized (mProcLock) {
+ mProcessList.updateCoreSettingsLOSP(settings);
}
}
@@ -14701,8 +14859,9 @@ public class ActivityManagerService extends IActivityManager.Stub
return info;
}
- private boolean processSanityChecksLocked(ProcessRecord process) {
- if (process == null || process.thread == null) {
+ @GuardedBy("mProcLock")
+ private boolean processSanityChecksLPr(ProcessRecord process, IApplicationThread thread) {
+ if (process == null || thread == null) {
return false;
}
@@ -14724,34 +14883,36 @@ public class ActivityManagerService extends IActivityManager.Stub
+ android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
- synchronized (this) {
+ synchronized (mProcLock) {
mBinderTransactionTrackingEnabled = true;
- for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
- ProcessRecord process = mProcessList.mLruProcesses.get(i);
- if (!processSanityChecksLocked(process)) {
- continue;
+ mProcessList.forEachLruProcessesLOSP(true, process -> {
+ final IApplicationThread thread = process.getThread();
+ if (!processSanityChecksLPr(process, thread)) {
+ return;
}
try {
- process.thread.startBinderTracking();
+ thread.startBinderTracking();
} catch (RemoteException e) {
Log.v(TAG, "Process disappared");
}
- }
- return true;
+ });
}
+ return true;
}
- public boolean stopBinderTrackingAndDump(ParcelFileDescriptor fd) throws RemoteException {
- try {
- // TODO: hijacking SET_ACTIVITY_WATCHER, but should be changed to its own
- // permission (same as profileControl).
- if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires permission "
- + android.Manifest.permission.SET_ACTIVITY_WATCHER);
- }
+ @Override
+ public boolean stopBinderTrackingAndDump(final ParcelFileDescriptor fd) throws RemoteException {
+ // TODO: hijacking SET_ACTIVITY_WATCHER, but should be changed to its own
+ // permission (same as profileControl).
+ if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SET_ACTIVITY_WATCHER);
+ }
- synchronized (this) {
+ boolean closeFd = true;
+ try {
+ synchronized (mProcLock) {
if (fd == null) {
throw new IllegalArgumentException("null fd");
}
@@ -14759,9 +14920,10 @@ public class ActivityManagerService extends IActivityManager.Stub
PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd.getFileDescriptor()));
pw.println("Binder transaction traces for all processes.\n");
- for (ProcessRecord process : mProcessList.mLruProcesses) {
- if (!processSanityChecksLocked(process)) {
- continue;
+ mProcessList.forEachLruProcessesLOSP(true, process -> {
+ final IApplicationThread thread = process.getThread();
+ if (!processSanityChecksLPr(process, thread)) {
+ return;
}
pw.println("Traces for process: " + process.processName);
@@ -14769,7 +14931,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
TransferPipe tp = new TransferPipe();
try {
- process.thread.stopBinderTrackingAndDump(tp.getWriteFd());
+ thread.stopBinderTrackingAndDump(tp.getWriteFd());
tp.go(fd.getFileDescriptor());
} finally {
tp.kill();
@@ -14783,12 +14945,12 @@ public class ActivityManagerService extends IActivityManager.Stub
process + ". Exception: " + e);
pw.flush();
}
- }
- fd = null;
+ });
+ closeFd = false;
return true;
}
} finally {
- if (fd != null) {
+ if (fd != null && closeFd) {
try {
fd.close();
} catch (IOException e) {
@@ -14833,12 +14995,12 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void killForegroundAppsForUser(@UserIdInt int userId) {
- synchronized (ActivityManagerService.this) {
- final ArrayList procs = new ArrayList<>();
- final int NP = mProcessList.mProcessNames.getMap().size();
- for (int ip = 0; ip < NP; ip++) {
+ final ArrayList procs = new ArrayList<>();
+ synchronized (mProcLock) {
+ final int numOfProcs = mProcessList.getProcessNamesLOSP().getMap().size();
+ for (int ip = 0; ip < numOfProcs; ip++) {
final SparseArray apps =
- mProcessList.mProcessNames.getMap().valueAt(ip);
+ mProcessList.getProcessNamesLOSP().getMap().valueAt(ip);
final int NA = apps.size();
for (int ia = 0; ia < NA; ia++) {
final ProcessRecord app = apps.valueAt(ia);
@@ -14846,19 +15008,23 @@ public class ActivityManagerService extends IActivityManager.Stub
// We don't kill persistent processes.
continue;
}
- if (app.removed
- || (app.userId == userId && app.hasForegroundActivities())) {
+ if (app.isRemoved()
+ || (app.userId == userId && app.mState.hasForegroundActivities())) {
procs.add(app);
}
}
}
+ }
- final int N = procs.size();
- for (int i = 0; i < N; i++) {
- mProcessList.removeProcessLocked(procs.get(i), false, true,
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_KILL_ALL_FG,
- "kill all fg");
+ final int numOfProcs = procs.size();
+ if (numOfProcs > 0) {
+ synchronized (ActivityManagerService.this) {
+ for (int i = 0; i < numOfProcs; i++) {
+ mProcessList.removeProcessLocked(procs.get(i), false, true,
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_ALL_FG,
+ "kill all fg");
+ }
}
}
}
@@ -14904,8 +15070,10 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void setDeviceIdleWhitelist(int[] allAppids, int[] exceptIdleAppids) {
synchronized (ActivityManagerService.this) {
- mDeviceIdleAllowlist = allAppids;
- mDeviceIdleExceptIdleAllowlist = exceptIdleAppids;
+ synchronized (mProcLock) {
+ mDeviceIdleAllowlist = allAppids;
+ mDeviceIdleExceptIdleAllowlist = exceptIdleAppids;
+ }
}
}
@@ -14913,13 +15081,15 @@ public class ActivityManagerService extends IActivityManager.Stub
public void updateDeviceIdleTempWhitelist(int[] appids, int changingUid, boolean adding,
long durationMs, @TempAllowListType int type) {
synchronized (ActivityManagerService.this) {
- mDeviceIdleTempAllowlist = appids;
- if (adding) {
- if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
- mFgsStartTempAllowList.add(changingUid, durationMs);
+ synchronized (mProcLock) {
+ mDeviceIdleTempAllowlist = appids;
+ if (adding) {
+ if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
+ mFgsStartTempAllowList.add(changingUid, durationMs);
+ }
}
+ setAppIdTempAllowlistStateLSP(changingUid, adding);
}
- setAppIdTempAllowlistStateLocked(changingUid, adding);
}
}
@@ -14957,10 +15127,10 @@ public class ActivityManagerService extends IActivityManager.Stub
return;
}
}
- if (pr.hasOverlayUi() == hasOverlayUi) {
+ if (pr.mState.hasOverlayUi() == hasOverlayUi) {
return;
}
- pr.setHasOverlayUi(hasOverlayUi);
+ pr.mState.setHasOverlayUi(hasOverlayUi);
//Slog.i(TAG, "Setting hasOverlayUi=" + pr.hasOverlayUi + " for pid=" + pid);
updateOomAdjLocked(pr, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
}
@@ -14978,8 +15148,8 @@ public class ActivityManagerService extends IActivityManager.Stub
+ uid + " seq: " + procStateSeq);
}
UidRecord record;
- synchronized (ActivityManagerService.this) {
- record = mProcessList.getUidRecordLocked(uid);
+ synchronized (mProcLock) {
+ record = mProcessList.getUidRecordLOSP(uid);
if (record == null) {
if (DEBUG_NETWORK) {
Slog.d(TAG_NETWORK, "No active uidRecord for uid: " + uid
@@ -15042,19 +15212,21 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean isUidActive(int uid) {
- synchronized (ActivityManagerService.this) {
- return isUidActiveLocked(uid);
+ synchronized (mProcLock) {
+ return isUidActiveLOSP(uid);
}
}
@Override
public List getMemoryStateForProcesses() {
List processMemoryStates = new ArrayList<>();
- synchronized (mPidsSelfLocked) {
- for (int i = 0, size = mPidsSelfLocked.size(); i < size; i++) {
- final ProcessRecord r = mPidsSelfLocked.valueAt(i);
- processMemoryStates.add(
- new ProcessMemoryState(r.uid, r.pid, r.processName, r.curAdj));
+ synchronized (mProcLock) {
+ synchronized (mPidsSelfLocked) {
+ for (int i = 0, size = mPidsSelfLocked.size(); i < size; i++) {
+ final ProcessRecord r = mPidsSelfLocked.valueAt(i);
+ processMemoryStates.add(new ProcessMemoryState(
+ r.uid, r.getPid(), r.processName, r.mState.getCurAdj()));
+ }
}
}
return processMemoryStates;
@@ -15094,14 +15266,14 @@ public class ActivityManagerService extends IActivityManager.Stub
final WindowProcessController wpc =
(WindowProcessController) procsToKill.get(i);
final ProcessRecord pr = (ProcessRecord) wpc.mOwner;
- if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
- && pr.curReceivers.isEmpty()) {
- pr.kill("remove task", ApplicationExitInfo.REASON_USER_REQUESTED,
+ if (pr.mState.getSetSchedGroup() == ProcessList.SCHED_GROUP_BACKGROUND
+ && pr.mReceivers.numberOfCurReceivers() == 0) {
+ pr.killLocked("remove task", ApplicationExitInfo.REASON_USER_REQUESTED,
ApplicationExitInfo.SUBREASON_UNKNOWN, true);
} else {
// We delay killing processes that are not in the background or running a
// receiver.
- pr.waitingToKill = "remove task";
+ pr.setWaitingToKill("remove task");
}
}
}
@@ -15123,18 +15295,15 @@ public class ActivityManagerService extends IActivityManager.Stub
public boolean hasRunningActivity(int uid, @Nullable String packageName) {
if (packageName == null) return false;
- synchronized (ActivityManagerService.this) {
- for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
- final ProcessRecord pr = mProcessList.mLruProcesses.get(i);
- if (pr.uid != uid) {
- continue;
+ synchronized (mProcLock) {
+ return mProcessList.searchEachLruProcessesLOSP(true, app -> {
+ if (app.uid == uid
+ && app.getWindowProcessController().hasRunningActivity(packageName)) {
+ return Boolean.TRUE;
}
- if (pr.getWindowProcessController().hasRunningActivity(packageName)) {
- return true;
- }
- }
+ return null;
+ }) != null;
}
- return false;
}
@Override
@@ -15565,7 +15734,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized (mPidsSelfLocked) {
final ProcessRecord pr = mPidsSelfLocked.get(pid);
- return pr == null ? Zygote.MOUNT_EXTERNAL_NONE : pr.mountMode;
+ return pr == null ? Zygote.MOUNT_EXTERNAL_NONE : pr.getMountMode();
}
}
@@ -15596,19 +15765,17 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean hasRunningForegroundService(int uid, int foregroundServicetype) {
synchronized (ActivityManagerService.this) {
- for (int i = 0; i < mProcessList.mLruProcesses.size(); i++) {
- final ProcessRecord pr = mProcessList.mLruProcesses.get(i);
- if (pr.uid != uid) {
- continue;
+ return mProcessList.searchEachLruProcessesLOSP(true, app -> {
+ if (app.uid != uid) {
+ return null;
}
- if ((pr.getForegroundServiceTypes() & foregroundServicetype) != 0) {
- return true;
+ if ((app.mServices.getForegroundServiceTypes() & foregroundServicetype) != 0) {
+ return Boolean.TRUE;
}
- }
+ return null;
+ }) != null;
}
-
- return false;
}
@Override
@@ -15623,7 +15790,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean isUidCurrentlyInstrumented(int uid) {
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
for (int i = mActiveInstrumentation.size() - 1; i >= 0; i--) {
ActiveInstrumentation activeInst = mActiveInstrumentation.get(i);
if (!activeInst.mFinished && activeInst.mTargetInfo != null
@@ -15775,8 +15942,8 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.d(TAG_NETWORK, "Called from " + callingUid + " to wait for seq: " + procStateSeq);
}
UidRecord record;
- synchronized (this) {
- record = mProcessList.getUidRecordLocked(callingUid);
+ synchronized (mProcLock) {
+ record = mProcessList.getUidRecordLOSP(callingUid);
if (record == null) {
return;
}
@@ -15892,11 +16059,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
try {
synchronized(this) {
- mProcessList.killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid),
- userId, ProcessList.FOREGROUND_APP_ADJ,
- ApplicationExitInfo.REASON_DEPENDENCY_DIED,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- "dep: " + packageName);
+ synchronized (mProcLock) {
+ mProcessList.killPackageProcessesLSP(packageName, UserHandle.getAppId(pkgUid),
+ userId, ProcessList.FOREGROUND_APP_ADJ,
+ ApplicationExitInfo.REASON_DEPENDENCY_DIED,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "dep: " + packageName);
+ }
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -15913,10 +16082,10 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"scheduleApplicationInfoChanged()");
- synchronized (this) {
+ synchronized (mProcLock) {
final long origId = Binder.clearCallingIdentity();
try {
- updateApplicationInfoLocked(packageNames, userId);
+ updateApplicationInfoLOSP(packageNames, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -15935,12 +16104,13 @@ public class ActivityManagerService extends IActivityManager.Stub
ActivityThread.currentActivityThread().handleSystemApplicationInfoChanged(ai);
}
- void updateApplicationInfoLocked(@NonNull List packagesToUpdate, int userId) {
+ @GuardedBy(anyOf = {"this", "mProcLock"})
+ private void updateApplicationInfoLOSP(@NonNull List packagesToUpdate, int userId) {
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
if (updateFrameworkRes) {
PackageParser.readConfigUseRoundIcon(null);
}
- mProcessList.updateApplicationInfoLocked(packagesToUpdate, userId, updateFrameworkRes);
+ mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);
if (updateFrameworkRes) {
// Update system server components that need to know about changed overlays. Because the
@@ -15969,7 +16139,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final int batchSize;
final float threshold;
final BinderCallHeavyHitterListener listener;
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
if (mConstants.BINDER_HEAVY_HITTER_WATCHER_ENABLED) {
// Default watcher takes precedence, ignore the auto sampler.
mHandler.removeMessages(BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG);
@@ -16006,7 +16176,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final int batchSize;
final float threshold;
final long now;
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
if (!mConstants.BINDER_HEAVY_HITTER_AUTO_SAMPLER_ENABLED) {
// It's configured OFF
return;
@@ -16040,7 +16210,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* Stop the binder heavy hitter auto sampler after given timeout.
*/
private void handleBinderHeavyHitterAutoSamplerTimeOut() {
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
if (mConstants.BINDER_HEAVY_HITTER_WATCHER_ENABLED) {
// The default watcher is ON, don't bother to stop it.
return;
@@ -16086,10 +16256,11 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
public void attachAgent(String process, String path) {
try {
- synchronized (this) {
- ProcessRecord proc = findProcessLocked(process, UserHandle.USER_SYSTEM,
+ synchronized (mProcLock) {
+ ProcessRecord proc = findProcessLOSP(process, UserHandle.USER_SYSTEM,
"attachAgent");
- if (proc == null || proc.thread == null) {
+ IApplicationThread thread;
+ if (proc == null || (thread = proc.getThread()) == null) {
throw new IllegalArgumentException("Unknown process: " + process);
}
@@ -16099,7 +16270,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- proc.thread.attachAgent(path);
+ thread.attachAgent(path);
}
} catch (RemoteException e) {
throw new IllegalStateException("Process disappeared");
@@ -16168,7 +16339,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// We allow delegation only to one instrumentation started from the shell
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
// If the delegate is already set up for the target UID, nothing to do.
if (mAppOpsService.getAppOpsServiceDelegate() != null) {
if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
@@ -16214,7 +16385,7 @@ public class ActivityManagerService extends IActivityManager.Stub
&& UserHandle.getCallingAppId() != Process.ROOT_UID) {
throw new SecurityException("Only the shell can delegate its permissions");
}
- synchronized (ActivityManagerService.this) {
+ synchronized (mProcLock) {
mAppOpsService.setAppOpsServiceDelegate(null);
getPermissionManagerInternal().stopShellPermissionIdentityDelegation();
}
@@ -16336,7 +16507,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!isCallerShell()) {
throw new SecurityException("Only shell can call it");
}
- synchronized (this) {
+ synchronized (mProcLock) {
try {
if (mLifeMonitorFds == null) {
mLifeMonitorFds = ParcelFileDescriptor.createPipe();
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index a7119d18117ab..34d9a60d78aae 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -160,7 +160,7 @@ class AnrHelper {
}
void appNotResponding(boolean onlyDumpSelf) {
- mApp.appNotResponding(mActivityShortComponentName, mAppInfo,
+ mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo,
mParentShortComponentName, mParentProcess, mAboveSystem, mAnnotation,
onlyDumpSelf);
}
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 779d37858ce2a..48222cb075cd2 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -38,6 +38,7 @@ import android.widget.TextView;
final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListener {
private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
private final AppErrorResult mResult;
private final ProcessRecord mProc;
private final boolean mIsRestartable;
@@ -63,6 +64,7 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
Resources res = context.getResources();
mService = service;
+ mProcLock = service.mProcLock;
mProc = data.proc;
mResult = data.result;
mIsRestartable = (data.taskId != INVALID_TASK_ID || data.isRestartableForService)
@@ -71,7 +73,7 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
BidiFormatter bidi = BidiFormatter.getInstance();
CharSequence name;
- if ((mProc.getPkgList().size() == 1)
+ if (mProc.getPkgList().size() == 1
&& (name = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
setTitle(res.getString(
data.repeating ? com.android.internal.R.string.aerr_application_repeated
@@ -112,7 +114,7 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
LayoutInflater.from(context).inflate(
com.android.internal.R.layout.app_error_dialog, frame, true);
- final boolean hasReceiver = mProc.errorReportReceiver != null;
+ final boolean hasReceiver = mProc.mErrorState.getErrorReportReceiver() != null;
final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);
restart.setOnClickListener(this);
@@ -166,11 +168,11 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
}
private void setResult(int result) {
- synchronized (mService) {
+ synchronized (mProcLock) {
if (mProc != null) {
// Don't dismiss again since it leads to recursive call between dismiss and this
// method.
- mProc.getDialogController().clearCrashDialogs(false /* needDismiss */);
+ mProc.mErrorState.getDialogController().clearCrashDialogs(false /* needDismiss */);
}
}
mResult.set(result);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 7be54c29a218f..e5a5cff409b3e 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -72,6 +72,7 @@ class AppErrors {
private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
private final Context mContext;
private final PackageWatchdog mPackageWatchdog;
@@ -137,6 +138,7 @@ class AppErrors {
AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
context.assertRuntimeOverlayThemable();
mService = service;
+ mProcLock = service.mProcLock;
mContext = context;
mPackageWatchdog = watchdog;
}
@@ -154,17 +156,48 @@ class AppErrors {
}
}
- void dumpDebug(ProtoOutputStream proto, long fieldId, String dumpPackage) {
- synchronized (mBadProcessLock) {
- final ProcessMap badProcesses = mBadProcesses;
- if (mProcessCrashTimes.getMap().isEmpty() && badProcesses.getMap().isEmpty()) {
- return;
+ @GuardedBy("mProcLock")
+ void dumpDebugLPr(ProtoOutputStream proto, long fieldId, String dumpPackage) {
+ final ProcessMap badProcesses = mBadProcesses;
+ if (mProcessCrashTimes.getMap().isEmpty() && badProcesses.getMap().isEmpty()) {
+ return;
+ }
+
+ final long token = proto.start(fieldId);
+ final long now = SystemClock.uptimeMillis();
+ proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
+
+ if (!badProcesses.getMap().isEmpty()) {
+ final ArrayMap> pmap = badProcesses.getMap();
+ final int processCount = pmap.size();
+ for (int ip = 0; ip < processCount; ip++) {
+ final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
+ final String pname = pmap.keyAt(ip);
+ final SparseArray uids = pmap.valueAt(ip);
+ final int uidCount = uids.size();
+
+ proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
+ for (int i = 0; i < uidCount; i++) {
+ final int puid = uids.keyAt(i);
+ final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
+ if (dumpPackage != null && (r == null
+ || !r.getPkgList().containsKey(dumpPackage))) {
+ continue;
+ }
+ final BadProcessInfo info = uids.valueAt(i);
+ final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
+ proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
+ proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
+ proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
+ proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
+ proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
+ proto.end(etoken);
+ }
+ proto.end(btoken);
}
+ }
- final long token = proto.start(fieldId);
- final long now = SystemClock.uptimeMillis();
- proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
-
+ synchronized (mBadProcessLock) {
if (!mProcessCrashTimes.getMap().isEmpty()) {
final ArrayMap> pmap = mProcessCrashTimes.getMap();
final int procCount = pmap.size();
@@ -177,7 +210,7 @@ class AppErrors {
proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.getProcessNames().get(pname, puid);
+ final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
if (dumpPackage != null
&& (r == null || !r.getPkgList().containsKey(dumpPackage))) {
continue;
@@ -190,44 +223,14 @@ class AppErrors {
}
proto.end(ctoken);
}
-
}
-
- if (!badProcesses.getMap().isEmpty()) {
- final ArrayMap> pmap = badProcesses.getMap();
- final int processCount = pmap.size();
- for (int ip = 0; ip < processCount; ip++) {
- final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
- final String pname = pmap.keyAt(ip);
- final SparseArray uids = pmap.valueAt(ip);
- final int uidCount = uids.size();
-
- proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
- for (int i = 0; i < uidCount; i++) {
- final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.getProcessNames().get(pname, puid);
- if (dumpPackage != null && (r == null
- || !r.getPkgList().containsKey(dumpPackage))) {
- continue;
- }
- final BadProcessInfo info = uids.valueAt(i);
- final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
- proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
- proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
- proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
- proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
- proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
- proto.end(etoken);
- }
- proto.end(btoken);
- }
- }
-
- proto.end(token);
}
+
+ proto.end(token);
}
- boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
+ @GuardedBy("mProcLock")
+ boolean dumpLPr(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
final long now = SystemClock.uptimeMillis();
synchronized (mBadProcessLock) {
if (!mProcessCrashTimes.getMap().isEmpty()) {
@@ -240,9 +243,9 @@ class AppErrors {
final int uidCount = uids.size();
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.getProcessNames().get(pname, puid);
- if (dumpPackage != null && (r == null
- || !r.getPkgList().containsKey(dumpPackage))) {
+ final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
+ if (dumpPackage != null
+ && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
continue;
}
if (!printed) {
@@ -271,7 +274,7 @@ class AppErrors {
final int uidCount = uids.size();
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.getProcessNames().get(pname, puid);
+ final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
if (dumpPackage != null
&& (r == null || !r.getPkgList().containsKey(dumpPackage))) {
continue;
@@ -303,7 +306,7 @@ class AppErrors {
final int uidCount = uids.size();
for (int i = 0; i < uidCount; i++) {
final int puid = uids.keyAt(i);
- final ProcessRecord r = mService.getProcessNames().get(pname, puid);
+ final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
if (dumpPackage != null && (r == null
|| !r.getPkgList().containsKey(dumpPackage))) {
continue;
@@ -330,14 +333,14 @@ class AppErrors {
for (int pos = 0; pos < info.stack.length(); pos++) {
if (info.stack.charAt(pos) == '\n') {
pw.print(" ");
- pw.write(info.stack, lastPos, pos-lastPos);
+ pw.write(info.stack, lastPos, pos - lastPos);
pw.println();
- lastPos = pos+1;
+ lastPos = pos + 1;
}
}
if (lastPos < info.stack.length()) {
pw.print(" ");
- pw.write(info.stack, lastPos, info.stack.length()-lastPos);
+ pw.write(info.stack, lastPos, info.stack.length() - lastPos);
pw.println();
}
}
@@ -437,32 +440,38 @@ class AppErrors {
}
}
+ @GuardedBy("mService")
void killAppAtUserRequestLocked(ProcessRecord app) {
- ProcessRecord.ErrorDialogController controller =
- app.getDialogController();
+ ErrorDialogController controller = app.mErrorState.getDialogController();
int reasonCode = ApplicationExitInfo.REASON_ANR;
int subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
- if (controller.hasDebugWaitingDialog()) {
- reasonCode = ApplicationExitInfo.REASON_OTHER;
- subReason = ApplicationExitInfo.SUBREASON_WAIT_FOR_DEBUGGER;
+ synchronized (mProcLock) {
+ if (controller.hasDebugWaitingDialog()) {
+ reasonCode = ApplicationExitInfo.REASON_OTHER;
+ subReason = ApplicationExitInfo.SUBREASON_WAIT_FOR_DEBUGGER;
+ }
+ controller.clearAllErrorDialogs();
+ killAppImmediateLSP(app, reasonCode, subReason,
+ "user-terminated", "user request after error");
}
-
- controller.clearAllErrorDialogs();
- killAppImmediateLocked(app, reasonCode, subReason,
- "user-terminated", "user request after error");
}
- private void killAppImmediateLocked(ProcessRecord app, int reasonCode, int subReason,
+ @GuardedBy({"mService", "mProcLock"})
+ private void killAppImmediateLSP(ProcessRecord app, int reasonCode, int subReason,
String reason, String killReason) {
- app.setCrashing(false);
- app.crashingReport = null;
- app.setNotResponding(false);
- app.notRespondingReport = null;
- if (app.pid > 0 && app.pid != MY_PID) {
- handleAppCrashLocked(app, reason,
- null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
- app.kill(killReason, reasonCode, subReason, true);
+ final ProcessErrorStateRecord errState = app.mErrorState;
+ errState.setCrashing(false);
+ errState.setCrashingReport(null);
+ errState.setNotResponding(false);
+ errState.setNotRespondingReport(null);
+ final int pid = errState.mApp.getPid();
+ if (pid > 0 && pid != MY_PID) {
+ synchronized (mBadProcessLock) {
+ handleAppCrashLSPB(app, reason,
+ null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
+ }
+ app.killLocked(killReason, reasonCode, subReason, true);
}
}
@@ -489,7 +498,7 @@ class AppErrors {
if (uid >= 0 && p.uid != uid) {
continue;
}
- if (p.pid == initialPid) {
+ if (p.getPid() == initialPid) {
proc = p;
break;
}
@@ -508,7 +517,7 @@ class AppErrors {
return;
}
- proc.scheduleCrash(message);
+ proc.scheduleCrashLocked(message);
if (force) {
// If the app is responsive, the scheduled crash will happen as expected
// and then the delayed summary kill will be a no-op.
@@ -516,9 +525,11 @@ class AppErrors {
mService.mHandler.postDelayed(
() -> {
synchronized (mService) {
- killAppImmediateLocked(p, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_INVALID_STATE,
- "forced", "killed for invalid state");
+ synchronized (mProcLock) {
+ killAppImmediateLSP(p, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE,
+ "forced", "killed for invalid state");
+ }
}
},
5000L);
@@ -627,52 +638,54 @@ class AppErrors {
if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
res = AppErrorDialog.FORCE_QUIT;
}
- if (res == AppErrorDialog.MUTE) {
- synchronized (mBadProcessLock) {
- stopReportingCrashesLBp(r);
- }
- }
- if (res == AppErrorDialog.RESTART) {
- synchronized (mService) {
- mService.mProcessList.removeProcessLocked(r, false, true,
- ApplicationExitInfo.REASON_CRASH, "crash");
- }
- if (taskId != INVALID_TASK_ID) {
- try {
- mService.startActivityFromRecents(taskId,
- ActivityOptions.makeBasic().toBundle());
- } catch (IllegalArgumentException e) {
- // Hmm...that didn't work. Task should either be in recents or associated
- // with a stack.
- Slog.e(TAG, "Could not restart taskId=" + taskId, e);
+ switch (res) {
+ case AppErrorDialog.MUTE:
+ synchronized (mBadProcessLock) {
+ stopReportingCrashesLBp(r);
}
- }
- }
- if (res == AppErrorDialog.FORCE_QUIT) {
- final long orig = Binder.clearCallingIdentity();
- try {
- // Kill it with fire!
- mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
- if (!r.isPersistent()) {
- synchronized (mService) {
- mService.mProcessList.removeProcessLocked(r, false, false,
- ApplicationExitInfo.REASON_CRASH, "crash");
+ break;
+ case AppErrorDialog.RESTART:
+ synchronized (mService) {
+ mService.mProcessList.removeProcessLocked(r, false, true,
+ ApplicationExitInfo.REASON_CRASH, "crash");
+ }
+ if (taskId != INVALID_TASK_ID) {
+ try {
+ mService.startActivityFromRecents(taskId,
+ ActivityOptions.makeBasic().toBundle());
+ } catch (IllegalArgumentException e) {
+ // Hmm...that didn't work. Task should either be in recents or associated
+ // with a stack.
+ Slog.e(TAG, "Could not restart taskId=" + taskId, e);
}
- mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
}
- } finally {
- Binder.restoreCallingIdentity(orig);
- }
- }
- if (res == AppErrorDialog.APP_INFO) {
- appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
- appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- }
- if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
- synchronized (mService) {
- appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
- }
+ break;
+ case AppErrorDialog.FORCE_QUIT:
+ final long orig = Binder.clearCallingIdentity();
+ try {
+ // Kill it with fire!
+ mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
+ if (!r.isPersistent()) {
+ synchronized (mService) {
+ mService.mProcessList.removeProcessLocked(r, false, false,
+ ApplicationExitInfo.REASON_CRASH, "crash");
+ }
+ mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(orig);
+ }
+ break;
+ case AppErrorDialog.APP_INFO:
+ appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
+ appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ break;
+ case AppErrorDialog.FORCE_QUIT_AND_REPORT:
+ synchronized (mProcLock) {
+ appErrorIntent = createAppErrorIntentLOSP(r, timeMillis, crashInfo);
+ }
+ break;
}
if (appErrorIntent != null) {
@@ -684,13 +697,14 @@ class AppErrors {
}
}
+ @GuardedBy("mService")
private boolean handleAppCrashInActivityController(ProcessRecord r,
ApplicationErrorReport.CrashInfo crashInfo,
String shortMsg, String longMsg,
String stackTrace, long timeMillis,
int callingPid, int callingUid) {
String name = r != null ? r.processName : null;
- int pid = r != null ? r.pid : callingPid;
+ int pid = r != null ? r.getPid() : callingPid;
int uid = r != null ? r.info.uid : callingUid;
return mService.mAtmInternal.handleAppCrashInActivityController(
@@ -703,7 +717,7 @@ class AppErrors {
Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
if (r != null) {
if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
- r.kill("crash", ApplicationExitInfo.REASON_CRASH, true);
+ r.killLocked("crash", ApplicationExitInfo.REASON_CRASH, true);
}
} else {
// Huh.
@@ -718,15 +732,22 @@ class AppErrors {
});
}
+ @GuardedBy("mService")
private boolean makeAppCrashingLocked(ProcessRecord app,
String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
- app.setCrashing(true);
- app.crashingReport = generateProcessError(app,
- ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
- app.startAppProblemLocked();
- app.getWindowProcessController().stopFreezingActivities();
- return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
- data);
+ synchronized (mProcLock) {
+ final ProcessErrorStateRecord errState = app.mErrorState;
+ errState.setCrashing(true);
+ errState.setCrashingReport(generateProcessError(app,
+ ActivityManager.ProcessErrorStateInfo.CRASHED,
+ null, shortMsg, longMsg, stackTrace));
+ errState.startAppProblemLSP();
+ app.getWindowProcessController().stopFreezingActivities();
+ synchronized (mBadProcessLock) {
+ return handleAppCrashLSPB(app, "force-crash" /*reason*/, shortMsg, longMsg,
+ stackTrace, data);
+ }
+ }
}
/**
@@ -748,7 +769,7 @@ class AppErrors {
report.condition = condition;
report.processName = app.processName;
- report.pid = app.pid;
+ report.pid = app.getPid();
report.uid = app.info.uid;
report.tag = activity;
report.shortMsg = shortMsg;
@@ -758,170 +779,157 @@ class AppErrors {
return report;
}
- Intent createAppErrorIntentLocked(ProcessRecord r,
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ Intent createAppErrorIntentLOSP(ProcessRecord r,
long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
- ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
+ ApplicationErrorReport report = createAppErrorReportLOSP(r, timeMillis, crashInfo);
if (report == null) {
return null;
}
Intent result = new Intent(Intent.ACTION_APP_ERROR);
- result.setComponent(r.errorReportReceiver);
+ result.setComponent(r.mErrorState.getErrorReportReceiver());
result.putExtra(Intent.EXTRA_BUG_REPORT, report);
result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return result;
}
- private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ private ApplicationErrorReport createAppErrorReportLOSP(ProcessRecord r,
long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
- if (r.errorReportReceiver == null) {
+ final ProcessErrorStateRecord errState = r.mErrorState;
+ if (errState.getErrorReportReceiver() == null) {
return null;
}
- if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) {
+ if (!errState.isCrashing() && !errState.isNotResponding()
+ && !errState.isForceCrashReport()) {
return null;
}
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = r.info.packageName;
- report.installerPackageName = r.errorReportReceiver.getPackageName();
+ report.installerPackageName = errState.getErrorReportReceiver().getPackageName();
report.processName = r.processName;
report.time = timeMillis;
report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0;
- if (r.isCrashing() || r.forceCrashReport) {
+ if (errState.isCrashing() || errState.isForceCrashReport()) {
report.type = ApplicationErrorReport.TYPE_CRASH;
report.crashInfo = crashInfo;
- } else if (r.isNotResponding()) {
+ } else if (errState.isNotResponding()) {
report.type = ApplicationErrorReport.TYPE_ANR;
report.anrInfo = new ApplicationErrorReport.AnrInfo();
- report.anrInfo.activity = r.notRespondingReport.tag;
- report.anrInfo.cause = r.notRespondingReport.shortMsg;
- report.anrInfo.info = r.notRespondingReport.longMsg;
+ report.anrInfo.activity = errState.getNotRespondingReport().tag;
+ report.anrInfo.cause = errState.getNotRespondingReport().shortMsg;
+ report.anrInfo.info = errState.getNotRespondingReport().longMsg;
}
return report;
}
- private boolean handleAppCrashLocked(ProcessRecord app, String reason,
+ @GuardedBy({"mService", "mProcLock", "mBadProcessLock"})
+ private boolean handleAppCrashLSPB(ProcessRecord app, String reason,
String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
final long now = SystemClock.uptimeMillis();
final boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0,
mService.mUserController.getCurrentUserId()) != 0;
- final boolean procIsBoundForeground =
- (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
-
Long crashTime;
Long crashTimePersistent;
- boolean tryAgain = false;
+ final String processName = app.processName;
+ final int uid = app.uid;
+ final int userId = app.userId;
+ final boolean isolated = app.isolated;
+ final boolean persistent = app.isPersistent();
+ final WindowProcessController proc = app.getWindowProcessController();
+ final ProcessErrorStateRecord errState = app.mErrorState;
- synchronized (mBadProcessLock) {
- if (!app.isolated) {
- crashTime = mProcessCrashTimes.get(app.processName, app.uid);
- crashTimePersistent = mProcessCrashTimesPersistent.get(app.processName, app.uid);
- } else {
- crashTime = crashTimePersistent = null;
- }
+ if (!app.isolated) {
+ crashTime = mProcessCrashTimes.get(processName, uid);
+ crashTimePersistent = mProcessCrashTimesPersistent.get(processName, uid);
+ } else {
+ crashTime = crashTimePersistent = null;
+ }
- // Bump up the crash count of any services currently running in the proc.
- for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
- // Any services running in the application need to be placed
- // back in the pending list.
- ServiceRecord sr = app.getRunningServiceAt(i);
- // If the service was restarted a while ago, then reset crash count,
- // else increment it.
- if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
- sr.crashCount = 1;
- } else {
- sr.crashCount++;
- }
- // Allow restarting for started or bound foreground services that are crashing.
- // This includes wallpapers.
- if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
- && (sr.isForeground || procIsBoundForeground)) {
- tryAgain = true;
- }
- }
+ // Bump up the crash count of any services currently running in the proc.
+ boolean tryAgain = app.mServices.incServiceCrashCountLocked(now);
- final boolean quickCrash = crashTime != null
- && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
- if (quickCrash || isProcOverCrashLimitLBp(app, now)) {
- // The process either crashed again very quickly or has been crashing periodically
- // in the last few hours. If it was a bound foreground service, let's try to
- // restart again in a while, otherwise the process loses!
- Slog.w(TAG, "Process " + app.processName + " has crashed too many times, killing!"
- + " Reason: "
- + (quickCrash ? "crashed quickly" : "over process crash limit"));
- EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
- app.userId, app.processName, app.uid);
- mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController());
- if (!app.isPersistent()) {
- // We don't want to start this process again until the user
- // explicitly does so... but for persistent process, we really
- // need to keep it running. If a persistent process is actually
- // repeatedly crashing, then badness for everyone.
- EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
- app.processName);
- if (!app.isolated) {
- // XXX We don't have a way to mark isolated processes
- // as bad, since they don't have a persistent identity.
- markBadProcess(app.processName, app.uid,
- new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
- mProcessCrashTimes.remove(app.processName, app.uid);
- mProcessCrashCounts.remove(app.processName, app.uid);
- }
- app.bad = true;
- app.removed = true;
- // Don't let services in this process be restarted and potentially
- // annoy the user repeatedly. Unless it is persistent, since those
- // processes run critical code.
- mService.mProcessList.removeProcessLocked(app, false, tryAgain,
- ApplicationExitInfo.REASON_CRASH, "crash");
- mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
- if (!showBackground) {
- return false;
- }
+ final boolean quickCrash = crashTime != null
+ && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
+ if (quickCrash || isProcOverCrashLimitLBp(app, now)) {
+ // The process either crashed again very quickly or has been crashing periodically in
+ // the last few hours. If it was a bound foreground service, let's try to restart again
+ // in a while, otherwise the process loses!
+ Slog.w(TAG, "Process " + processName + " has crashed too many times, killing!"
+ + " Reason: " + (quickCrash ? "crashed quickly" : "over process crash limit"));
+ EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
+ userId, processName, uid);
+ mService.mAtmInternal.onHandleAppCrash(proc);
+ if (!persistent) {
+ // We don't want to start this process again until the user
+ // explicitly does so... but for persistent process, we really
+ // need to keep it running. If a persistent process is actually
+ // repeatedly crashing, then badness for everyone.
+ EventLog.writeEvent(EventLogTags.AM_PROC_BAD, userId, uid,
+ processName);
+ if (!isolated) {
+ // XXX We don't have a way to mark isolated processes
+ // as bad, since they don't have a persistent identity.
+ markBadProcess(processName, app.uid,
+ new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
+ mProcessCrashTimes.remove(processName, app.uid);
+ mProcessCrashCounts.remove(processName, app.uid);
}
+ errState.setBad(true);
+ app.setRemoved(true);
+ // Don't let services in this process be restarted and potentially
+ // annoy the user repeatedly. Unless it is persistent, since those
+ // processes run critical code.
+ mService.mProcessList.removeProcessLocked(app, false, tryAgain,
+ ApplicationExitInfo.REASON_CRASH, "crash");
mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
- } else {
- final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
- app.getWindowProcessController(), reason);
- if (data != null) {
- data.taskId = affectedTaskId;
- }
- if (data != null && crashTimePersistent != null
- && now < crashTimePersistent
- + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
- data.repeating = true;
+ if (!showBackground) {
+ return false;
}
}
-
- if (data != null && tryAgain) {
- data.isRestartableForService = true;
+ mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
+ } else {
+ final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
+ proc, reason);
+ if (data != null) {
+ data.taskId = affectedTaskId;
}
-
- // If the crashing process is what we consider to be the "home process" and it has been
- // replaced by a third-party app, clear the package preferred activities from packages
- // with a home activity running in the process to prevent a repeatedly crashing app
- // from blocking the user to manually clear the list.
- final WindowProcessController proc = app.getWindowProcessController();
- if (proc.isHomeProcess() && proc.hasActivities()
- && (app.info.flags & FLAG_SYSTEM) == 0) {
- proc.clearPackagePreferredForHomeActivities();
- }
-
- if (!app.isolated) {
- // XXX Can't keep track of crash times for isolated processes,
- // because they don't have a persistent identity.
- mProcessCrashTimes.put(app.processName, app.uid, now);
- mProcessCrashTimesPersistent.put(app.processName, app.uid, now);
- updateProcessCrashCountLBp(app.processName, app.uid, now);
+ if (data != null && crashTimePersistent != null
+ && now < crashTimePersistent + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
+ data.repeating = true;
}
}
- if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
+ if (data != null && tryAgain) {
+ data.isRestartableForService = true;
+ }
+
+ // If the crashing process is what we consider to be the "home process" and it has been
+ // replaced by a third-party app, clear the package preferred activities from packages
+ // with a home activity running in the process to prevent a repeatedly crashing app
+ // from blocking the user to manually clear the list.
+ if (proc.isHomeProcess() && proc.hasActivities() && (app.info.flags & FLAG_SYSTEM) == 0) {
+ proc.clearPackagePreferredForHomeActivities();
+ }
+
+ if (!isolated) {
+ // XXX Can't keep track of crash times for isolated processes,
+ // because they don't have a persistent identity.
+ mProcessCrashTimes.put(processName, uid, now);
+ mProcessCrashTimesPersistent.put(processName, uid, now);
+ updateProcessCrashCountLBp(processName, uid, now);
+ }
+
+ if (errState.getCrashHandler() != null) {
+ mService.mHandler.post(errState.getCrashHandler());
+ }
return true;
}
@@ -951,15 +959,16 @@ class AppErrors {
mService.mUserController.getCurrentUserId()) != 0;
final int userId;
- synchronized (mService) {
+ synchronized (mProcLock) {
final ProcessRecord proc = data.proc;
final AppErrorResult res = data.result;
if (proc == null) {
Slog.e(TAG, "handleShowAppErrorUi: proc is null");
return;
}
+ final ProcessErrorStateRecord errState = proc.mErrorState;
userId = proc.userId;
- if (proc.getDialogController().hasCrashDialogs()) {
+ if (errState.getDialogController().hasCrashDialogs()) {
Slog.e(TAG, "App already has crash dialog: " + proc);
if (res != null) {
res.set(AppErrorDialog.ALREADY_SHOWING);
@@ -968,7 +977,7 @@ class AppErrors {
}
boolean isBackground = (UserHandle.getAppId(proc.uid)
>= Process.FIRST_APPLICATION_UID
- && proc.pid != MY_PID);
+ && proc.getPid() != MY_PID);
for (int profileId : mService.mUserController.getCurrentProfileIds()) {
isBackground &= (userId != profileId);
}
@@ -1001,7 +1010,7 @@ class AppErrors {
if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
&& !crashSilenced && !shouldThottle
&& (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
- proc.getDialogController().showCrashDialogs(data);
+ errState.getDialogController().showCrashDialogs(data);
if (!proc.isolated) {
mProcessCrashShowDialogTimes.put(proc.processName, proc.uid, now);
}
@@ -1026,17 +1035,19 @@ class AppErrors {
void handleShowAnrUi(Message msg) {
List packageList = null;
- synchronized (mService) {
- AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
- final ProcessRecord proc = data.proc;
- if (proc == null) {
- Slog.e(TAG, "handleShowAnrUi: proc is null");
- return;
- }
+ boolean doKill = false;
+ AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
+ final ProcessRecord proc = data.proc;
+ if (proc == null) {
+ Slog.e(TAG, "handleShowAnrUi: proc is null");
+ return;
+ }
+ synchronized (mProcLock) {
+ final ProcessErrorStateRecord errState = proc.mErrorState;
if (!proc.isPersistent()) {
packageList = proc.getPackageListWithVersionCode();
}
- if (proc.getDialogController().hasAnrDialogs()) {
+ if (errState.getDialogController().hasAnrDialogs()) {
Slog.e(TAG, "App already has anr dialog: " + proc);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.ALREADY_SHOWING);
@@ -1047,14 +1058,17 @@ class AppErrors {
Settings.Secure.ANR_SHOW_BACKGROUND, 0,
mService.mUserController.getCurrentUserId()) != 0;
if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
- proc.getDialogController().showAnrDialogs(data);
+ errState.getDialogController().showAnrDialogs(data);
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.CANT_SHOW);
// Just kill the app if there is no dialog to be shown.
- mService.killAppAtUsersRequest(proc);
+ doKill = true;
}
}
+ if (doKill) {
+ mService.killAppAtUsersRequest(proc);
+ }
// Notify PackageWatchdog without the lock held
if (packageList != null) {
mPackageWatchdog.onPackageFailure(packageList,
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 48aa8be1e2d57..17be2100414fb 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -920,20 +920,20 @@ public final class AppExitInfoTracker {
info = new ApplicationExitInfo();
}
- synchronized (mService) {
- final int definingUid = app.hostingRecord != null
- ? app.hostingRecord.getDefiningUid() : 0;
- info.setPid(app.pid);
+ synchronized (mService.mProcLock) {
+ final int definingUid = app.getHostingRecord() != null
+ ? app.getHostingRecord().getDefiningUid() : 0;
+ info.setPid(app.getPid());
info.setRealUid(app.uid);
info.setPackageUid(app.info.uid);
info.setDefiningUid(definingUid > 0 ? definingUid : app.info.uid);
info.setProcessName(app.processName);
- info.setConnectionGroup(app.connectionGroup);
+ info.setConnectionGroup(app.mServices.getConnectionGroup());
info.setPackageName(app.info.packageName);
info.setPackageList(app.getPackageList());
info.setReason(ApplicationExitInfo.REASON_UNKNOWN);
info.setStatus(0);
- info.setImportance(procStateToImportance(app.setProcState));
+ info.setImportance(procStateToImportance(app.mState.getSetProcState()));
info.setPss(app.mProfile.getLastPss());
info.setRss(app.mProfile.getLastRss());
info.setTimestamp(System.currentTimeMillis());
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 96e6f6ea4476b..77d2898842c62 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -63,7 +63,7 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
? data.aInfo.loadLabel(context.getPackageManager())
: null;
CharSequence name2 = null;
- if ((mProc.getPkgList().size() == 1)
+ if (mProc.getPkgList().size() == 1
&& (name2 = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
if (name1 != null) {
resid = com.android.internal.R.string.anr_activity_application;
@@ -108,7 +108,7 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
final TextView report = findViewById(com.android.internal.R.id.aerr_report);
report.setOnClickListener(this);
- final boolean hasReceiver = mProc.errorReportReceiver != null;
+ final boolean hasReceiver = mProc.mErrorState.getErrorReportReceiver() != null;
report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
final TextView close = findViewById(com.android.internal.R.id.aerr_close);
close.setOnClickListener(this);
@@ -152,15 +152,18 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
// Continue waiting for the application.
synchronized (mService) {
ProcessRecord app = mProc;
+ final ProcessErrorStateRecord errState = app.mErrorState;
if (msg.what == WAIT_AND_REPORT) {
- appErrorIntent = mService.mAppErrors.createAppErrorIntentLocked(app,
+ appErrorIntent = mService.mAppErrors.createAppErrorIntentLOSP(app,
System.currentTimeMillis(), null);
}
- app.setNotResponding(false);
- app.notRespondingReport = null;
- app.getDialogController().clearAnrDialogs();
+ synchronized (mService.mProcLock) {
+ errState.setNotResponding(false);
+ errState.setNotRespondingReport(null);
+ errState.getDialogController().clearAnrDialogs();
+ }
mService.mServices.scheduleServiceTimeoutLocked(app);
}
break;
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 3df058c8ed82f..8f11a5ab900b2 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -207,7 +207,6 @@ public class AppProfiler {
*/
private volatile boolean mTestPssMode = false;
- @GuardedBy("mService")
private final LowMemDetector mLowMemDetector;
/**
@@ -239,13 +238,13 @@ public class AppProfiler {
/**
* Total time spent with RAM that has been added in the past since the last idle time.
*/
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
private long mLowRamTimeSinceLastIdle = 0;
/**
* If RAM is currently low, when that horrible situation started.
*/
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
private long mLowRamStartTime = 0;
/**
@@ -331,6 +330,8 @@ public class AppProfiler {
*/
final Object mProfilerLock = new Object();
+ final ActivityManagerGlobalLock mProcLock;
+
/**
* Observe DeviceConfig changes to the PSS calculation interval
*/
@@ -852,8 +853,8 @@ public class AppProfiler {
/**
* Schedule PSS collection of all processes.
*/
- @GuardedBy("mService")
- void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
+ @GuardedBy("mProcLock")
+ void requestPssAllProcsLPr(long now, boolean always, boolean memLowered) {
synchronized (mProfilerLock) {
if (!always) {
if (now < (mLastFullPssTime
@@ -870,10 +871,9 @@ public class AppProfiler {
for (int i = mPendingPssProfiles.size() - 1; i >= 0; i--) {
mPendingPssProfiles.get(i).abortNextPssTime();
}
- mPendingPssProfiles.ensureCapacity(mService.mProcessList.getLruSizeLocked());
+ mPendingPssProfiles.ensureCapacity(mService.mProcessList.getLruSizeLOSP());
mPendingPssProfiles.clear();
- for (int i = mService.mProcessList.getLruSizeLocked() - 1; i >= 0; i--) {
- ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ mService.mProcessList.forEachLruProcessesLOSP(false, app -> {
final ProcessProfileRecord profile = app.mProfile;
if (profile.getThread() == null
|| profile.getSetProcState() == PROCESS_STATE_NONEXISTENT) {
@@ -889,7 +889,7 @@ public class AppProfiler {
updateNextPssTimeLPf(profile.getSetProcState(), profile, now, true);
mPendingPssProfiles.add(profile);
}
- }
+ });
if (!mBgHandler.hasMessages(BgHandler.COLLECT_PSS_BG_MSG)) {
mBgHandler.sendEmptyMessage(BgHandler.COLLECT_PSS_BG_MSG);
}
@@ -897,12 +897,12 @@ public class AppProfiler {
}
void setTestPssMode(boolean enabled) {
- synchronized (mService) {
+ synchronized (mProcLock) {
mTestPssMode = enabled;
if (enabled) {
// Whenever we enable the mode, we want to take a snapshot all of current
// process mem use.
- requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, true);
+ requestPssAllProcsLPr(SystemClock.uptimeMillis(), true, true);
}
}
}
@@ -921,8 +921,8 @@ public class AppProfiler {
return mLastMemoryLevel <= ADJ_MEM_FACTOR_NORMAL;
}
- @GuardedBy("mService")
- void updateLowRamTimestampLocked(long now) {
+ @GuardedBy("mProcLock")
+ void updateLowRamTimestampLPr(long now) {
mLowRamTimeSinceLastIdle = 0;
if (mLowRamStartTime != 0) {
mLowRamStartTime = now;
@@ -939,9 +939,8 @@ public class AppProfiler {
mMemFactorOverride = factor;
}
- @GuardedBy("mService")
- boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
- final int numOfLru = mService.mProcessList.getLruSizeLocked();
+ @GuardedBy({"mService", "mProcLock"})
+ boolean updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming) {
final long now = SystemClock.uptimeMillis();
int memFactor;
if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
@@ -973,7 +972,7 @@ public class AppProfiler {
if (DEBUG_OOM_ADJ) {
Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + " override=" + mMemFactorOverride
+ " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
- + " numProcs=" + mService.mProcessList.getLruSizeLocked()
+ + " numProcs=" + mService.mProcessList.getLruSizeLOSP()
+ " last=" + mLastNumProcesses);
}
boolean override;
@@ -982,7 +981,7 @@ public class AppProfiler {
}
if (memFactor > mLastMemoryLevel) {
if (!override && (!mAllowLowerMemLevel
- || mService.mProcessList.getLruSizeLocked() >= mLastNumProcesses)) {
+ || mService.mProcessList.getLruSizeLOSP() >= mLastNumProcesses)) {
memFactor = mLastMemoryLevel;
if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
}
@@ -992,7 +991,7 @@ public class AppProfiler {
FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
}
mLastMemoryLevel = memFactor;
- mLastNumProcesses = mService.mProcessList.getLruSizeLocked();
+ mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
boolean allChanged;
int trackerMemFactor;
synchronized (mService.mProcessStats.mLock) {
@@ -1004,7 +1003,6 @@ public class AppProfiler {
if (mLowRamStartTime == 0) {
mLowRamStartTime = now;
}
- int step = 0;
int fgTrimLevel;
switch (memFactor) {
case ADJ_MEM_FACTOR_CRITICAL:
@@ -1022,126 +1020,129 @@ public class AppProfiler {
if (mHasHomeProcess) minFactor++;
if (mHasPreviousProcess) minFactor++;
if (factor < minFactor) factor = minFactor;
- int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
- for (int i = 0; i < numOfLru; i++) {
- final ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ final int actualFactor = factor;
+ final int[] step = {0};
+ final int[] curLevel = {ComponentCallbacks2.TRIM_MEMORY_COMPLETE};
+ mService.mProcessList.forEachLruProcessesLOSP(true, app -> {
final ProcessProfileRecord profile = app.mProfile;
final int trimMemoryLevel = profile.getTrimMemoryLevel();
- if (allChanged || app.procStateChanged) {
- mService.setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
+ final ProcessStateRecord state = app.mState;
+ final int curProcState = state.getCurProcState();
+ IApplicationThread thread;
+ if (allChanged || state.hasProcStateChanged()) {
+ mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
+ state.setProcStateChanged(false);
}
- if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedByAm) {
- if (trimMemoryLevel < curLevel && app.thread != null) {
+ if (curProcState >= ActivityManager.PROCESS_STATE_HOME && !app.isKilledByAm()) {
+ if (trimMemoryLevel < curLevel[0] && (thread = app.getThread()) != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
Slog.v(TAG_OOM_ADJ,
"Trimming memory of " + app.processName
- + " to " + curLevel);
+ + " to " + curLevel[0]);
}
- app.thread.scheduleTrimMemory(curLevel);
+ thread.scheduleTrimMemory(curLevel[0]);
} catch (RemoteException e) {
}
}
- profile.setTrimMemoryLevel(curLevel);
- step++;
- if (step >= factor) {
- step = 0;
- switch (curLevel) {
+ profile.setTrimMemoryLevel(curLevel[0]);
+ step[0]++;
+ if (step[0] >= actualFactor) {
+ step[0] = 0;
+ switch (curLevel[0]) {
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
+ curLevel[0] = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
break;
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+ curLevel[0] = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
break;
}
}
- } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- && !app.killedByAm) {
+ } else if (curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+ && !app.isKilledByAm()) {
if (trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
- && app.thread != null) {
+ && (thread = app.getThread()) != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
Slog.v(TAG_OOM_ADJ,
"Trimming memory of heavy-weight " + app.processName
+ " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
}
- app.thread.scheduleTrimMemory(
+ thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} catch (RemoteException e) {
}
}
profile.setTrimMemoryLevel(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} else {
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && profile.hasPendingUiClean()) {
+ if ((curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || state.isSystemNoUi()) && profile.hasPendingUiClean()) {
// If this application is now in the background and it
// had done UI, then give it the special trim level to
// have it free UI resources.
final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
- if (trimMemoryLevel < level && app.thread != null) {
+ if (trimMemoryLevel < level && (thread = app.getThread()) != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
Slog.v(TAG_OOM_ADJ, "Trimming memory of bg-ui "
+ app.processName + " to " + level);
}
- app.thread.scheduleTrimMemory(level);
+ thread.scheduleTrimMemory(level);
} catch (RemoteException e) {
}
}
profile.setPendingUiClean(false);
}
- if (trimMemoryLevel < fgTrimLevel && app.thread != null) {
+ if (trimMemoryLevel < fgTrimLevel && (thread = app.getThread()) != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
Slog.v(TAG_OOM_ADJ, "Trimming memory of fg " + app.processName
+ " to " + fgTrimLevel);
}
- app.thread.scheduleTrimMemory(fgTrimLevel);
+ thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
profile.setTrimMemoryLevel(fgTrimLevel);
}
- }
+ });
} else {
if (mLowRamStartTime != 0) {
mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
mLowRamStartTime = 0;
}
- for (int i = 0; i < numOfLru; i++) {
- final ProcessRecord app = mService.mProcessList.mLruProcesses.get(i);
+ mService.mProcessList.forEachLruProcessesLOSP(true, app -> {
final ProcessProfileRecord profile = app.mProfile;
- if (allChanged || app.procStateChanged) {
- mService.setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
+ final IApplicationThread thread;
+ final ProcessStateRecord state = app.mState;
+ if (allChanged || state.hasProcStateChanged()) {
+ mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
+ state.setProcStateChanged(false);
}
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && profile.hasPendingUiClean()) {
+ if ((state.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || state.isSystemNoUi()) && profile.hasPendingUiClean()) {
if (profile.getTrimMemoryLevel() < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
- && app.thread != null) {
+ && (thread = app.getThread()) != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
Slog.v(TAG_OOM_ADJ,
"Trimming memory of ui hidden " + app.processName
+ " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
}
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ thread.scheduleTrimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
} catch (RemoteException e) {
}
}
profile.setPendingUiClean(false);
}
profile.setTrimMemoryLevel(0);
- }
+ });
}
return allChanged;
}
- @GuardedBy("mService")
- long getLowRamTimeSinceIdleLocked(long now) {
+ @GuardedBy("mProcLock")
+ long getLowRamTimeSinceIdleLPr(long now) {
return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now - mLowRamStartTime) : 0);
}
@@ -1262,7 +1263,7 @@ public class AppProfiler {
// If there are no longer any background processes running,
// and the app that died was not running instrumentation,
// then tell everyone we are now low on memory.
- if (!mService.mProcessList.haveBackgroundProcessLocked()) {
+ if (!mService.mProcessList.haveBackgroundProcessLOSP()) {
boolean doReport = Build.IS_DEBUGGABLE;
final long now = SystemClock.uptimeMillis();
if (doReport) {
@@ -1272,19 +1273,19 @@ public class AppProfiler {
mLastMemUsageReportTime = now;
}
}
- final int lruSize = mService.mProcessList.getLruSizeLocked();
+ final int lruSize = mService.mProcessList.getLruSizeLOSP();
final ArrayList memInfos = doReport
? new ArrayList(lruSize) : null;
EventLogTags.writeAmLowMemory(lruSize);
- for (int i = lruSize - 1; i >= 0; i--) {
- ProcessRecord rec = mService.mProcessList.mLruProcesses.get(i);
- if (rec == dyingProc || rec.thread == null) {
+ mService.mProcessList.forEachLruProcessesLOSP(false, rec -> {
+ if (rec == dyingProc || rec.getThread() == null) {
return;
}
+ final ProcessStateRecord state = rec.mState;
if (memInfos != null) {
- memInfos.add(new ProcessMemInfo(rec.processName, rec.pid,
- rec.setAdj, rec.setProcState,
- rec.adjType, rec.makeAdjReason()));
+ memInfos.add(new ProcessMemInfo(rec.processName, rec.getPid(),
+ state.getSetAdj(), state.getSetProcState(),
+ state.getAdjType(), state.makeAdjReason()));
}
final ProcessProfileRecord profile = rec.mProfile;
if ((profile.getLastLowMemory() + mService.mConstants.GC_MIN_INTERVAL) <= now) {
@@ -1292,7 +1293,7 @@ public class AppProfiler {
// state for a GC request. Make sure to do
// heavy/important/visible/foreground processes first.
synchronized (mProfilerLock) {
- if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
+ if (state.getSetAdj() <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
profile.setLastRequestedGc(0);
} else {
profile.setLastRequestedGc(profile.getLastLowMemory());
@@ -1303,7 +1304,7 @@ public class AppProfiler {
addProcessToGcListLPf(rec);
}
}
- }
+ });
if (doReport) {
Message msg = mService.mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos);
mService.mHandler.sendMessage(msg);
@@ -1554,7 +1555,9 @@ public class AppProfiler {
PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
String[] emptyArgs = new String[] { };
catPw.println();
- mService.mProcessList.dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null, -1);
+ synchronized (mProcLock) {
+ mService.mProcessList.dumpProcessesLSP(null, catPw, emptyArgs, 0, false, null, -1);
+ }
catPw.println();
mService.mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0,
false, null).dumpLocked();
@@ -1575,7 +1578,7 @@ public class AppProfiler {
}
}
- @GuardedBy("mService")
+ @GuardedBy("mProfilerLock")
private void stopProfilerLPf(ProcessRecord proc, int profileType) {
if (proc == null || proc == mProfileData.getProfileProc()) {
proc = mProfileData.getProfileProc();
@@ -1644,7 +1647,7 @@ public class AppProfiler {
}
mProfileData.getProfilerInfo().profileFd = null;
- if (proc.pid == mService.MY_PID) {
+ if (proc.getPid() == mService.MY_PID) {
// When profiling the system server itself, avoid closing the file
// descriptor, as profilerControl will not create a copy.
// Note: it is also not correct to just set profileFd to null, as the
@@ -1930,6 +1933,7 @@ public class AppProfiler {
AppProfiler(ActivityManagerService service, Looper bgLooper, LowMemDetector detector) {
mService = service;
+ mProcLock = service.mProcLock;
mBgHandler = new BgHandler(bgLooper);
mLowMemDetector = detector;
mProcessCpuThread = new ProcessCpuThread("CpuTracker");
@@ -2027,19 +2031,21 @@ public class AppProfiler {
i >= 0 && app.getActiveInstrumentation() == null; i--) {
ActiveInstrumentation aInstr = mService.mActiveInstrumentation.get(i);
if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
- if (aInstr.mTargetProcesses.length == 0) {
- // This is the wildcard mode, where every process brought up for
- // the target instrumentation should be included.
- if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
- app.setActiveInstrumentation(aInstr);
- aInstr.mRunningProcesses.add(app);
- }
- } else {
- for (String proc : aInstr.mTargetProcesses) {
- if (proc.equals(app.processName)) {
+ synchronized (mProcLock) {
+ if (aInstr.mTargetProcesses.length == 0) {
+ // This is the wildcard mode, where every process brought up for
+ // the target instrumentation should be included.
+ if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
app.setActiveInstrumentation(aInstr);
aInstr.mRunningProcesses.add(app);
- break;
+ }
+ } else {
+ for (String proc : aInstr.mTargetProcesses) {
+ if (proc.equals(app.processName)) {
+ app.setActiveInstrumentation(aInstr);
+ aInstr.mRunningProcesses.add(app);
+ break;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index fca3a52aeeaca..7e65434b81897 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -26,6 +26,7 @@ import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
+import android.app.IApplicationThread;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -222,7 +223,7 @@ public final class BroadcastQueue {
}
public boolean isPendingBroadcastProcessLocked(int pid) {
- return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
+ return mPendingBroadcast != null && mPendingBroadcast.curApp.getPid() == pid;
}
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
@@ -286,19 +287,21 @@ public final class BroadcastQueue {
ProcessRecord app) throws RemoteException {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
- if (app.thread == null) {
+ final IApplicationThread thread = app.getThread();
+ if (thread == null) {
throw new RemoteException();
}
- if (app.inFullBackup) {
+ if (app.isInFullBackup()) {
skipReceiverLocked(r);
return;
}
- r.receiver = app.thread.asBinder();
+ r.receiver = thread.asBinder();
r.curApp = app;
- app.curReceivers.add(r);
- app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
- mService.mProcessList.updateLruProcessLocked(app, false, null);
+ final ProcessReceiverRecord prr = app.mReceivers;
+ prr.addCurReceiver(r);
+ app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
+ mService.updateLruProcessLocked(app, false, null);
// Make sure the oom adj score is updated before delivering the broadcast.
// Force an update, even if there are other pending requests, overall it still saves time,
// because time(updateOomAdj(N apps)) <= N * time(updateOomAdj(1 app)).
@@ -315,10 +318,10 @@ public final class BroadcastQueue {
+ ": " + r);
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
- app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
+ thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackage(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
- app.getReportedProcState());
+ app.mState.getReportedProcState());
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
@@ -328,7 +331,7 @@ public final class BroadcastQueue {
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
- app.curReceivers.remove(r);
+ prr.removeCurReceiver(r);
}
}
}
@@ -336,7 +339,7 @@ public final class BroadcastQueue {
public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
- if (br != null && br.curApp.pid > 0 && br.curApp.pid == app.pid) {
+ if (br != null && br.curApp.getPid() > 0 && br.curApp.getPid() == app.getPid()) {
if (br.curApp != app) {
Slog.e(TAG, "App mismatch when sending pending broadcast to "
+ app.processName + ", intended target is " + br.curApp.processName);
@@ -363,7 +366,7 @@ public final class BroadcastQueue {
public void skipPendingBroadcastLocked(int pid) {
final BroadcastRecord br = mPendingBroadcast;
- if (br != null && br.curApp.pid == pid) {
+ if (br != null && br.curApp.getPid() == pid) {
br.state = BroadcastRecord.IDLE;
br.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
@@ -503,8 +506,8 @@ public final class BroadcastQueue {
r.receiver = null;
r.intent.setComponent(null);
- if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
- r.curApp.curReceivers.remove(r);
+ if (r.curApp != null && r.curApp.mReceivers.hasCurReceiver(r)) {
+ r.curApp.mReceivers.removeCurReceiver(r);
mService.enqueueOomAdjTargetLocked(r.curApp);
}
if (r.curFilter != null) {
@@ -578,12 +581,14 @@ public final class BroadcastQueue {
throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
- if (app.thread != null) {
+ final IApplicationThread thread = app.getThread();
+ if (thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
- app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
- data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
+ thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
+ data, extras, ordered, sticky, sendingUser,
+ app.mState.getReportedProcState());
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
// DeadObjectException when the process isn't actually dead.
//} catch (DeadObjectException ex) {
@@ -593,8 +598,8 @@ public final class BroadcastQueue {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
- + " (pid " + app.pid + "). Crashing it.");
- app.scheduleCrash("can't deliver broadcast");
+ + " (pid " + app.getPid() + "). Crashing it.");
+ app.scheduleCrashLocked("can't deliver broadcast");
}
throw ex;
}
@@ -724,8 +729,8 @@ public final class BroadcastQueue {
skip = true;
}
- if (!skip && (filter.receiverList.app == null || filter.receiverList.app.killed
- || filter.receiverList.app.isCrashing())) {
+ if (!skip && (filter.receiverList.app == null || filter.receiverList.app.isKilled()
+ || filter.receiverList.app.mErrorState.isCrashing())) {
Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
+ " to " + filter.receiverList + ": process gone or crashing");
skip = true;
@@ -794,7 +799,7 @@ public final class BroadcastQueue {
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
- filter.receiverList.app.curReceivers.add(r);
+ filter.receiverList.app.mReceivers.addCurReceiver(r);
mService.enqueueOomAdjTargetLocked(r.curApp);
mService.updateOomAdjPendingTargetsLocked(
OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
@@ -806,7 +811,7 @@ public final class BroadcastQueue {
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
- if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
+ if (filter.receiverList.app != null && filter.receiverList.app.isInFullBackup()) {
// Skip delivery if full backup in progress
// If it's an ordered broadcast, we need to continue to the next receiver.
if (ordered) {
@@ -833,7 +838,7 @@ public final class BroadcastQueue {
if (filter.receiverList.app != null) {
filter.receiverList.app.removeAllowBackgroundActivityStartsToken(r);
if (ordered) {
- filter.receiverList.app.curReceivers.remove(r);
+ filter.receiverList.app.mReceivers.removeCurReceiver(r);
// Something wrong, its oom adj could be downgraded, but not in a hurry.
mService.enqueueOomAdjTargetLocked(r.curApp);
}
@@ -856,8 +861,8 @@ public final class BroadcastQueue {
}
final boolean callerForeground = receiverRecord.callerApp != null
- ? receiverRecord.callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND
- : true;
+ ? receiverRecord.callerApp.mState.getSetSchedGroup()
+ != ProcessList.SCHED_GROUP_BACKGROUND : true;
// Show a permission review UI only for explicit broadcast from a foreground app
if (callerForeground && receiverRecord.intent.getComponent() != null) {
@@ -1018,16 +1023,16 @@ public final class BroadcastQueue {
+ mPendingBroadcast.curApp);
boolean isDead;
- if (mPendingBroadcast.curApp.pid > 0) {
+ if (mPendingBroadcast.curApp.getPid() > 0) {
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(
- mPendingBroadcast.curApp.pid);
- isDead = proc == null || proc.isCrashing();
+ mPendingBroadcast.curApp.getPid());
+ isDead = proc == null || proc.mErrorState.isCrashing();
}
} else {
- final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
+ final ProcessRecord proc = mService.mProcessList.getProcessNamesLOSP().get(
mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
- isDead = proc == null || !proc.pendingStart;
+ isDead = proc == null || !proc.isPendingStart();
}
if (!isDead) {
// It's still alive, so keep waiting
@@ -1497,7 +1502,7 @@ public final class BroadcastQueue {
+ " (uid " + r.callingUid + ")");
skip = true;
}
- if (r.curApp != null && r.curApp.isCrashing()) {
+ if (r.curApp != null && r.curApp.mErrorState.isCrashing()) {
// If the target process is crashing, just skip it.
Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
+ " to " + r.curApp + ": process crashing");
@@ -1548,14 +1553,14 @@ public final class BroadcastQueue {
info.activityInfo.applicationInfo.uid, false);
if (!skip) {
- final int allowed = mService.getAppStartModeLocked(
+ final int allowed = mService.getAppStartModeLOSP(
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// We won't allow this receiver to be launched if the app has been
// completely disabled from launches, or it was not explicitly sent
// to it and the app is in a state that should not receive it
- // (depending on how getAppStartModeLocked has determined that).
+ // (depending on how getAppStartModeLOSP has determined that).
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
Slog.w(TAG, "Background execution disabled: receiving "
+ r.intent + " to "
@@ -1630,7 +1635,7 @@ public final class BroadcastQueue {
}
// Is this receiver's application already running?
- if (app != null && app.thread != null && !app.killed) {
+ if (app != null && app.getThread() != null && !app.isKilled()) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
@@ -1665,13 +1670,13 @@ public final class BroadcastQueue {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Need to start app ["
+ mQueueName + "] " + targetProcess + " for broadcast " + r);
- if ((r.curApp=mService.startProcessLocked(targetProcess,
+ r.curApp = mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
- new HostingRecord("broadcast", r.curComponent),
- isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
- (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
- == null) {
+ new HostingRecord("broadcast", r.curComponent), isActivityCapable
+ ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
+ (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false);
+ if (r.curApp == null) {
// Ah, this recipient is unavailable. Finish it if necessary,
// and mark the broadcast record as ready for the next.
Slog.w(TAG, "Unable to launch app "
diff --git a/services/core/java/com/android/server/am/CacheOomRanker.java b/services/core/java/com/android/server/am/CacheOomRanker.java
index 45ce4c5021bb2..50278fd81bb24 100644
--- a/services/core/java/com/android/server/am/CacheOomRanker.java
+++ b/services/core/java/com/android/server/am/CacheOomRanker.java
@@ -61,6 +61,7 @@ public class CacheOomRanker {
private final Object mPhenotypeFlagLock = new Object();
private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
private final Object mProfilerLock;
@GuardedBy("mPhenotypeFlagLock")
@@ -106,6 +107,7 @@ public class CacheOomRanker {
CacheOomRanker(final ActivityManagerService service) {
mService = service;
+ mProcLock = service.mProcLock;
mProfilerLock = service.mAppProfiler.mProfilerLock;
}
@@ -179,15 +181,14 @@ public class CacheOomRanker {
* Re-rank the cached processes in the lru list with a weighted ordering
* of lru, rss size and number of times the process has been put in the cache.
*/
- public void reRankLruCachedApps(ProcessList processList) {
+ @GuardedBy({"mService", "mProcLock"})
+ void reRankLruCachedAppsLSP(ArrayList lruList, int lruProcessServiceStart) {
float lruWeight;
float usesWeight;
float rssWeight;
int[] lruPositions;
RankedProcessRecord[] scoredProcessRecords;
- ArrayList lruList = processList.mLruProcesses;
-
synchronized (mPhenotypeFlagLock) {
lruWeight = mLruWeight;
usesWeight = mUsesWeight;
@@ -204,11 +205,11 @@ public class CacheOomRanker {
// Collect the least recently used processes to re-rank, only rank cached
// processes further down the list than mLruProcessServiceStart.
int cachedProcessPos = 0;
- for (int i = 0; i < processList.mLruProcessServiceStart
+ for (int i = 0; i < lruProcessServiceStart
&& cachedProcessPos < scoredProcessRecords.length; ++i) {
ProcessRecord app = lruList.get(i);
// Processes that will be assigned a cached oom adj score.
- if (!app.killedByAm && app.thread != null && app.curAdj
+ if (!app.isKilledByAm() && app.getThread() != null && app.mState.getCurAdj()
>= ProcessList.UNKNOWN_ADJ) {
scoredProcessRecords[cachedProcessPos].proc = app;
scoredProcessRecords[cachedProcessPos].score = 0.0f;
@@ -247,7 +248,8 @@ public class CacheOomRanker {
if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
boolean printedHeader = false;
for (int i = 0; i < scoredProcessRecords.length; ++i) {
- if (scoredProcessRecords[i].proc.pid != lruList.get(lruPositions[i]).pid) {
+ if (scoredProcessRecords[i].proc.getPid()
+ != lruList.get(lruPositions[i]).getPid()) {
if (!printedHeader) {
Slog.i(OomAdjuster.TAG, "reRankLruCachedApps");
printedHeader = true;
@@ -291,15 +293,15 @@ public class CacheOomRanker {
private static class LastActivityTimeComparator implements Comparator {
@Override
public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
- return Long.compare(o1.proc.lastActivityTime, o2.proc.lastActivityTime);
+ return Long.compare(o1.proc.getLastActivityTime(), o2.proc.getLastActivityTime());
}
}
private static class CacheUseComparator implements Comparator {
@Override
public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
- return Long.compare(o1.proc.getCacheOomRankerUseCount(),
- o2.proc.getCacheOomRankerUseCount());
+ return Long.compare(o1.proc.mState.getCacheOomRankerUseCount(),
+ o2.proc.mState.getCacheOomRankerUseCount());
}
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index c558b3d004007..c18031fd6de60 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -42,7 +42,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.ServiceThread;
-import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
@@ -153,9 +152,14 @@ public final class CachedAppOptimizer {
*/
final ServiceThread mCachedAppOptimizerThread;
+ @GuardedBy("mProcLock")
private final ArrayList mPendingCompactionProcesses =
new ArrayList();
+
private final ActivityManagerService mAm;
+
+ private final ActivityManagerGlobalLock mProcLock;
+
private final OnPropertiesChangedListener mOnFlagsChangedListener =
new OnPropertiesChangedListener() {
@Override
@@ -234,7 +238,7 @@ public final class CachedAppOptimizer {
@VisibleForTesting
Handler mCompactionHandler;
private Handler mFreezeHandler;
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
private boolean mFreezerOverride = false;
// Maps process ID to last compaction statistics for processes that we've fully compacted. Used
@@ -242,6 +246,7 @@ public final class CachedAppOptimizer {
// data for "some" compactions. Uses LinkedHashMap to ensure insertion order is kept and
// facilitate removal of the oldest entry.
@VisibleForTesting
+ @GuardedBy("mProcLock")
LinkedHashMap mLastCompactionStats =
new LinkedHashMap() {
@Override
@@ -264,6 +269,7 @@ public final class CachedAppOptimizer {
CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback,
ProcessDependencies processDependencies) {
mAm = am;
+ mProcLock = am.mProcLock;
mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread",
Process.THREAD_GROUP_SYSTEM, true);
mProcStateThrottle = new HashSet<>();
@@ -309,7 +315,7 @@ public final class CachedAppOptimizer {
}
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
void dump(PrintWriter pw) {
pw.println("CachedAppOptimizer settings");
synchronized (mPhenotypeFlagLock) {
@@ -350,58 +356,57 @@ public final class CachedAppOptimizer {
}
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
void compactAppSome(ProcessRecord app) {
- app.reqCompactAction = COMPACT_PROCESS_SOME;
+ app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_SOME);
mPendingCompactionProcesses.add(app);
mCompactionHandler.sendMessage(
mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));
+ COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState()));
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
void compactAppFull(ProcessRecord app) {
- app.reqCompactAction = COMPACT_PROCESS_FULL;
+ app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
mPendingCompactionProcesses.add(app);
mCompactionHandler.sendMessage(
mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));
+ COMPACT_PROCESS_MSG, app.mState.getSetAdj(), app.mState.getSetProcState()));
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
void compactAppPersistent(ProcessRecord app) {
- app.reqCompactAction = COMPACT_PROCESS_PERSISTENT;
+ app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_PERSISTENT);
mPendingCompactionProcesses.add(app);
mCompactionHandler.sendMessage(
mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+ COMPACT_PROCESS_MSG, app.mState.getCurAdj(), app.mState.getSetProcState()));
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
boolean shouldCompactPersistent(ProcessRecord app, long now) {
- return (app.lastCompactTime == 0
- || (now - app.lastCompactTime) > mCompactThrottlePersistent);
+ return (app.mOptRecord.getLastCompactTime() == 0
+ || (now - app.mOptRecord.getLastCompactTime()) > mCompactThrottlePersistent);
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
void compactAppBfgs(ProcessRecord app) {
- app.reqCompactAction = COMPACT_PROCESS_BFGS;
+ app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_BFGS);
mPendingCompactionProcesses.add(app);
mCompactionHandler.sendMessage(
mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+ COMPACT_PROCESS_MSG, app.mState.getCurAdj(), app.mState.getSetProcState()));
}
- @GuardedBy("mAm")
+ @GuardedBy("mProcLock")
boolean shouldCompactBFGS(ProcessRecord app, long now) {
- return (app.lastCompactTime == 0
- || (now - app.lastCompactTime) > mCompactThrottleBFGS);
+ return (app.mOptRecord.getLastCompactTime() == 0
+ || (now - app.mOptRecord.getLastCompactTime()) > mCompactThrottleBFGS);
}
- @GuardedBy("mAm")
void compactAllSystem() {
- if (mUseCompaction) {
+ if (useCompaction()) {
mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage(
COMPACT_SYSTEM_MSG));
}
@@ -468,29 +473,28 @@ public final class CachedAppOptimizer {
// Override is applied immediately, restore is delayed
synchronized (mAm) {
- int processCount = mAm.mProcessList.mLruProcesses.size();
+ synchronized (mProcLock) {
+ mFreezerOverride = !enable;
+ Slog.d(TAG_AM, "freezer override set to " + mFreezerOverride);
- mFreezerOverride = !enable;
- Slog.d(TAG_AM, "freezer override set to " + mFreezerOverride);
+ mAm.mProcessList.forEachLruProcessesLOSP(true, process -> {
+ if (process == null) {
+ return;
+ }
- for (int i = 0; i < processCount; i++) {
- ProcessRecord process = mAm.mProcessList.mLruProcesses.get(i);
+ final ProcessCachedOptimizerRecord opt = process.mOptRecord;
+ if (enable && opt.hasFreezerOverride()) {
+ freezeAppAsyncLSP(process);
+ opt.setFreezerOverride(false);
+ }
- if (process == null) {
- continue;
- }
+ if (!enable && opt.isFrozen()) {
+ unfreezeAppLSP(process);
- if (enable && process.freezerOverride) {
- freezeAppAsync(process);
- process.freezerOverride = false;
- }
-
- if (!enable && process.frozen) {
- unfreezeAppLocked(process);
-
- // Set freezerOverride *after* calling unfreezeAppLocked (it resets the flag)
- process.freezerOverride = true;
- }
+ // Set freezerOverride *after* calling unfreezeAppLSP (it resets the flag)
+ opt.setFreezerOverride(true);
+ }
+ });
}
}
@@ -740,19 +744,20 @@ public final class CachedAppOptimizer {
}
// This will ensure app will be out of the freezer for at least FREEZE_TIMEOUT_MS
+ @GuardedBy("mAm")
void unfreezeTemporarily(ProcessRecord app) {
if (mUseFreezer) {
- synchronized (mAm) {
- if (app.frozen) {
- unfreezeAppLocked(app);
- freezeAppAsync(app);
+ synchronized (mProcLock) {
+ if (app.mOptRecord.isFrozen()) {
+ unfreezeAppLSP(app);
+ freezeAppAsyncLSP(app);
}
}
}
}
- @GuardedBy("mAm")
- void freezeAppAsync(ProcessRecord app) {
+ @GuardedBy({"mAm", "mProcLock"})
+ void freezeAppAsyncLSP(ProcessRecord app) {
mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
mFreezeHandler.sendMessageDelayed(
@@ -761,16 +766,17 @@ public final class CachedAppOptimizer {
FREEZE_TIMEOUT_MS);
}
- @GuardedBy("mAm")
- void unfreezeAppLocked(ProcessRecord app) {
+ @GuardedBy({"mAm", "mProcLock"})
+ void unfreezeAppLSP(ProcessRecord app) {
mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
- app.freezerOverride = false;
-
- if (!app.frozen) {
+ final int pid = app.getPid();
+ final ProcessCachedOptimizerRecord opt = app.mOptRecord;
+ opt.setFreezerOverride(false);
+ if (!opt.isFrozen()) {
if (DEBUG_FREEZER) {
Slog.d(TAG_AM,
- "Skipping unfreeze for process " + app.pid + " "
+ "Skipping unfreeze for process " + pid + " "
+ app.processName + " (not frozen)");
}
return;
@@ -781,25 +787,25 @@ public final class CachedAppOptimizer {
boolean processKilled = false;
try {
- int freezeInfo = getBinderFreezeInfo(app.pid);
+ int freezeInfo = getBinderFreezeInfo(pid);
if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {
- Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " "
+ " received sync transactions while frozen, killing");
- app.kill("Sync transaction while in frozen state",
+ app.killLocked("Sync transaction while in frozen state",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
processKilled = true;
}
if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) {
- Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ Slog.d(TAG_AM, "pid " + pid + " " + app.processName + " "
+ " received async transactions while frozen");
}
} catch (Exception e) {
- Slog.d(TAG_AM, "Unable to query binder frozen info for pid " + app.pid + " "
+ Slog.d(TAG_AM, "Unable to query binder frozen info for pid " + pid + " "
+ app.processName + ". Killing it. Exception: " + e);
- app.kill("Unable to query binder frozen stats",
+ app.killLocked("Unable to query binder frozen stats",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
processKilled = true;
@@ -809,38 +815,38 @@ public final class CachedAppOptimizer {
return;
}
- long freezeTime = app.freezeUnfreezeTime;
+ long freezeTime = opt.getFreezeUnfreezeTime();
try {
- freezeBinder(app.pid, false);
+ freezeBinder(pid, false);
} catch (RuntimeException e) {
- Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + pid + " " + app.processName
+ ". Killing it");
- app.kill("Unable to unfreeze",
+ app.killLocked("Unable to unfreeze",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
return;
}
try {
- Process.setProcessFrozen(app.pid, app.uid, false);
+ Process.setProcessFrozen(pid, app.uid, false);
- app.freezeUnfreezeTime = SystemClock.uptimeMillis();
- app.frozen = false;
+ opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());
+ opt.setFrozen(false);
} catch (Exception e) {
- Slog.e(TAG_AM, "Unable to unfreeze " + app.pid + " " + app.processName
+ Slog.e(TAG_AM, "Unable to unfreeze " + pid + " " + app.processName
+ ". This might cause inconsistency or UI hangs.");
}
- if (!app.frozen) {
+ if (!opt.isFrozen()) {
if (DEBUG_FREEZER) {
- Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName);
+ Slog.d(TAG_AM, "sync unfroze " + pid + " " + app.processName);
}
mFreezeHandler.sendMessage(
mFreezeHandler.obtainMessage(REPORT_UNFREEZE_MSG,
- app.pid,
- (int) Math.min(app.freezeUnfreezeTime - freezeTime, Integer.MAX_VALUE),
+ pid,
+ (int) Math.min(opt.getFreezeUnfreezeTime() - freezeTime, Integer.MAX_VALUE),
app.processName));
}
}
@@ -869,6 +875,7 @@ public final class CachedAppOptimizer {
case COMPACT_PROCESS_MSG: {
long start = SystemClock.uptimeMillis();
ProcessRecord proc;
+ final ProcessCachedOptimizerRecord opt;
int pid;
String action;
final String name;
@@ -877,18 +884,19 @@ public final class CachedAppOptimizer {
LastCompactionStats lastCompactionStats;
int lastOomAdj = msg.arg1;
int procState = msg.arg2;
- synchronized (mAm) {
+ synchronized (mProcLock) {
proc = mPendingCompactionProcesses.remove(0);
+ opt = proc.mOptRecord;
- pendingAction = proc.reqCompactAction;
- pid = proc.pid;
+ pendingAction = opt.getReqCompactAction();
+ pid = proc.getPid();
name = proc.processName;
// don't compact if the process has returned to perceptible
// and this is only a cached/home/prev compaction
if ((pendingAction == COMPACT_PROCESS_SOME
|| pendingAction == COMPACT_PROCESS_FULL)
- && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
+ && (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
"Skipping compaction as process " + name + " is "
@@ -897,8 +905,8 @@ public final class CachedAppOptimizer {
return;
}
- lastCompactAction = proc.lastCompactAction;
- lastCompactTime = proc.lastCompactTime;
+ lastCompactAction = opt.getLastCompactAction();
+ lastCompactTime = opt.getLastCompactTime();
lastCompactionStats = mLastCompactionStats.get(pid);
}
@@ -1076,9 +1084,9 @@ public final class CachedAppOptimizer {
lastOomAdj, ActivityManager.processStateAmToProto(procState),
zramFreeKbBefore, zramFreeKbAfter);
}
- synchronized (mAm) {
- proc.lastCompactTime = end;
- proc.lastCompactAction = pendingAction;
+ synchronized (mProcLock) {
+ opt.setLastCompactTime(end);
+ opt.setLastCompactAction(pendingAction);
}
if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])
|| action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) {
@@ -1126,11 +1134,12 @@ public final class CachedAppOptimizer {
}
}
- private void freezeProcess(ProcessRecord proc) {
- final int pid = proc.pid;
+ private void freezeProcess(final ProcessRecord proc) {
+ int pid = proc.getPid(); // Unlocked intentionally
final String name = proc.processName;
final long unfrozenDuration;
final boolean frozen;
+ final ProcessCachedOptimizerRecord opt = proc.mOptRecord;
try {
// pre-check for locks to avoid unnecessary freeze/unfreeze operations
@@ -1146,26 +1155,27 @@ public final class CachedAppOptimizer {
return;
}
- synchronized (mAm) {
- if (proc.curAdj < ProcessList.CACHED_APP_MIN_ADJ
- || proc.shouldNotFreeze) {
+ synchronized (mProcLock) {
+ pid = proc.getPid();
+ if (proc.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ
+ || opt.shouldNotFreeze()) {
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "Skipping freeze for process " + pid
- + " " + name + " curAdj = " + proc.curAdj
- + ", shouldNotFreeze = " + proc.shouldNotFreeze);
+ + " " + name + " curAdj = " + proc.mState.getCurAdj()
+ + ", shouldNotFreeze = " + opt.shouldNotFreeze());
}
return;
}
if (mFreezerOverride) {
- proc.freezerOverride = true;
+ opt.setFreezerOverride(true);
Slog.d(TAG_AM, "Skipping freeze for process " + pid
- + " " + name + " curAdj = " + proc.curAdj
+ + " " + name + " curAdj = " + proc.mState.getCurAdj()
+ "(override)");
return;
}
- if (pid == 0 || proc.frozen) {
+ if (pid == 0 || opt.isFrozen()) {
// Already frozen or not a real process, either one being
// launched or one being killed
return;
@@ -1177,24 +1187,28 @@ public final class CachedAppOptimizer {
freezeBinder(pid, true);
} catch (RuntimeException e) {
Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
- proc.kill("Unable to freeze binder interface",
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ mFreezeHandler.post(() -> {
+ synchronized (mAm) {
+ proc.killLocked("Unable to freeze binder interface",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ }
+ });
}
- long unfreezeTime = proc.freezeUnfreezeTime;
+ long unfreezeTime = opt.getFreezeUnfreezeTime();
try {
Process.setProcessFrozen(pid, proc.uid, true);
- proc.freezeUnfreezeTime = SystemClock.uptimeMillis();
- proc.frozen = true;
+ opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());
+ opt.setFrozen(true);
} catch (Exception e) {
Slog.w(TAG_AM, "Unable to freeze " + pid + " " + name);
}
- unfrozenDuration = proc.freezeUnfreezeTime - unfreezeTime;
- frozen = proc.frozen;
+ unfrozenDuration = opt.getFreezeUnfreezeTime() - unfreezeTime;
+ frozen = opt.isFrozen();
}
if (!frozen) {
@@ -1225,13 +1239,17 @@ public final class CachedAppOptimizer {
}
synchronized (mAm) {
- unfreezeAppLocked(proc);
+ synchronized (mProcLock) {
+ unfreezeAppLSP(proc);
+ }
}
}
} catch (IOException e) {
Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
synchronized (mAm) {
- unfreezeAppLocked(proc);
+ synchronized (mProcLock) {
+ unfreezeAppLSP(proc);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 478c512338f00..f43c7f6278c93 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -57,6 +57,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -148,7 +149,7 @@ public class ContentProviderHelper {
ProcessRecord r = null;
if (caller != null) {
- r = mService.getRecordForAppLocked(caller);
+ r = mService.getRecordForAppLOSP(caller);
if (r == null) {
throw new SecurityException("Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid() + ") when getting content provider "
@@ -183,14 +184,14 @@ public class ContentProviderHelper {
ProcessRecord dyingProc = null;
if (cpr != null && cpr.proc != null) {
- providerRunning = !cpr.proc.killed;
+ providerRunning = !cpr.proc.isKilled();
// Note if killedByAm is also set, this means the provider process has just been
// killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
// yet. So we need to call appDiedLocked() here and let it clean up.
// (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
// how to test this case.)
- if (cpr.proc.killed && cpr.proc.killedByAm) {
+ if (cpr.proc.isKilled() && cpr.proc.isKilledByAm()) {
Slog.wtf(TAG, cpr.proc.toString() + " was killed by AM but isn't really dead");
// Now we are going to wait for the death before starting the new process.
dyingProc = cpr.proc;
@@ -235,7 +236,7 @@ public class ContentProviderHelper {
callingTag, stable, true, startTime, mService.mProcessList);
checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
- final int verifiedAdj = cpr.proc.verifiedAdj;
+ final int verifiedAdj = cpr.proc.mState.getVerifiedAdj();
boolean success = mService.updateOomAdjLocked(cpr.proc, true,
OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
// XXX things have changed so updateOomAdjLocked doesn't actually tell us
@@ -243,7 +244,7 @@ public class ContentProviderHelper {
// it, we will check whether the process still exists. Note that this doesn't
// completely get rid of races with LMK killing the process, but should make
// them much smaller.
- if (success && verifiedAdj != cpr.proc.setAdj
+ if (success && verifiedAdj != cpr.proc.mState.getSetAdj()
&& !isProcessAliveLocked(cpr.proc)) {
success = false;
}
@@ -275,7 +276,7 @@ public class ContentProviderHelper {
conn = null;
dyingProc = cpr.proc;
} else {
- cpr.proc.verifiedAdj = cpr.proc.setAdj;
+ cpr.proc.mState.setVerifiedAdj(cpr.proc.mState.getSetAdj());
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -428,15 +429,18 @@ public class ContentProviderHelper {
checkTime(startTime, "getContentProviderImpl: looking for process record");
ProcessRecord proc = mService.getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
- if (proc != null && proc.thread != null && !proc.killed) {
+ IApplicationThread thread;
+ if (proc != null && (thread = proc.getThread()) != null
+ && !proc.isKilled()) {
if (ActivityManagerDebugConfig.DEBUG_PROVIDER) {
Slog.d(TAG, "Installing in existing process " + proc);
}
- if (!proc.pubProviders.containsKey(cpi.name)) {
+ final ProcessProviderRecord pr = proc.mProviders;
+ if (!pr.hasProvider(cpi.name)) {
checkTime(startTime, "getContentProviderImpl: scheduling install");
- proc.pubProviders.put(cpi.name, cpr);
+ pr.installProvider(cpi.name, cpr);
try {
- proc.thread.scheduleInstallProvider(cpi);
+ thread.scheduleInstallProvider(cpi);
} catch (RemoteException e) {
}
}
@@ -445,8 +449,8 @@ public class ContentProviderHelper {
proc = mService.startProcessLocked(
cpi.processName, cpr.appInfo, false, 0,
new HostingRecord("content provider",
- new ComponentName(
- cpi.applicationInfo.packageName, cpi.name)),
+ new ComponentName(
+ cpi.applicationInfo.packageName, cpi.name)),
Process.ZYGOTE_POLICY_FLAG_EMPTY, false, false, false);
checkTime(startTime, "getContentProviderImpl: after start process");
if (proc == null) {
@@ -558,9 +562,9 @@ public class ContentProviderHelper {
// Note we do it after releasing the lock.
String callerName = "unknown";
if (caller != null) {
- synchronized (mService) {
+ synchronized (mService.mProcLock) {
final ProcessRecord record =
- mService.mProcessList.getLRURecordForAppLocked(caller);
+ mService.mProcessList.getLRURecordForAppLOSP(caller);
if (record != null) {
callerName = record.processName;
}
@@ -600,7 +604,7 @@ public class ContentProviderHelper {
mService.enforceNotIsolatedCaller("publishContentProviders");
synchronized (mService) {
- final ProcessRecord r = mService.getRecordForAppLocked(caller);
+ final ProcessRecord r = mService.getRecordForAppLOSP(caller);
if (DEBUG_MU) {
Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid);
}
@@ -617,7 +621,7 @@ public class ContentProviderHelper {
if (src == null || src.info == null || src.provider == null) {
continue;
}
- ContentProviderRecord dst = r.pubProviders.get(src.info.name);
+ ContentProviderRecord dst = r.mProviders.getProvider(src.info.name);
if (dst == null) {
continue;
}
@@ -808,7 +812,7 @@ public class ContentProviderHelper {
}
ProcessRecord proc = conn.provider.proc;
- if (proc == null || proc.thread == null) {
+ if (proc == null || proc.getThread() == null) {
// Seems like the process is already cleaned up.
return;
}
@@ -816,7 +820,7 @@ public class ContentProviderHelper {
// As far as we're concerned, this is just like receiving a
// death notification... just a bit prematurely.
mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
- + " (pid " + proc.pid + ") early provider death", proc.info.uid);
+ + " (pid " + proc.getPid() + ") early provider death", proc.info.uid);
final long token = Binder.clearCallingIdentity();
try {
mService.appDiedLocked(proc, "unstable content provider");
@@ -1074,7 +1078,8 @@ public class ContentProviderHelper {
}
int numProviders = providers.size();
- app.pubProviders.ensureCapacity(numProviders + app.pubProviders.size());
+ final ProcessProviderRecord pr = app.mProviders;
+ pr.ensureProviderCapacity(numProviders + pr.numberOfProviders());
for (int i = 0; i < numProviders; i++) {
// NOTE: keep logic in sync with installEncryptionUnawareProviders
ProviderInfo cpi = providers.get(i);
@@ -1111,7 +1116,7 @@ public class ContentProviderHelper {
if (DEBUG_MU) {
Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
}
- app.pubProviders.put(cpi.name, cpr);
+ pr.installProvider(cpi.name, cpr);
if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
@@ -1162,7 +1167,8 @@ public class ContentProviderHelper {
public final void installSystemProviders() {
List providers;
synchronized (mService) {
- ProcessRecord app = mService.mProcessList.mProcessNames.get("system", SYSTEM_UID);
+ ProcessRecord app = mService.mProcessList
+ .getProcessNamesLOSP().get("system", SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i = providers.size() - 1; i >= 0; i--) {
@@ -1205,25 +1211,29 @@ public class ContentProviderHelper {
final int matchFlags =
PackageManager.GET_PROVIDERS | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- synchronized (mService) {
- final int numProc = mService.mProcessList.mProcessNames.getMap().size();
+ synchronized (mService.mProcLock) {
+ final ArrayMap> pmap =
+ mService.mProcessList.getProcessNamesLOSP().getMap();
+ final int numProc = pmap.size();
for (int iProc = 0; iProc < numProc; iProc++) {
- final SparseArray apps =
- mService.mProcessList.mProcessNames.getMap().valueAt(iProc);
+ final SparseArray apps = pmap.valueAt(iProc);
for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
final ProcessRecord app = apps.valueAt(iApp);
- if (app.userId != userId || app.thread == null || app.unlocked) continue;
+ if (app.userId != userId || app.getThread() == null || app.isUnlocked()) {
+ continue;
+ }
app.getPkgList().forEachPackage(pkgName -> {
try {
final PackageInfo pkgInfo = AppGlobals.getPackageManager()
- .getPackageInfo(pkgName, matchFlags, userId);
+ .getPackageInfo(pkgName, matchFlags, app.userId);
+ final IApplicationThread thread = app.getThread();
if (pkgInfo != null && !ArrayUtils.isEmpty(pkgInfo.providers)) {
for (ProviderInfo pi : pkgInfo.providers) {
// NOTE: keep in sync with generateApplicationProvidersLocked
final boolean processMatch =
Objects.equals(pi.processName, app.processName)
- || pi.multiprocess;
+ || pi.multiprocess;
final boolean userMatch = !mService.isSingleton(
pi.processName, pi.applicationInfo, pi.name, pi.flags)
|| app.userId == UserHandle.USER_SYSTEM;
@@ -1234,7 +1244,7 @@ public class ContentProviderHelper {
if (processMatch && userMatch
&& (!isInstantApp || splitInstalled)) {
Log.v(TAG, "Installing " + pi);
- app.thread.scheduleInstallProvider(pi);
+ thread.scheduleInstallProvider(pi);
} else {
Log.v(TAG, "Skipping " + pi);
}
@@ -1259,8 +1269,9 @@ public class ContentProviderHelper {
}
- for (int i = 0, size = r.conProviders.size(); i < size; i++) {
- ContentProviderConnection conn = r.conProviders.get(i);
+ final ProcessProviderRecord pr = r.mProviders;
+ for (int i = 0, size = pr.numberOfProviderConnections(); i < size; i++) {
+ ContentProviderConnection conn = pr.getProviderConnectionAt(i);
if (conn.provider == cpr) {
conn.incrementCount(stable);
return conn;
@@ -1272,10 +1283,11 @@ public class ContentProviderHelper {
conn.startAssociationIfNeeded();
conn.initializeCount(stable);
cpr.connections.add(conn);
- r.conProviders.add(conn);
- mService.startAssociationLocked(r.uid, r.processName, r.getCurProcState(),
+ pr.addProviderConnection(conn);
+ mService.startAssociationLocked(r.uid, r.processName, r.mState.getCurProcState(),
cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
- if (updateLru && cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ if (updateLru && cpr.proc != null
+ && r.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
// If this is a perceptible app accessing the provider, make
// sure to count it as being accessed and thus back up on
// the LRU list. This is good because content providers are
@@ -1325,13 +1337,14 @@ public class ContentProviderHelper {
final ContentProviderRecord cpr = conn.provider;
conn.stopAssociation();
cpr.connections.remove(conn);
- conn.client.conProviders.remove(conn);
- if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
+ conn.client.mProviders.removeProviderConnection(conn);
+ if (conn.client.mState.getSetProcState()
+ < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
// The client is more important than last activity -- note the time this
// is happening, so we keep the old provider process around a bit as last
// activity to avoid thrashing it.
if (cpr.proc != null) {
- cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
+ cpr.proc.mProviders.setLastProviderTime(SystemClock.uptimeMillis());
}
}
mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
@@ -1429,9 +1442,9 @@ public class ContentProviderHelper {
return mService.validateAssociationAllowedLocked(cpi.packageName,
cpi.applicationInfo.uid, null, callingUid) ? null : "";
}
- final String r = callingApp.getPkgList().forEachPackage(pkgName -> {
+ final String r = callingApp.getPkgList().searchEachPackage(pkgName -> {
if (!mService.validateAssociationAllowedLocked(pkgName,
- callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) {
+ callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) {
return cpi.packageName;
}
return null;
@@ -1455,8 +1468,8 @@ public class ContentProviderHelper {
private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
String authority) {
- if (app == null
- || app.getCurProcState() > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ if (app == null || app.mState.getCurProcState()
+ > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
return;
}
@@ -1483,31 +1496,30 @@ public class ContentProviderHelper {
private final long[] mProcessStateStatsLongs = new long[1];
private boolean isProcessAliveLocked(ProcessRecord proc) {
- if (proc.pid <= 0) {
+ final int pid = proc.getPid();
+ if (pid <= 0) {
if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
Slog.d(ActivityManagerService.TAG, "Process hasn't started yet: " + proc);
}
return false;
}
- if (proc.procStatFile == null) {
- proc.procStatFile = "/proc/" + proc.pid + "/stat";
- }
+ final String procStatFile = "/proc/" + pid + "/stat";
mProcessStateStatsLongs[0] = 0;
- if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+ if (!Process.readProcFile(procStatFile, PROCESS_STATE_STATS_FORMAT, null,
mProcessStateStatsLongs, null)) {
if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
Slog.d(ActivityManagerService.TAG,
- "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
+ "UNABLE TO RETRIEVE STATE FOR " + procStatFile);
}
return false;
}
final long state = mProcessStateStatsLongs[0];
if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
Slog.d(ActivityManagerService.TAG,
- "RETRIEVED STATE FOR " + proc.procStatFile + ": " + (char) state);
+ "RETRIEVED STATE FOR " + procStatFile + ": " + (char) state);
}
if (state != 'Z' && state != 'X' && state != 'x' && state != 'K') {
- return Process.getUidForPid(proc.pid) == proc.uid;
+ return Process.getUidForPid(pid) == proc.uid;
}
return false;
}
@@ -1537,7 +1549,7 @@ public class ContentProviderHelper {
}
final boolean callerForeground = r == null
- || r.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
+ || r.mState.getSetSchedGroup() != ProcessList.SCHED_GROUP_BACKGROUND;
// Show a permission review UI only for starting from a foreground app
if (!callerForeground) {
@@ -1611,26 +1623,29 @@ public class ContentProviderHelper {
}
}
ProcessRecord capp = conn.client;
+ final IApplicationThread thread = capp.getThread();
conn.dead = true;
if (conn.stableCount() > 0) {
- if (!capp.isPersistent() && capp.thread != null
- && capp.pid != 0 && capp.pid != ActivityManagerService.MY_PID) {
- capp.kill("depends on provider " + cpr.name.flattenToShortString()
- + " in dying proc " + (proc != null ? proc.processName : "??")
- + " (adj " + (proc != null ? proc.setAdj : "??") + ")",
+ final int pid = capp.getPid();
+ if (!capp.isPersistent() && thread != null
+ && pid != 0 && pid != ActivityManagerService.MY_PID) {
+ capp.killLocked(
+ "depends on provider " + cpr.name.flattenToShortString()
+ + " in dying proc " + (proc != null ? proc.processName : "??")
+ + " (adj " + (proc != null ? proc.mState.getSetAdj() : "??") + ")",
ApplicationExitInfo.REASON_DEPENDENCY_DIED,
ApplicationExitInfo.SUBREASON_UNKNOWN,
true);
}
- } else if (capp.thread != null && conn.provider.provider != null) {
+ } else if (thread != null && conn.provider.provider != null) {
try {
- capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
+ thread.unstableProviderDied(conn.provider.provider.asBinder());
} catch (RemoteException e) {
}
// In the protocol here, we don't expect the client to correctly
// clean up this connection, we'll just remove it.
cpr.connections.remove(i);
- if (conn.client.conProviders.remove(conn)) {
+ if (conn.client.mProviders.removeProviderConnection(conn)) {
mService.stopAssociationLocked(capp.uid, capp.processName,
cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
}
@@ -1671,7 +1686,7 @@ public class ContentProviderHelper {
// It's being launched but we've reached maximum attempts, mark it as bad
alwaysBad = true;
}
- if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
+ if (!alwaysBad && !app.mErrorState.isBad() && cpr.hasConnectionOrHandle()) {
restart = true;
} else {
removeDyingProviderLocked(app, cpr, true);
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index 59a19398420d2..b217cae61d4cb 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import android.app.ContentProviderHolder;
+import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.IContentProvider;
import android.content.pm.ApplicationInfo;
@@ -211,9 +212,10 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
+ " caller=" + client);
}
}
- if (client.thread != null) {
+ final IApplicationThread thread = client.getThread();
+ if (thread != null) {
try {
- client.thread.notifyContentProviderPublishStatus(
+ thread.notifyContentProviderPublishStatus(
newHolder(status ? conn : null, false),
info.authority, userId, status);
} catch (RemoteException e) {
@@ -343,8 +345,8 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
&& mAssociation == null && provider.proc != null
&& (provider.appInfo.uid != mOwningUid
|| !provider.info.processName.equals(mOwningProcessName))) {
- ProcessStats.ProcessStateHolder holder = provider.proc.getPkgList().get(
- provider.name.getPackageName());
+ ProcessStats.ProcessStateHolder holder =
+ provider.proc.getPkgList().get(provider.name.getPackageName());
if (holder == null) {
Slog.wtf(TAG_AM, "No package in referenced provider "
+ provider.name.toShortString() + ": proc=" + provider.proc);
@@ -373,7 +375,7 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
if (hasExternalProcessHandles() &&
externalProcessTokenToHandle.get(mToken) != null) {
removeExternalProcessHandleInternalLocked(mToken);
- }
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ErrorDialogController.java b/services/core/java/com/android/server/am/ErrorDialogController.java
new file mode 100644
index 0000000000000..ef135d55e43cd
--- /dev/null
+++ b/services/core/java/com/android/server/am/ErrorDialogController.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.Dialog;
+import android.content.Context;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * A controller to generate error dialogs in {@link ProcessRecord}.
+ */
+final class ErrorDialogController {
+ private final ProcessRecord mApp;
+ private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
+
+ /**
+ * Dialogs being displayed due to crash.
+ */
+ @GuardedBy("mProcLock")
+ private List mCrashDialogs;
+
+ /**
+ * Dialogs being displayed due to app not responding.
+ */
+ @GuardedBy("mProcLock")
+ private List mAnrDialogs;
+
+ /**
+ * Dialogs displayed due to strict mode violation.
+ */
+ @GuardedBy("mProcLock")
+ private List mViolationDialogs;
+
+ /**
+ * Current wait for debugger dialog.
+ */
+ @GuardedBy("mProcLock")
+ private AppWaitingForDebuggerDialog mWaitDialog;
+
+ @GuardedBy("mProcLock")
+ boolean hasCrashDialogs() {
+ return mCrashDialogs != null;
+ }
+
+ @GuardedBy("mProcLock")
+ List getCrashDialogs() {
+ return mCrashDialogs;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasAnrDialogs() {
+ return mAnrDialogs != null;
+ }
+
+ @GuardedBy("mProcLock")
+ List getAnrDialogs() {
+ return mAnrDialogs;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasViolationDialogs() {
+ return mViolationDialogs != null;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasDebugWaitingDialog() {
+ return mWaitDialog != null;
+ }
+
+ @GuardedBy("mProcLock")
+ void clearAllErrorDialogs() {
+ clearCrashDialogs();
+ clearAnrDialogs();
+ clearViolationDialogs();
+ clearWaitingDialog();
+ }
+
+ @GuardedBy("mProcLock")
+ void clearCrashDialogs() {
+ clearCrashDialogs(true /* needDismiss */);
+ }
+
+ @GuardedBy("mProcLock")
+ void clearCrashDialogs(boolean needDismiss) {
+ if (mCrashDialogs == null) {
+ return;
+ }
+ if (needDismiss) {
+ forAllDialogs(mCrashDialogs, Dialog::dismiss);
+ }
+ mCrashDialogs = null;
+ }
+
+ @GuardedBy("mProcLock")
+ void clearAnrDialogs() {
+ if (mAnrDialogs == null) {
+ return;
+ }
+ forAllDialogs(mAnrDialogs, Dialog::dismiss);
+ mAnrDialogs = null;
+ }
+
+ @GuardedBy("mProcLock")
+ void clearViolationDialogs() {
+ if (mViolationDialogs == null) {
+ return;
+ }
+ forAllDialogs(mViolationDialogs, Dialog::dismiss);
+ mViolationDialogs = null;
+ }
+
+ @GuardedBy("mProcLock")
+ void clearWaitingDialog() {
+ if (mWaitDialog == null) {
+ return;
+ }
+ mWaitDialog.dismiss();
+ mWaitDialog = null;
+ }
+
+ void forAllDialogs(List extends BaseErrorDialog> dialogs, Consumer c) {
+ for (int i = dialogs.size() - 1; i >= 0; i--) {
+ c.accept(dialogs.get(i));
+ }
+ }
+
+ @GuardedBy("mProcLock")
+ void showCrashDialogs(AppErrorDialog.Data data) {
+ List contexts = getDisplayContexts(false /* lastUsedOnly */);
+ mCrashDialogs = new ArrayList<>();
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mCrashDialogs.add(new AppErrorDialog(c, mService, data));
+ }
+ mService.mUiHandler.post(() -> {
+ List dialogs;
+ synchronized (mProcLock) {
+ dialogs = mCrashDialogs;
+ }
+ if (dialogs != null) {
+ forAllDialogs(dialogs, Dialog::show);
+ }
+ });
+ }
+
+ @GuardedBy("mProcLock")
+ void showAnrDialogs(AppNotRespondingDialog.Data data) {
+ List contexts = getDisplayContexts(
+ mApp.mErrorState.isSilentAnr() /* lastUsedOnly */);
+ mAnrDialogs = new ArrayList<>();
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
+ }
+ mService.mUiHandler.post(() -> {
+ List dialogs;
+ synchronized (mProcLock) {
+ dialogs = mAnrDialogs;
+ }
+ if (dialogs != null) {
+ forAllDialogs(dialogs, Dialog::show);
+ }
+ });
+ }
+
+ @GuardedBy("mProcLock")
+ void showViolationDialogs(AppErrorResult res) {
+ List contexts = getDisplayContexts(false /* lastUsedOnly */);
+ mViolationDialogs = new ArrayList<>();
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mViolationDialogs.add(
+ new StrictModeViolationDialog(c, mService, res, mApp));
+ }
+ mService.mUiHandler.post(() -> {
+ List dialogs;
+ synchronized (mProcLock) {
+ dialogs = mViolationDialogs;
+ }
+ if (dialogs != null) {
+ forAllDialogs(dialogs, Dialog::show);
+ }
+ });
+ }
+
+ @GuardedBy("mProcLock")
+ void showDebugWaitingDialogs() {
+ List contexts = getDisplayContexts(true /* lastUsedOnly */);
+ final Context c = contexts.get(0);
+ mWaitDialog = new AppWaitingForDebuggerDialog(mService, c, mApp);
+
+ mService.mUiHandler.post(() -> {
+ Dialog dialog;
+ synchronized (mProcLock) {
+ dialog = mWaitDialog;
+ }
+ if (dialog != null) {
+ dialog.show();
+ }
+ });
+ }
+
+ /**
+ * Helper function to collect contexts from crashed app located displays.
+ *
+ * @param lastUsedOnly Sets to {@code true} to indicate to only get last used context.
+ * Sets to {@code false} to collect contexts from crashed app located
+ * displays.
+ *
+ * @return display context list.
+ */
+ private List getDisplayContexts(boolean lastUsedOnly) {
+ List displayContexts = new ArrayList<>();
+ if (!lastUsedOnly) {
+ mApp.getWindowProcessController().getDisplayContextsWithErrorDialogs(displayContexts);
+ }
+ // If there is no foreground window display, fallback to last used display.
+ if (displayContexts.isEmpty() || lastUsedOnly) {
+ displayContexts.add(mService.mWmInternal != null
+ ? mService.mWmInternal.getTopFocusedDisplayUiContext()
+ : mService.mUiContext);
+ }
+ return displayContexts;
+ }
+
+ ErrorDialogController(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ mProcLock = mService.mProcLock;
+ }
+}
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index 6e42aee3ba2aa..94eb07611037b 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -16,6 +16,12 @@
package com.android.server.am;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.SOCK_STREAM;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_RCVTIMEO;
+import static android.system.OsConstants.SO_SNDTIMEO;
+
import android.app.ApplicationErrorReport.CrashInfo;
import android.system.ErrnoException;
import android.system.Os;
@@ -23,8 +29,6 @@ import android.system.StructTimeval;
import android.system.UnixSocketAddress;
import android.util.Slog;
-import static android.system.OsConstants.*;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
@@ -259,8 +263,10 @@ final class NativeCrashListener extends Thread {
// even though the process will vanish as soon as we let
// debuggerd proceed.
synchronized (mAm) {
- pr.setCrashing(true);
- pr.forceCrashReport = true;
+ synchronized (mAm.mProcLock) {
+ pr.mErrorState.setCrashing(true);
+ pr.mErrorState.setForceCrashReport(true);
+ }
}
// Crash reporting is synchronous but we want to let debuggerd
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index c075336ecc1ec..d79fb8a265e88 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -100,6 +100,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
@@ -206,11 +207,12 @@ public final class OomAdjuster {
int mNumCachedHiddenProcs = 0;
/** Track all uids that have actively running processes. */
+ @CompositeRWLock({"mService", "mProcLock"})
ActiveUids mActiveUids;
/**
* The handler to execute {@link #setProcessGroup} (it may be heavy if the process has many
- * threads) for reducing the time spent in {@link #applyOomAdjLocked}.
+ * threads) for reducing the time spent in {@link #applyOomAdjLSP}.
*/
private final Handler mProcessGroupHandler;
@@ -218,6 +220,7 @@ public final class OomAdjuster {
private final ActivityManagerService mService;
private final ProcessList mProcessList;
+ private final ActivityManagerGlobalLock mProcLock;
private final int mNumSlots;
private final ArrayList mTmpProcessList = new ArrayList();
@@ -333,6 +336,7 @@ public final class OomAdjuster {
ServiceThread adjusterThread) {
mService = service;
mProcessList = processList;
+ mProcLock = service.mProcLock;
mActiveUids = activeUids;
mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
@@ -389,24 +393,28 @@ public final class OomAdjuster {
@VisibleForTesting
@GuardedBy("mService")
void handleUserSwitchedLocked() {
+ mProcessList.forEachLruProcessesLOSP(false,
+ this::updateKeepWarmIfNecessaryForProcessLocked);
+ }
+
+ @GuardedBy("mService")
+ private void updateKeepWarmIfNecessaryForProcessLocked(final ProcessRecord app) {
final ArraySet warmServices = mService.mConstants.KEEP_WARMING_SERVICES;
- final ArrayList processes = mProcessList.mLruProcesses;
- for (int i = processes.size() - 1; i >= 0; i--) {
- final ProcessRecord app = processes.get(i);
- boolean includeWarmPkg = false;
- for (int j = warmServices.size() - 1; j >= 0; j--) {
- if (app.getPkgList().containsKey(warmServices.valueAt(j).getPackageName())) {
- includeWarmPkg = true;
- break;
- }
- }
- if (!includeWarmPkg) {
- continue;
- }
- for (int j = app.numberOfRunningServices() - 1; j >= 0; j--) {
- app.getRunningServiceAt(j).updateKeepWarmLocked();
+ boolean includeWarmPkg = false;
+ final PackageList pkgList = app.getPkgList();
+ for (int j = warmServices.size() - 1; j >= 0; j--) {
+ if (pkgList.containsKey(warmServices.valueAt(j).getPackageName())) {
+ includeWarmPkg = true;
+ break;
}
}
+ if (!includeWarmPkg) {
+ return;
+ }
+ final ProcessServiceRecord psr = app.mServices;
+ for (int j = psr.numberOfRunningServices() - 1; j >= 0; j--) {
+ psr.getRunningServiceAt(j).updateKeepWarmLocked();
+ }
}
/**
@@ -420,11 +428,20 @@ public final class OomAdjuster {
@GuardedBy("mService")
boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
String oomAdjReason) {
+ synchronized (mProcLock) {
+ return updateOomAdjLSP(app, oomAdjAll, oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean updateOomAdjLSP(ProcessRecord app, boolean oomAdjAll,
+ String oomAdjReason) {
if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
- return updateOomAdjLocked(app, oomAdjReason);
+ return updateOomAdjLSP(app, oomAdjReason);
}
final ProcessRecord topApp = mService.getTopApp();
- final boolean wasCached = app.isCached();
+ final ProcessStateRecord state = app.mState;
+ final boolean wasCached = state.isCached();
mAdjSeq++;
@@ -432,30 +449,31 @@ public final class OomAdjuster {
// If our app is currently cached, we know it, and that is it. Otherwise,
// we don't know it yet, and it needs to now be cached we will then
// need to do a complete oom adj.
- final int cachedAdj = app.getCurRawAdj() >= ProcessList.CACHED_APP_MIN_ADJ
- ? app.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
+ final int cachedAdj = state.getCurRawAdj() >= ProcessList.CACHED_APP_MIN_ADJ
+ ? state.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
- boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
+ boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
if (oomAdjAll
- && (wasCached != app.isCached() || app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
+ && (wasCached != state.isCached()
+ || state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
// Changed to/from cached state, so apps after it in the LRU
// list may also be changed.
- updateOomAdjLocked(oomAdjReason);
+ updateOomAdjLSP(oomAdjReason);
}
return success;
}
- @GuardedBy("mService")
- private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean updateOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord TOP_APP, boolean doingAll, long now) {
- if (app.thread == null) {
+ if (app.getThread() == null) {
return false;
}
- app.resetCachedInfo();
- UidRecord uidRec = app.uidRecord;
+ app.mState.resetCachedInfo();
+ UidRecord uidRec = app.getUidRecord();
if (uidRec != null) {
if (DEBUG_UID_OBSERVERS) {
Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
@@ -466,35 +484,23 @@ public final class OomAdjuster {
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
- computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);
+ computeOomAdjLSP(app, cachedAdj, TOP_APP, doingAll, now, false, true);
- boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
+ boolean success = applyOomAdjLSP(app, doingAll, now, SystemClock.elapsedRealtime());
if (uidRec != null) {
- // After uidRec.reset() above, for UidRecord that has multiple processes (ProcessRecord)
- // , We need to apply all ProcessRecord into UidRecord.
- final ArraySet procRecords = app.uidRecord.procRecords;
- for (int i = procRecords.size() - 1; i >= 0; i--) {
- final ProcessRecord pr = procRecords.valueAt(i);
- if (!pr.killedByAm && pr.thread != null) {
- if (pr.isolated && pr.numberOfRunningServices() <= 0
- && pr.isolatedEntryPoint == null) {
- // No op.
- } else {
- // Keeping this process, update its uid.
- updateAppUidRecLocked(pr);
- }
- }
- }
+ // After uidRec.reset() above, for UidRecord with multiple processes (ProcessRecord),
+ // we need to apply all ProcessRecord into UidRecord.
+ uidRec.forEachProcess(this::updateAppUidRecIfNecessaryLSP);
if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
- && (uidRec.setProcState != uidRec.getCurProcState()
- || uidRec.setCapability != uidRec.curCapability
- || uidRec.mSetAllowlist != uidRec.mCurAllowlist)) {
+ && (uidRec.getSetProcState() != uidRec.getCurProcState()
+ || uidRec.getSetCapability() != uidRec.getCurCapability()
+ || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
ActiveUids uids = mTmpUidRecords;
uids.clear();
- uids.put(uidRec.uid, uidRec);
- updateUidsLocked(uids, SystemClock.elapsedRealtime());
- mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
+ uids.put(uidRec.getUid(), uidRec);
+ updateUidsLSP(uids, SystemClock.elapsedRealtime());
+ mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids);
}
}
@@ -506,11 +512,18 @@ public final class OomAdjuster {
*/
@GuardedBy("mService")
void updateOomAdjLocked(String oomAdjReason) {
+ synchronized (mProcLock) {
+ updateOomAdjLSP(oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateOomAdjLSP(String oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
// Clear any pending ones because we are doing a full update now.
mPendingProcessSet.clear();
mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
- updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
+ updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true);
}
/**
@@ -523,8 +536,15 @@ public final class OomAdjuster {
*/
@GuardedBy("mService")
boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+ synchronized (mProcLock) {
+ return updateOomAdjLSP(app, oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
- updateOomAdjLocked(oomAdjReason);
+ updateOomAdjLSP(oomAdjReason);
return true;
}
@@ -535,20 +555,23 @@ public final class OomAdjuster {
mAdjSeq++;
// Firstly, try to see if the importance of itself gets changed
- final boolean wasCached = app.isCached();
- final int oldAdj = app.getCurRawAdj();
+ final ProcessStateRecord state = app.mState;
+ final boolean wasCached = state.isCached();
+ final int oldAdj = state.getCurRawAdj();
final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
? oldAdj : ProcessList.UNKNOWN_ADJ;
- final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
- app.containsCycle = false;
- app.procStateChanged = false;
- app.resetCachedInfo();
+ final boolean wasBackground = ActivityManager.isProcStateBackground(
+ state.getSetProcState());
+ state.setContainsCycle(false);
+ state.setProcStateChanged(false);
+ state.resetCachedInfo();
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
- boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
+ boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
- if (!success || (wasCached == app.isCached() && oldAdj != ProcessList.INVALID_ADJ
- && wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
+ if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ
+ && wasBackground == ActivityManager.isProcStateBackground(
+ state.getSetProcState()))) {
// Okay, it's unchanged, it won't impact any service it binds to, we're done here.
if (DEBUG_OOM_ADJ) {
Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
@@ -570,23 +593,25 @@ public final class OomAdjuster {
// Track if any of them reachables could include a cycle
boolean containsCycle = false;
// Scan downstreams of the process record
- app.mReachable = true;
+ state.setReachable(true);
for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
if (pr != app) {
processes.add(pr);
}
- if (pr.uidRecord != null) {
- uids.put(pr.uidRecord.uid, pr.uidRecord);
+ final UidRecord uidRec = pr.getUidRecord();
+ if (uidRec != null) {
+ uids.put(uidRec.getUid(), uidRec);
}
- for (int i = pr.connections.size() - 1; i >= 0; i--) {
- ConnectionRecord cr = pr.connections.valueAt(i);
+ final ProcessServiceRecord psr = pr.mServices;
+ for (int i = psr.numberOfConnections() - 1; i >= 0; i--) {
+ ConnectionRecord cr = psr.getConnectionAt(i);
ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
? cr.binding.service.isolatedProc : cr.binding.service.app;
if (service == null || service == pr) {
continue;
}
- containsCycle |= service.mReachable;
- if (service.mReachable) {
+ containsCycle |= service.mState.isReachable();
+ if (service.mState.isReachable()) {
continue;
}
if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
@@ -596,24 +621,26 @@ public final class OomAdjuster {
continue;
}
queue.offer(service);
- service.mReachable = true;
+ service.mState.setReachable(true);
// During scanning the reachable dependants, remove them from the pending oomadj
// targets list if it's possible, as they've been added into the immediate
// oomadj targets list 'processes' above.
mPendingProcessSet.remove(service);
}
- for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
- ContentProviderConnection cpc = pr.conProviders.get(i);
+ final ProcessProviderRecord ppr = pr.mProviders;
+ for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) {
+ ContentProviderConnection cpc = ppr.getProviderConnectionAt(i);
ProcessRecord provider = cpc.provider.proc;
- if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
+ if (provider == null || provider == pr
+ || (containsCycle |= provider.mState.isReachable())) {
continue;
}
- containsCycle |= provider.mReachable;
- if (provider.mReachable) {
+ containsCycle |= provider.mState.isReachable();
+ if (provider.mState.isReachable()) {
continue;
}
queue.offer(provider);
- provider.mReachable = true;
+ provider.mState.setReachable(true);
// During scanning the reachable dependants, remove them from the pending oomadj
// targets list if it's possible, as they've been added into the immediate
// oomadj targets list 'processes' above.
@@ -622,10 +649,10 @@ public final class OomAdjuster {
}
// Reset the flag
- app.mReachable = false;
+ state.setReachable(false);
int size = processes.size();
if (size > 0) {
- // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
+ // Reverse the process list, since the updateOomAdjInnerLSP scans from the end of it.
for (int l = 0, r = size - 1; l < r; l++, r--) {
ProcessRecord t = processes.get(l);
processes.set(l, processes.get(r));
@@ -633,13 +660,13 @@ public final class OomAdjuster {
}
mAdjSeq--;
// Update these reachable processes
- updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
- } else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
+ updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
+ } else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
// In case the app goes from non-cached to cached but it doesn't have other reachable
// processes, its adj could be still unknown as of now, assign one.
processes.add(app);
assignCachedAdjIfNecessary(processes);
- applyOomAdjLocked(app, false, SystemClock.uptimeMillis(),
+ applyOomAdjLSP(app, false, SystemClock.uptimeMillis(),
SystemClock.elapsedRealtime());
}
mTmpProcessList.clear();
@@ -684,17 +711,20 @@ public final class OomAdjuster {
final ArrayList processes = mTmpProcessList;
final ActiveUids uids = mTmpUidRecords;
- uids.clear();
- processes.clear();
- for (int i = mPendingProcessSet.size() - 1; i >= 0; i--) {
- final ProcessRecord app = mPendingProcessSet.valueAt(i);
- if (app.uidRecord != null) {
- uids.put(app.uidRecord.uid, app.uidRecord);
+ synchronized (mProcLock) {
+ uids.clear();
+ processes.clear();
+ for (int i = mPendingProcessSet.size() - 1; i >= 0; i--) {
+ final ProcessRecord app = mPendingProcessSet.valueAt(i);
+ final UidRecord uidRec = app.getUidRecord();
+ if (uidRec != null) {
+ uids.put(uidRec.getUid(), uidRec);
+ }
+ processes.add(app);
}
- processes.add(app);
- }
- updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, true, false);
+ updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false);
+ }
processes.clear();
mPendingProcessSet.clear();
@@ -707,8 +737,8 @@ public final class OomAdjuster {
* list if the given list is null; when it's partial update, each process's client proc won't
* get evaluated recursively here.
*/
- @GuardedBy("mService")
- private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp,
ArrayList processes, ActiveUids uids, boolean potentialCycles,
boolean startProfiling) {
if (startProfiling) {
@@ -720,7 +750,7 @@ public final class OomAdjuster {
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final boolean fullUpdate = processes == null;
ActiveUids activeUids = uids;
- ArrayList activeProcesses = fullUpdate ? mProcessList.mLruProcesses
+ ArrayList activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
: processes;
final int numProc = activeProcesses.size();
@@ -729,8 +759,8 @@ public final class OomAdjuster {
activeUids = mTmpUidRecords;
activeUids.clear();
for (int i = 0; i < numUids; i++) {
- UidRecord r = mActiveUids.valueAt(i);
- activeUids.put(r.uid, r);
+ UidRecord uidRec = mActiveUids.valueAt(i);
+ activeUids.put(uidRec.getUid(), uidRec);
}
}
@@ -752,36 +782,39 @@ public final class OomAdjuster {
boolean retryCycles = false;
boolean computeClients = fullUpdate || potentialCycles;
- // need to reset cycle state before calling computeOomAdjLocked because of service conns
+ // need to reset cycle state before calling computeOomAdjLSP because of service conns
for (int i = numProc - 1; i >= 0; i--) {
ProcessRecord app = activeProcesses.get(i);
- app.mReachable = false;
+ final ProcessStateRecord state = app.mState;
+ state.setReachable(false);
// No need to compute again it has been evaluated in previous iteration
- if (app.adjSeq != mAdjSeq) {
- app.containsCycle = false;
- app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
- app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
- app.setCapability = PROCESS_CAPABILITY_NONE;
- app.resetCachedInfo();
+ if (state.getAdjSeq() != mAdjSeq) {
+ state.setContainsCycle(false);
+ state.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
+ state.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+ state.setSetCapability(PROCESS_CAPABILITY_NONE);
+ state.resetCachedInfo();
}
}
for (int i = numProc - 1; i >= 0; i--) {
ProcessRecord app = activeProcesses.get(i);
- if (!app.killedByAm && app.thread != null) {
- app.procStateChanged = false;
- computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
+ final ProcessStateRecord state = app.mState;
+ if (!app.isKilledByAm() && app.getThread() != null) {
+ state.setProcStateChanged(false);
+ computeOomAdjLSP(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
computeClients); // It won't enter cycle if not computing clients.
// if any app encountered a cycle, we need to perform an additional loop later
- retryCycles |= app.containsCycle;
+ retryCycles |= state.containsCycle();
// Keep the completedAdjSeq to up to date.
- app.completedAdjSeq = mAdjSeq;
+ state.setCompletedAdjSeq(mAdjSeq);
}
}
if (mCacheOomRanker.useOomReranking()) {
- mCacheOomRanker.reRankLruCachedApps(mProcessList);
+ mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(),
+ mProcessList.getLruProcessServiceStartLOSP());
}
- assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
+ assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
if (computeClients) { // There won't be cycles if we didn't compute clients above.
// Cycle strategy:
@@ -795,16 +828,18 @@ public final class OomAdjuster {
for (int i = 0; i < numProc; i++) {
ProcessRecord app = activeProcesses.get(i);
- if (!app.killedByAm && app.thread != null && app.containsCycle) {
- app.adjSeq--;
- app.completedAdjSeq--;
+ final ProcessStateRecord state = app.mState;
+ if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
+ state.decAdjSeq();
+ state.decCompletedAdjSeq();
}
}
for (int i = 0; i < numProc; i++) {
ProcessRecord app = activeProcesses.get(i);
- if (!app.killedByAm && app.thread != null && app.containsCycle) {
- if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
+ final ProcessStateRecord state = app.mState;
+ if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
+ if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now,
true, true)) {
retryCycles = true;
}
@@ -816,7 +851,7 @@ public final class OomAdjuster {
mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;
- boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
+ boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids);
mNumServiceProcs = mNewNumServiceProcs;
if (mService.mAlwaysFinishActivities) {
@@ -826,11 +861,11 @@ public final class OomAdjuster {
}
if (allChanged) {
- mService.mAppProfiler.requestPssAllProcsLocked(now, false,
+ mService.mAppProfiler.requestPssAllProcsLPr(now, false,
mService.mProcessStats.isMemFactorLowered());
}
- updateUidsLocked(activeUids, nowElapsed);
+ updateUidsLSP(activeUids, nowElapsed);
synchronized (mService.mProcessStats.mLock) {
if (mService.mProcessStats.shouldWriteNowLocked(now)) {
@@ -857,6 +892,7 @@ public final class OomAdjuster {
}
}
+ @GuardedBy({"mService", "mProcLock"})
private void assignCachedAdjIfNecessary(ArrayList lruList) {
final int numLru = lruList.size();
@@ -900,23 +936,27 @@ public final class OomAdjuster {
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
+ final ProcessStateRecord state = app.mState;
// If we haven't yet assigned the final cached adj
// to the process, do that now.
- if (!app.killedByAm && app.thread != null && app.curAdj
+ if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
>= ProcessList.UNKNOWN_ADJ) {
- switch (app.getCurProcState()) {
+ final ProcessServiceRecord psr = app.mServices;
+ switch (state.getCurProcState()) {
case PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
// Figure out the next cached level, taking into account groups.
boolean inGroup = false;
- if (app.connectionGroup != 0) {
+ final int connectionGroup = psr.getConnectionGroup();
+ if (connectionGroup != 0) {
+ final int connectionImportance = psr.getConnectionImportance();
if (lastCachedGroupUid == app.uid
- && lastCachedGroup == app.connectionGroup) {
+ && lastCachedGroup == connectionGroup) {
// This is in the same group as the last process, just tweak
// adjustment by importance.
- if (app.connectionImportance > lastCachedGroupImportance) {
- lastCachedGroupImportance = app.connectionImportance;
+ if (connectionImportance > lastCachedGroupImportance) {
+ lastCachedGroupImportance = connectionImportance;
if (curCachedAdj < nextCachedAdj
&& curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
curCachedImpAdj++;
@@ -925,8 +965,8 @@ public final class OomAdjuster {
inGroup = true;
} else {
lastCachedGroupUid = app.uid;
- lastCachedGroup = app.connectionGroup;
- lastCachedGroupImportance = app.connectionImportance;
+ lastCachedGroup = connectionGroup;
+ lastCachedGroupImportance = connectionImportance;
}
}
if (!inGroup && curCachedAdj != nextCachedAdj) {
@@ -944,11 +984,12 @@ public final class OomAdjuster {
// This process is a cached process holding activities...
// assign it the next cached value for that type, and then
// step that cached level.
- app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
- app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
+ state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
+ state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
if (DEBUG_LRU) {
Slog.d(TAG_LRU, "Assigning activity LRU #" + i
- + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
+ + " adj: " + state.getCurAdj()
+ + " (curCachedAdj=" + curCachedAdj
+ " curCachedImpAdj=" + curCachedImpAdj + ")");
}
break;
@@ -970,11 +1011,11 @@ public final class OomAdjuster {
// long-running services that have dropped down to the
// cached level will be treated as empty (since their process
// state is still as a service), which is what we want.
- app.setCurRawAdj(curEmptyAdj);
- app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
+ state.setCurRawAdj(curEmptyAdj);
+ state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
if (DEBUG_LRU) {
Slog.d(TAG_LRU, "Assigning empty LRU #" + i
- + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
+ + " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj
+ ")");
}
break;
@@ -983,9 +1024,10 @@ public final class OomAdjuster {
}
}
- private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
final long oldTime, final ActiveUids activeUids) {
- ArrayList lruList = mProcessList.mLruProcesses;
+ ArrayList lruList = mProcessList.getLruProcessesLOSP();
final int numLru = lruList.size();
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
@@ -1000,34 +1042,37 @@ public final class OomAdjuster {
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
- if (!app.killedByAm && app.thread != null) {
+ final ProcessStateRecord state = app.mState;
+ if (!app.isKilledByAm() && app.getThread() != null) {
// We don't need to apply the update for the process which didn't get computed
- if (app.completedAdjSeq == mAdjSeq) {
- applyOomAdjLocked(app, true, now, nowElapsed);
+ if (state.getCompletedAdjSeq() == mAdjSeq) {
+ applyOomAdjLSP(app, true, now, nowElapsed);
}
+ final ProcessServiceRecord psr = app.mServices;
// Count the number of process types.
- switch (app.getCurProcState()) {
+ switch (state.getCurProcState()) {
case PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++;
- if (app.connectionGroup != 0) {
+ final int connectionGroup = psr.getConnectionGroup();
+ if (connectionGroup != 0) {
if (lastCachedGroupUid == app.info.uid
- && lastCachedGroup == app.connectionGroup) {
+ && lastCachedGroup == connectionGroup) {
// If this process is the next in the same group, we don't
// want it to count against our limit of the number of cached
// processes, so bump up the group count to account for it.
numCachedExtraGroup++;
} else {
lastCachedGroupUid = app.info.uid;
- lastCachedGroup = app.connectionGroup;
+ lastCachedGroup = connectionGroup;
}
} else {
lastCachedGroupUid = lastCachedGroup = 0;
}
if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
- app.kill("cached #" + numCached,
+ app.killLocked("cached #" + numCached,
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
true);
@@ -1035,17 +1080,16 @@ public final class OomAdjuster {
break;
case PROCESS_STATE_CACHED_EMPTY:
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
- && app.lastActivityTime < oldTime) {
- app.kill("empty for "
- + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
- / 1000) + "s",
+ && app.getLastActivityTime() < oldTime) {
+ app.killLocked("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME
+ - app.getLastActivityTime()) / 1000) + "s",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
true);
} else {
numEmpty++;
if (numEmpty > emptyProcessLimit) {
- app.kill("empty #" + numEmpty,
+ app.killLocked("empty #" + numEmpty,
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
true);
@@ -1057,8 +1101,8 @@ public final class OomAdjuster {
break;
}
- if (app.isolated && app.numberOfRunningServices() <= 0
- && app.isolatedEntryPoint == null) {
+ if (app.isolated && psr.numberOfRunningServices() <= 0
+ && app.getIsolatedEntryPoint() == null) {
// If this is an isolated process, there are no services
// running in it, and it's not a special process with a
// custom entry point, then the process is no longer
@@ -1066,40 +1110,56 @@ public final class OomAdjuster {
// definition not re-use the same process again, and it is
// good to avoid having whatever code was running in them
// left sitting around after no longer needed.
- app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER,
+ app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
} else {
// Keeping this process, update its uid.
- updateAppUidRecLocked(app);
+ updateAppUidRecLSP(app);
}
- if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedByAm) {
+ if (state.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
+ && !app.isKilledByAm()) {
numTrimming++;
}
}
}
- mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
+ mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
- return mService.mAppProfiler.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
+ return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
}
- private void updateAppUidRecLocked(ProcessRecord app) {
- final UidRecord uidRec = app.uidRecord;
- if (uidRec != null) {
- uidRec.ephemeral = app.info.isInstantApp();
- if (uidRec.getCurProcState() > app.getCurProcState()) {
- uidRec.setCurProcState(app.getCurProcState());
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateAppUidRecIfNecessaryLSP(final ProcessRecord app) {
+ if (!app.isKilledByAm() && app.getThread() != null) {
+ if (app.isolated && app.mServices.numberOfRunningServices() <= 0
+ && app.getIsolatedEntryPoint() == null) {
+ // No op.
+ } else {
+ // Keeping this process, update its uid.
+ updateAppUidRecLSP(app);
}
- if (app.hasForegroundServices()) {
- uidRec.foregroundServices = true;
- }
- uidRec.curCapability |= app.curCapability;
}
}
- private void updateUidsLocked(ActiveUids activeUids, final long nowElapsed) {
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateAppUidRecLSP(ProcessRecord app) {
+ final UidRecord uidRec = app.getUidRecord();
+ if (uidRec != null) {
+ final ProcessStateRecord state = app.mState;
+ uidRec.setEphemeral(app.info.isInstantApp());
+ if (uidRec.getCurProcState() > state.getCurProcState()) {
+ uidRec.setCurProcState(state.getCurProcState());
+ }
+ if (app.mServices.hasForegroundServices()) {
+ uidRec.setForegroundServices(true);
+ }
+ uidRec.setCurCapability(uidRec.getCurCapability() | state.getCurCapability());
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
ArrayList becameIdle = mTmpBecameIdle;
becameIdle.clear();
@@ -1111,22 +1171,22 @@ public final class OomAdjuster {
final UidRecord uidRec = activeUids.valueAt(i);
int uidChange = UidRecord.CHANGE_PROCSTATE;
if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
- && (uidRec.setProcState != uidRec.getCurProcState()
- || uidRec.setCapability != uidRec.curCapability
- || uidRec.mSetAllowlist != uidRec.mCurAllowlist)) {
+ && (uidRec.getSetProcState() != uidRec.getCurProcState()
+ || uidRec.getSetCapability() != uidRec.getCurCapability()
+ || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
- + ": proc state from " + uidRec.setProcState + " to "
+ + ": proc state from " + uidRec.getSetProcState() + " to "
+ uidRec.getCurProcState() + ", capability from "
- + uidRec.setCapability + " to " + uidRec.curCapability
- + ", allowlist from " + uidRec.mSetAllowlist
- + " to " + uidRec.mCurAllowlist);
+ + uidRec.getSetCapability() + " to " + uidRec.getCurCapability()
+ + ", allowlist from " + uidRec.isSetAllowListed()
+ + " to " + uidRec.isCurAllowListed());
if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
- && !uidRec.mCurAllowlist) {
+ && !uidRec.isCurAllowListed()) {
// UID is now in the background (and not on the temp allowlist). Was it
// previously in the foreground (or on the temp allowlist)?
- if (!ActivityManager.isProcStateBackground(uidRec.setProcState)
- || uidRec.mSetAllowlist) {
- uidRec.lastBackgroundTime = nowElapsed;
+ if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
+ || uidRec.isSetAllowListed()) {
+ uidRec.setLastBackgroundTime(nowElapsed);
if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
// Note: the background settle time is in elapsed realtime, while
// the handler time base is uptime. All this means is that we may
@@ -1136,38 +1196,40 @@ public final class OomAdjuster {
mConstants.BACKGROUND_SETTLE_TIME);
}
}
- if (uidRec.idle && !uidRec.setIdle) {
+ if (uidRec.isIdle() && !uidRec.isSetIdle()) {
uidChange = UidRecord.CHANGE_IDLE;
becameIdle.add(uidRec);
}
} else {
- if (uidRec.idle) {
+ if (uidRec.isIdle()) {
uidChange = UidRecord.CHANGE_ACTIVE;
- EventLogTags.writeAmUidActive(uidRec.uid);
- uidRec.idle = false;
+ EventLogTags.writeAmUidActive(uidRec.getUid());
+ uidRec.setIdle(false);
}
- uidRec.lastBackgroundTime = 0;
+ uidRec.setLastBackgroundTime(0);
}
- final boolean wasCached = uidRec.setProcState
+ final boolean wasCached = uidRec.getSetProcState()
> ActivityManager.PROCESS_STATE_RECEIVER;
final boolean isCached = uidRec.getCurProcState()
> ActivityManager.PROCESS_STATE_RECEIVER;
- if (wasCached != isCached || uidRec.setProcState == PROCESS_STATE_NONEXISTENT) {
+ if (wasCached != isCached
+ || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) {
uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
}
- uidRec.setProcState = uidRec.getCurProcState();
- uidRec.setCapability = uidRec.curCapability;
- uidRec.mSetAllowlist = uidRec.mCurAllowlist;
- uidRec.setIdle = uidRec.idle;
- mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState);
+ uidRec.setSetProcState(uidRec.getCurProcState());
+ uidRec.setSetCapability(uidRec.getCurCapability());
+ uidRec.setSetAllowListed(uidRec.isCurAllowListed());
+ uidRec.setSetIdle(uidRec.isIdle());
+ mService.mAtmInternal.onUidProcStateChanged(
+ uidRec.getUid(), uidRec.getSetProcState());
mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
- mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(),
- uidRec.curCapability);
- if (uidRec.foregroundServices) {
+ mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(),
+ uidRec.getCurCapability());
+ if (uidRec.hasForegroundServices()) {
mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
}
- mService.mInternal.deletePendingTopUid(uidRec.uid);
+ mService.mInternal.deletePendingTopUid(uidRec.getUid());
}
if (mLocalPowerManager != null) {
mLocalPowerManager.finishUidChanges();
@@ -1178,7 +1240,7 @@ public final class OomAdjuster {
// If we have any new uids that became idle this time, we need to make sure
// they aren't left with running services.
for (int i = size - 1; i >= 0; i--) {
- mService.mServices.stopInBackgroundLocked(becameIdle.get(i).uid);
+ mService.mServices.stopInBackgroundLocked(becameIdle.get(i).getUid());
}
}
}
@@ -1186,7 +1248,7 @@ public final class OomAdjuster {
private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
new ComputeOomAdjWindowCallback();
- /** These methods are called inline during computeOomAdjLocked(), on the same thread */
+ /** These methods are called inline during computeOomAdjLSP(), on the same thread */
final class ComputeOomAdjWindowCallback
implements WindowProcessController.ComputeOomAdjCallback {
@@ -1198,6 +1260,7 @@ public final class OomAdjuster {
int appUid;
int logUid;
int processStateCurTop;
+ ProcessStateRecord mState;
void initialize(ProcessRecord app, int adj, boolean foregroundActivities,
int procState, int schedGroup, int appUid, int logUid, int processStateCurTop) {
@@ -1209,6 +1272,7 @@ public final class OomAdjuster {
this.appUid = appUid;
this.logUid = logUid;
this.processStateCurTop = processStateCurTop;
+ this.mState = app.mState;
}
@Override
@@ -1216,14 +1280,14 @@ public final class OomAdjuster {
// App has a visible activity; only upgrade adjustment.
if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
- app.adjType = "vis-activity";
+ mState.setAdjType("vis-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app);
}
}
if (procState > processStateCurTop) {
procState = processStateCurTop;
- app.adjType = "vis-activity";
+ mState.setAdjType("vis-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to vis-activity (top): " + app);
@@ -1232,8 +1296,8 @@ public final class OomAdjuster {
if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
- app.setCached(false);
- app.empty = false;
+ mState.setCached(false);
+ mState.setEmpty(false);
foregroundActivities = true;
}
@@ -1241,14 +1305,14 @@ public final class OomAdjuster {
public void onPausedActivity() {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "pause-activity";
+ mState.setAdjType("pause-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: " + app);
}
}
if (procState > processStateCurTop) {
procState = processStateCurTop;
- app.adjType = "pause-activity";
+ mState.setAdjType("pause-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to pause-activity (top): " + app);
@@ -1257,8 +1321,8 @@ public final class OomAdjuster {
if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
- app.setCached(false);
- app.empty = false;
+ mState.setCached(false);
+ mState.setEmpty(false);
foregroundActivities = true;
}
@@ -1266,7 +1330,7 @@ public final class OomAdjuster {
public void onStoppingActivity(boolean finishing) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "stop-activity";
+ mState.setAdjType("stop-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to stop-activity: " + app);
@@ -1282,15 +1346,15 @@ public final class OomAdjuster {
if (!finishing) {
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
- app.adjType = "stop-activity";
+ mState.setAdjType("stop-activity");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to stop-activity: " + app);
}
}
}
- app.setCached(false);
- app.empty = false;
+ mState.setCached(false);
+ mState.setEmpty(false);
foregroundActivities = true;
}
@@ -1298,7 +1362,7 @@ public final class OomAdjuster {
public void onOtherActivity() {
if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
procState = PROCESS_STATE_CACHED_ACTIVITY;
- app.adjType = "cch-act";
+ mState.setAdjType("cch-act");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to cached activity: " + app);
@@ -1307,99 +1371,102 @@ public final class OomAdjuster {
}
}
- private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
- if (mAdjSeq == app.adjSeq) {
- if (app.adjSeq == app.completedAdjSeq) {
+ final ProcessStateRecord state = app.mState;
+ if (mAdjSeq == state.getAdjSeq()) {
+ if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
// This adjustment has already been computed successfully.
return false;
} else {
// The process is being computed, so there is a cycle. We cannot
// rely on this process's state.
- app.containsCycle = true;
+ state.setContainsCycle(true);
return false;
}
}
- if (app.thread == null) {
- app.adjSeq = mAdjSeq;
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
- app.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
- app.curAdj = ProcessList.CACHED_APP_MAX_ADJ;
- app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
- app.completedAdjSeq = app.adjSeq;
- app.curCapability = PROCESS_CAPABILITY_NONE;
+ if (app.getThread() == null) {
+ state.setAdjSeq(mAdjSeq);
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
+ state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
+ state.setCurAdj(ProcessList.CACHED_APP_MAX_ADJ);
+ state.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
+ state.setCompletedAdjSeq(state.getAdjSeq());
+ state.setCurCapability(PROCESS_CAPABILITY_NONE);
return false;
}
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
- app.adjSource = null;
- app.adjTarget = null;
- app.empty = false;
- app.setCached(false);
- app.shouldNotFreeze = false;
-
- app.resetAllowStartFgs();
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
+ state.setAdjSource(null);
+ state.setAdjTarget(null);
+ state.setEmpty(false);
+ state.setCached(false);
+ state.setAllowStartFgsState(PROCESS_STATE_NONEXISTENT);
+ state.resetAllowStartFgs();
+ app.mOptRecord.setShouldNotFreeze(false);
final int appUid = app.info.uid;
final int logUid = mService.mCurOomAdjUid;
- int prevAppAdj = app.curAdj;
- int prevProcState = app.getCurProcState();
- int prevCapability = app.curCapability;
+ int prevAppAdj = state.getCurAdj();
+ int prevProcState = state.getCurProcState();
+ int prevCapability = state.getCurCapability();
+ final ProcessServiceRecord psr = app.mServices;
- if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ if (state.getMaxAdj() <= ProcessList.FOREGROUND_APP_ADJ) {
// The max adjustment doesn't allow this app to be anything
// below foreground, so it is not worth doing work for it.
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
}
- app.adjType = "fixed";
- app.adjSeq = mAdjSeq;
- app.setCurRawAdj(app.maxAdj);
- app.setHasForegroundActivities(false);
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
- app.curCapability = PROCESS_CAPABILITY_ALL;
- app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
+ state.setAdjType("fixed");
+ state.setAdjSeq(mAdjSeq);
+ state.setCurRawAdj(state.getMaxAdj());
+ state.setHasForegroundActivities(false);
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
+ state.setCurCapability(PROCESS_CAPABILITY_ALL);
+ state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
// System processes can do UI, and when they do we want to have
// them trim their memory after the user leaves the UI. To
// facilitate this, here we need to determine whether or not it
// is currently showing UI.
- app.systemNoUi = true;
+ state.setSystemNoUi(true);
if (app == topApp) {
- app.systemNoUi = false;
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
- app.adjType = "pers-top-activity";
- } else if (app.hasTopUi()) {
+ state.setSystemNoUi(false);
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
+ state.setAdjType("pers-top-activity");
+ } else if (state.hasTopUi()) {
// sched group/proc state adjustment is below
- app.systemNoUi = false;
- app.adjType = "pers-top-ui";
- } else if (app.getCachedHasVisibleActivities()) {
- app.systemNoUi = false;
+ state.setSystemNoUi(false);
+ state.setAdjType("pers-top-ui");
+ } else if (state.getCachedHasVisibleActivities()) {
+ state.setSystemNoUi(false);
}
- if (!app.systemNoUi) {
+ if (!state.isSystemNoUi()) {
if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE) {
// screen on, promote UI
- app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
+ state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
} else {
// screen off, restrict UI scheduling
- app.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
+ state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
}
}
- app.setCurRawProcState(app.getCurProcState());
- app.curAdj = app.maxAdj;
- app.completedAdjSeq = app.adjSeq;
- app.bumpAllowStartFgsState(app.getCurProcState());
- app.setAllowStartFgs();
+ state.setCurRawProcState(state.getCurProcState());
+ state.setCurAdj(state.getMaxAdj());
+ state.setCompletedAdjSeq(state.getAdjSeq());
+ state.bumpAllowStartFgsState(state.getCurProcState());
+ state.setAllowStartFgs();
// if curAdj is less than prevAppAdj, then this process was promoted
- return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
+ return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
}
- app.systemNoUi = false;
+ state.setSystemNoUi(false);
final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState();
@@ -1416,17 +1483,17 @@ public final class OomAdjuster {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
- app.adjType = "top-activity";
+ state.setAdjType("top-activity");
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
- app.bumpAllowStartFgsState(PROCESS_STATE_TOP);
+ state.bumpAllowStartFgsState(PROCESS_STATE_TOP);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
}
- } else if (app.runningRemoteAnimation) {
+ } else if (state.isRunningRemoteAnimation()) {
adj = ProcessList.VISIBLE_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
- app.adjType = "running-remote-anim";
+ state.setAdjType("running-remote-anim");
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
@@ -1435,12 +1502,12 @@ public final class OomAdjuster {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
- app.adjType = "instrumentation";
+ state.setAdjType("instrumentation");
procState = PROCESS_STATE_FOREGROUND_SERVICE;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
}
- } else if (app.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
+ } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
@@ -1448,27 +1515,26 @@ public final class OomAdjuster {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
- app.adjType = "broadcast";
+ state.setAdjType("broadcast");
procState = ActivityManager.PROCESS_STATE_RECEIVER;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
}
- } else if (app.executingServices.size() > 0) {
+ } else if (psr.numberOfExecutingServices() > 0) {
// An app that is currently executing a service callback also
// counts as being in the foreground.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = app.execServicesFg ?
- ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
- app.adjType = "exec-service";
+ schedGroup = psr.shouldExecServicesFg()
+ ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
+ state.setAdjType("exec-service");
procState = PROCESS_STATE_SERVICE;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
}
- //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
} else if (app == topApp) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- app.adjType = "top-sleeping";
+ state.setAdjType("top-sleeping");
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
@@ -1481,10 +1547,10 @@ public final class OomAdjuster {
// value that the caller wants us to.
adj = cachedAdj;
procState = PROCESS_STATE_CACHED_EMPTY;
- if (!app.containsCycle) {
- app.setCached(true);
- app.empty = true;
- app.adjType = "cch-empty";
+ if (!state.containsCycle()) {
+ state.setCached(true);
+ state.setEmpty(true);
+ state.setAdjType("cch-empty");
}
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
@@ -1492,20 +1558,20 @@ public final class OomAdjuster {
}
// Examine all activities if not already foreground.
- if (!foregroundActivities && app.getCachedHasActivities()) {
- app.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
+ if (!foregroundActivities && state.getCachedHasActivities()) {
+ state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
adj, foregroundActivities, procState, schedGroup, appUid, logUid,
PROCESS_STATE_CUR_TOP);
- adj = app.mCachedAdj;
- foregroundActivities = app.mCachedForegroundActivities;
- procState = app.mCachedProcState;
- schedGroup = app.mCachedSchedGroup;
+ adj = state.getCachedAdj();
+ foregroundActivities = state.getCachedForegroundActivities();
+ procState = state.getCachedProcState();
+ schedGroup = state.getCachedSchedGroup();
}
- if (procState > PROCESS_STATE_CACHED_RECENT && app.getCachedHasRecentTasks()) {
+ if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
procState = PROCESS_STATE_CACHED_RECENT;
- app.adjType = "cch-rec";
+ state.setAdjType("cch-rec");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
}
@@ -1513,24 +1579,24 @@ public final class OomAdjuster {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_FOREGROUND_SERVICE) {
- if (app.hasForegroundServices()) {
+ if (psr.hasForegroundServices()) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_FOREGROUND_SERVICE;
- app.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE);
- app.adjType = "fg-service";
- app.setCached(false);
+ state.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE);
+ state.setAdjType("fg-service");
+ state.setCached(false);
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + app.adjType + ": "
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + state.getAdjType() + ": "
+ app + " ");
}
- } else if (app.hasOverlayUi()) {
+ } else if (state.hasOverlayUi()) {
// The process is display an overlay UI.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
- app.setCached(false);
- app.adjType = "has-overlay-ui";
+ state.setCached(false);
+ state.setAdjType("has-overlay-ui");
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
@@ -1541,11 +1607,11 @@ public final class OomAdjuster {
// If the app was recently in the foreground and moved to a foreground service status,
// allow it to get a higher rank in memory for some time, compared to other foreground
// services so that it can finish performing any persistence/processing of in-memory state.
- if (app.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
- && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
- || app.setProcState <= PROCESS_STATE_TOP)) {
+ if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
+ && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now
+ || state.getSetProcState() <= PROCESS_STATE_TOP)) {
adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
- app.adjType = "fg-service-act";
+ state.setAdjType("fg-service-act");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
}
@@ -1553,15 +1619,15 @@ public final class OomAdjuster {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
- if (app.forcingToImportant != null) {
+ if (state.getForcingToImportant() != null) {
// This is currently used for toasts... they are not interactive, and
// we don't want them to cause the app to become fully foreground (and
// thus out of background check), so we yes the best background level we can.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
- app.setCached(false);
- app.adjType = "force-imp";
- app.adjSource = app.forcingToImportant;
+ state.setCached(false);
+ state.setAdjType("force-imp");
+ state.setAdjSource(state.getForcingToImportant());
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
@@ -1569,63 +1635,63 @@ public final class OomAdjuster {
}
}
- if (app.getCachedIsHeavyWeight()) {
+ if (state.getCachedIsHeavyWeight()) {
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- app.setCached(false);
- app.adjType = "heavy";
+ state.setCached(false);
+ state.setAdjType("heavy");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
- app.adjType = "heavy";
+ state.setAdjType("heavy");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
}
}
}
- if (app.getCachedIsHomeProcess()) {
+ if (state.getCachedIsHomeProcess()) {
if (adj > ProcessList.HOME_APP_ADJ) {
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- app.setCached(false);
- app.adjType = "home";
+ state.setCached(false);
+ state.setAdjType("home");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
}
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
- app.adjType = "home";
+ state.setAdjType("home");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
}
}
}
- if (app.getCachedIsPreviousProcess() && app.getCachedHasActivities()) {
+ if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
// This was the previous process that showed UI to the user.
// We want to try to keep it around more aggressively, to give
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- app.setCached(false);
- app.adjType = "previous";
+ state.setCached(false);
+ state.setAdjType("previous");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
}
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
- app.adjType = "previous";
+ state.setAdjType("previous");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
}
@@ -1633,7 +1699,7 @@ public final class OomAdjuster {
}
if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
- + " reason=" + app.adjType);
+ + " reason=" + state.getAdjType());
// By default, we use the computed adjustment. It may be changed if
// there are applications dependent on our services or providers, but
@@ -1641,15 +1707,15 @@ public final class OomAdjuster {
// infinite recursion. If we're re-evaluating due to cycles, use the previously computed
// values.
if (cycleReEval) {
- procState = Math.min(procState, app.getCurRawProcState());
- adj = Math.min(adj, app.getCurRawAdj());
- schedGroup = Math.max(schedGroup, app.getCurrentSchedulingGroup());
+ procState = Math.min(procState, state.getCurRawProcState());
+ adj = Math.min(adj, state.getCurRawAdj());
+ schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup());
}
- app.setCurRawAdj(adj);
- app.setCurRawProcState(procState);
+ state.setCurRawAdj(adj);
+ state.setCurRawProcState(procState);
- app.hasStartedServices = false;
- app.adjSeq = mAdjSeq;
+ state.setHasStartedServices(false);
+ state.setAdjSeq(mAdjSeq);
final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
if (backupTarget != null && app == backupTarget.app) {
@@ -1660,15 +1726,15 @@ public final class OomAdjuster {
if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
}
- app.adjType = "backup";
+ state.setAdjType("backup");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
}
- app.setCached(false);
+ state.setCached(false);
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
- app.adjType = "backup";
+ state.setAdjType("backup");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
}
@@ -1676,29 +1742,29 @@ public final class OomAdjuster {
}
int capabilityFromFGS = 0; // capability from foreground service.
- for (int is = app.numberOfRunningServices() - 1;
+ for (int is = psr.numberOfRunningServices() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
is--) {
- ServiceRecord s = app.getRunningServiceAt(is);
+ ServiceRecord s = psr.getRunningServiceAt(is);
if (s.startRequested) {
- app.hasStartedServices = true;
+ state.setHasStartedServices(true);
if (procState > PROCESS_STATE_SERVICE) {
procState = PROCESS_STATE_SERVICE;
- app.adjType = "started-services";
+ state.setAdjType("started-services");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to started service: " + app);
}
}
- if (!s.mKeepWarming && app.hasShownUi && !app.getCachedIsHomeProcess()) {
+ if (!s.mKeepWarming && state.hasShownUi() && !state.getCachedIsHomeProcess()) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > ProcessList.SERVICE_ADJ) {
- app.adjType = "cch-started-ui-services";
+ state.setAdjType("cch-started-ui-services");
}
} else {
if (s.mKeepWarming
@@ -1708,19 +1774,19 @@ public final class OomAdjuster {
// of the background processes.
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
- app.adjType = "started-services";
+ state.setAdjType("started-services");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to started service: " + app);
}
- app.setCached(false);
+ state.setCached(false);
}
}
// If we have let the service slide into the background
// state, still have some text describing what it is doing
// even though the service no longer has an impact.
if (adj > ProcessList.SERVICE_ADJ) {
- app.adjType = "cch-started-services";
+ state.setAdjType("cch-started-services");
}
}
}
@@ -1775,30 +1841,31 @@ public final class OomAdjuster {
boolean trackedProcState = false;
ProcessRecord client = cr.binding.client;
+ final ProcessStateRecord cstate = client.mState;
if (computeClients) {
- computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now,
+ computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
cycleReEval, true);
} else {
- client.setCurRawAdj(client.setAdj);
- client.setCurRawProcState(client.setProcState);
+ cstate.setCurRawAdj(cstate.getSetAdj());
+ cstate.setCurRawProcState(cstate.getSetProcState());
}
- int clientAdj = client.getCurRawAdj();
- int clientProcState = client.getCurRawProcState();
+ int clientAdj = cstate.getCurRawAdj();
+ int clientProcState = cstate.getCurRawProcState();
// pass client's mAllowStartFgs to the app if client is not persistent process.
- if (client.mAllowStartFgs != FGS_FEATURE_DENIED
- && client.maxAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- app.mAllowStartFgs = client.mAllowStartFgs;
+ if (cstate.getAllowedStartFgs() != FGS_FEATURE_DENIED
+ && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) {
+ state.setAllowStartFgs(cstate.getAllowedStartFgs());
}
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
- if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
+ if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
continue;
}
if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
- capability |= client.curCapability;
+ capability |= cstate.getCurCapability();
}
if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
@@ -1811,7 +1878,7 @@ public final class OomAdjuster {
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
// this guy more like a started service.
- if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
// If this process has shown some UI, let it immediately
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
@@ -1819,7 +1886,7 @@ public final class OomAdjuster {
if (adj > clientAdj) {
adjType = "cch-bound-ui-services";
}
- app.setCached(false);
+ state.setCached(false);
clientAdj = adj;
clientProcState = procState;
} else {
@@ -1845,7 +1912,7 @@ public final class OomAdjuster {
// about letting this process get into the LRU
// list to be killed and restarted if needed for
// memory.
- if (app.hasShownUi && !app.getCachedIsHomeProcess()
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
adjType = "cch-bound-ui-services";
@@ -1882,12 +1949,12 @@ public final class OomAdjuster {
newAdj = adj;
}
}
- if (!client.isCached()) {
- app.setCached(false);
+ if (!cstate.isCached()) {
+ state.setCached(false);
}
if (adj > newAdj) {
adj = newAdj;
- app.setCurRawAdj(adj);
+ state.setCurRawAdj(adj);
adjType = "service";
}
}
@@ -1897,7 +1964,7 @@ public final class OomAdjuster {
// This will treat important bound services identically to
// the top app, which may behave differently than generic
// foreground work.
- final int curSchedGroup = client.getCurrentSchedulingGroup();
+ final int curSchedGroup = cstate.getCurrentSchedulingGroup();
if (curSchedGroup > schedGroup) {
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = curSchedGroup;
@@ -1912,7 +1979,7 @@ public final class OomAdjuster {
// give them the best bound state after that.
if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- app.bumpAllowStartFgsState(
+ state.bumpAllowStartFgsState(
PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
} else if (mService.mWakefulness.get()
== PowerManagerInternal.WAKEFULNESS_AWAKE
@@ -1927,7 +1994,7 @@ public final class OomAdjuster {
// Go at most to BOUND_TOP, unless requested to elevate
// to client's state.
clientProcState = PROCESS_STATE_BOUND_TOP;
- app.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP);
+ state.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP);
boolean enabled = false;
try {
enabled = mPlatformCompatCache.isChangeEnabled(
@@ -1971,7 +2038,7 @@ public final class OomAdjuster {
if (procState > clientProcState) {
procState = clientProcState;
- app.setCurRawProcState(procState);
+ state.setCurRawProcState(procState);
if (adjType == null) {
adjType = "service";
}
@@ -1981,12 +2048,12 @@ public final class OomAdjuster {
app.setPendingUiClean(true);
}
if (adjType != null) {
- app.adjType = adjType;
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE;
- app.adjSource = cr.binding.client;
- app.adjSourceProcState = clientProcState;
- app.adjTarget = s.instanceName;
+ state.setAdjType(adjType);
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE);
+ state.setAdjSource(cr.binding.client);
+ state.setAdjSourceProcState(clientProcState);
+ state.setAdjTarget(s.instanceName);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + cr.binding.client
@@ -2005,18 +2072,18 @@ public final class OomAdjuster {
// bound by an unfrozen app via a WPRI binding has to remain
// unfrozen.
if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
- app.shouldNotFreeze = true;
+ app.mOptRecord.setShouldNotFreeze(true);
}
}
if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
- app.treatLikeActivity = true;
+ psr.setTreatLikeActivity(true);
}
final ActivityServiceConnectionsHolder a = cr.activity;
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
&& a.isActivityVisible()) {
adj = ProcessList.FOREGROUND_APP_ADJ;
- app.setCurRawAdj(adj);
+ state.setCurRawAdj(adj);
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
@@ -2024,13 +2091,13 @@ public final class OomAdjuster {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
- app.setCached(false);
- app.adjType = "service";
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE;
- app.adjSource = a;
- app.adjSourceProcState = procState;
- app.adjTarget = s.instanceName;
+ state.setCached(false);
+ state.setAdjType("service");
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE);
+ state.setAdjSource(a);
+ state.setAdjSourceProcState(procState);
+ state.setAdjTarget(s.instanceName);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise to service w/activity: " + app);
@@ -2041,12 +2108,13 @@ public final class OomAdjuster {
}
}
- for (int provi = app.pubProviders.size() - 1;
+ final ProcessProviderRecord ppr = app.mProviders;
+ for (int provi = ppr.numberOfProviders() - 1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
provi--) {
- ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
+ ContentProviderRecord cpr = ppr.getProviderAt(provi);
for (int i = cpr.connections.size() - 1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
@@ -2054,24 +2122,24 @@ public final class OomAdjuster {
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
+ final ProcessStateRecord cstate = client.mState;
if (client == app) {
// Being our own client is not interesting.
continue;
}
if (computeClients) {
- computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now, cycleReEval,
- true);
+ computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
} else {
- client.setCurRawAdj(client.setAdj);
- client.setCurRawProcState(client.setProcState);
+ cstate.setCurRawAdj(cstate.getSetAdj());
+ cstate.setCurRawProcState(cstate.getSetProcState());
}
- if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
+ if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
continue;
}
- int clientAdj = client.getCurRawAdj();
- int clientProcState = client.getCurRawProcState();
+ int clientAdj = cstate.getCurRawAdj();
+ int clientProcState = cstate.getCurRawProcState();
if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
// If the other app is cached for any reason, for purposes here
@@ -2080,16 +2148,16 @@ public final class OomAdjuster {
}
String adjType = null;
if (adj > clientAdj) {
- if (app.hasShownUi && !app.getCachedIsHomeProcess()
+ if (state.hasShownUi() && !state.getCachedIsHomeProcess()
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adjType = "cch-ui-provider";
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
- app.setCurRawAdj(adj);
+ state.setCurRawAdj(adj);
adjType = "provider";
}
- app.setCached(app.isCached() & client.isCached());
+ state.setCached(state.isCached() & cstate.isCached());
}
if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -2106,18 +2174,18 @@ public final class OomAdjuster {
conn.trackProcState(clientProcState, mAdjSeq, now);
if (procState > clientProcState) {
procState = clientProcState;
- app.setCurRawProcState(procState);
+ state.setCurRawProcState(procState);
}
- if (client.getCurrentSchedulingGroup() > schedGroup) {
+ if (cstate.getCurrentSchedulingGroup() > schedGroup) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
if (adjType != null) {
- app.adjType = adjType;
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_PROVIDER_IN_USE;
- app.adjSource = client;
- app.adjSourceProcState = clientProcState;
- app.adjTarget = cpr.name;
+ state.setAdjType(adjType);
+ state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE);
+ state.setAdjSource(client);
+ state.setAdjSourceProcState(clientProcState);
+ state.setAdjTarget(cpr.name);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + client
@@ -2132,11 +2200,11 @@ public final class OomAdjuster {
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
- app.setCurRawAdj(adj);
+ state.setCurRawAdj(adj);
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
- app.setCached(false);
- app.adjType = "ext-provider";
- app.adjTarget = cpr.name;
+ state.setCached(false);
+ state.setAdjType("ext-provider");
+ state.setAdjTarget(cpr.name);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to external provider: " + app);
@@ -2144,7 +2212,7 @@ public final class OomAdjuster {
}
if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
- app.setCurRawProcState(procState);
+ state.setCurRawProcState(procState);
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to external provider: " + app);
@@ -2153,13 +2221,13 @@ public final class OomAdjuster {
}
}
- if (app.lastProviderTime > 0 &&
- (app.lastProviderTime + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
+ if (ppr.getLastProviderTime() > 0
+ && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- app.setCached(false);
- app.adjType = "recent-provider";
+ state.setCached(false);
+ state.setAdjType("recent-provider");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise adj to recent provider: " + app);
@@ -2167,7 +2235,7 @@ public final class OomAdjuster {
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
- app.adjType = "recent-provider";
+ state.setAdjType("recent-provider");
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise procstate to recent provider: " + app);
@@ -2176,24 +2244,23 @@ public final class OomAdjuster {
}
if (procState >= PROCESS_STATE_CACHED_EMPTY) {
- if (app.hasClientActivities()) {
+ if (psr.hasClientActivities()) {
// This is a cached process, but with client activities. Mark it so.
procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
- app.adjType = "cch-client-act";
- } else if (app.treatLikeActivity) {
+ state.setAdjType("cch-client-act");
+ } else if (psr.isTreatedLikeActivity()) {
// This is a cached process, but somebody wants us to treat it like it has
// an activity, okay!
procState = PROCESS_STATE_CACHED_ACTIVITY;
- app.adjType = "cch-as-act";
+ state.setAdjType("cch-as-act");
}
}
if (adj == ProcessList.SERVICE_ADJ) {
if (doingAll && !cycleReEval) {
- app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
+ state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3));
mNewNumServiceProcs++;
- //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
- if (!app.serviceb) {
+ if (!state.isServiceB()) {
// This service isn't far enough down on the LRU list to
// normally be a B service, but if we are low on RAM and it
// is large we want to force it down since we would prefer to
@@ -2201,29 +2268,27 @@ public final class OomAdjuster {
if (!mService.mAppProfiler.isLastMemoryLevelNormal()
&& app.mProfile.getLastPss()
>= mProcessList.getCachedRestoreThresholdKb()) {
- app.serviceHighRam = true;
- app.serviceb = true;
+ state.setServiceHighRam(true);
+ state.setServiceB(true);
//Slog.i(TAG, "ADJ " + app + " high ram!");
} else {
mNewNumAServiceProcs++;
//Slog.i(TAG, "ADJ " + app + " not high ram!");
}
} else {
- app.serviceHighRam = false;
+ state.setServiceHighRam(false);
}
}
- if (app.serviceb) {
+ if (state.isServiceB()) {
adj = ProcessList.SERVICE_B_ADJ;
}
}
- app.setCurRawAdj(adj);
+ state.setCurRawAdj(adj);
- //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
- // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
- if (adj > app.maxAdj) {
- adj = app.maxAdj;
- if (app.maxAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ if (adj > state.getMaxAdj()) {
+ adj = state.getMaxAdj();
+ if (adj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
@@ -2238,31 +2303,32 @@ public final class OomAdjuster {
}
// apply capability from FGS.
- if (app.hasForegroundServices()) {
+ if (psr.hasForegroundServices()) {
capability |= capabilityFromFGS;
}
- capability |= getDefaultCapability(app, procState);
+ capability |= getDefaultCapability(psr, procState);
// Do final modification to adj. Everything we do between here and applying
// the final setAdj must be done in this function, because we will also use
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
- app.curAdj = app.modifyRawOomAdj(adj);
- app.curCapability = capability;
- app.setCurrentSchedulingGroup(schedGroup);
- app.setCurProcState(procState);
- app.setCurRawProcState(procState);
- app.setHasForegroundActivities(foregroundActivities);
- app.completedAdjSeq = mAdjSeq;
- app.setAllowStartFgs();
+ state.setCurAdj(psr.modifyRawOomAdj(adj));
+ state.setCurCapability(capability);
+ state.setCurrentSchedulingGroup(schedGroup);
+ state.setCurProcState(procState);
+ state.setCurRawProcState(procState);
+ state.setHasForegroundActivities(foregroundActivities);
+ state.setCompletedAdjSeq(mAdjSeq);
+ state.setAllowStartFgs();
+
// if curAdj or curProcState improved, then this process was promoted
- return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState
- || app.curCapability != prevCapability ;
+ return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
+ || state.getCurCapability() != prevCapability;
}
- private int getDefaultCapability(ProcessRecord app, int procState) {
+ private int getDefaultCapability(ProcessServiceRecord psr, int procState) {
switch (procState) {
case PROCESS_STATE_PERSISTENT:
case PROCESS_STATE_PERSISTENT_UI:
@@ -2271,7 +2337,7 @@ public final class OomAdjuster {
case PROCESS_STATE_BOUND_TOP:
return PROCESS_CAPABILITY_NONE;
case PROCESS_STATE_FOREGROUND_SERVICE:
- if (app.hasForegroundServices()) {
+ if (psr.hasForegroundServices()) {
// Capability from FGS are conditional depending on foreground service type in
// manifest file and the mAllowWhileInUsePermissionInFgs flag.
return PROCESS_CAPABILITY_NONE;
@@ -2299,16 +2365,16 @@ public final class OomAdjuster {
* evaluation.
* @return whether to skip using the client connection at this time
*/
- private boolean shouldSkipDueToCycle(ProcessRecord app, ProcessRecord client,
+ private boolean shouldSkipDueToCycle(ProcessStateRecord app, ProcessStateRecord client,
int procState, int adj, boolean cycleReEval) {
- if (client.containsCycle) {
- // We've detected a cycle. We should retry computeOomAdjLocked later in
+ if (client.containsCycle()) {
+ // We've detected a cycle. We should retry computeOomAdjLSP later in
// case a later-checked connection from a client would raise its
// priority legitimately.
- app.containsCycle = true;
+ app.setContainsCycle(true);
// If the client has not been completely evaluated, check if it's worth
// using the partial values.
- if (client.completedAdjSeq < mAdjSeq) {
+ if (client.getCompletedAdjSeq() < mAdjSeq) {
if (cycleReEval) {
// If the partial values are no better, skip until the next
// attempt
@@ -2327,7 +2393,8 @@ public final class OomAdjuster {
}
/** Inform the oomadj observer of changes to oomadj. Used by tests. */
- void reportOomAdjMessageLocked(String tag, String msg) {
+ @GuardedBy("mService")
+ private void reportOomAdjMessageLocked(String tag, String msg) {
Slog.d(tag, msg);
synchronized (mService.mOomAdjObserverLock) {
if (mService.mCurOomAdjObserver != null) {
@@ -2338,13 +2405,14 @@ public final class OomAdjuster {
}
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
- @GuardedBy("mService")
- private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
boolean success = true;
+ final ProcessStateRecord state = app.mState;
- if (app.getCurRawAdj() != app.setRawAdj) {
- app.setRawAdj = app.getCurRawAdj();
+ if (state.getCurRawAdj() != state.getSetRawAdj()) {
+ state.setSetRawAdj(state.getCurRawAdj());
}
int changes = 0;
@@ -2352,22 +2420,22 @@ public final class OomAdjuster {
// don't compact during bootup
if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {
// Cached and prev/home compaction
- if (app.curAdj != app.setAdj) {
+ if (state.getCurAdj() != state.getSetAdj()) {
// Perform a minor compaction when a perceptible app becomes the prev/home app
// Perform a major compaction when any app enters cached
// reminder: here, setAdj is previous state, curAdj is upcoming state
- if (app.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ &&
- (app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||
- app.curAdj == ProcessList.HOME_APP_ADJ)) {
+ if (state.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ
+ && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ
+ || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) {
mCachedAppOptimizer.compactAppSome(app);
- } else if ((app.setAdj < ProcessList.CACHED_APP_MIN_ADJ
- || app.setAdj > ProcessList.CACHED_APP_MAX_ADJ)
- && app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
- && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
+ } else if ((state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ
+ || state.getSetAdj() > ProcessList.CACHED_APP_MAX_ADJ)
+ && state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
+ && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) {
mCachedAppOptimizer.compactAppFull(app);
}
} else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
- && app.setAdj < ProcessList.FOREGROUND_APP_ADJ
+ && state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ
// Because these can fire independent of oom_adj/procstate changes, we need
// to throttle the actual dispatch of these requests in addition to the
// processing of the requests. As a result, there is throttling both here
@@ -2375,36 +2443,36 @@ public final class OomAdjuster {
&& mCachedAppOptimizer.shouldCompactPersistent(app, now)) {
mCachedAppOptimizer.compactAppPersistent(app);
} else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
- && app.getCurProcState()
+ && state.getCurProcState()
== ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
&& mCachedAppOptimizer.shouldCompactBFGS(app, now)) {
mCachedAppOptimizer.compactAppBfgs(app);
}
}
- if (app.curAdj != app.setAdj) {
- ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
+ if (state.getCurAdj() != state.getSetAdj()) {
+ ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
- String msg = "Set " + app.pid + " " + app.processName + " adj "
- + app.curAdj + ": " + app.adjType;
+ String msg = "Set " + app.getPid() + " " + app.processName + " adj "
+ + state.getCurAdj() + ": " + state.getAdjType();
reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
}
- app.setAdj = app.curAdj;
- app.verifiedAdj = ProcessList.INVALID_ADJ;
+ state.setSetAdj(state.getCurAdj());
+ state.setVerifiedAdj(ProcessList.INVALID_ADJ);
}
- final int curSchedGroup = app.getCurrentSchedulingGroup();
- if (app.setSchedGroup != curSchedGroup) {
- int oldSchedGroup = app.setSchedGroup;
- app.setSchedGroup = curSchedGroup;
+ final int curSchedGroup = state.getCurrentSchedulingGroup();
+ if (state.getSetSchedGroup() != curSchedGroup) {
+ int oldSchedGroup = state.getSetSchedGroup();
+ state.setSetSchedGroup(curSchedGroup);
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
String msg = "Setting sched group of " + app.processName
- + " to " + curSchedGroup + ": " + app.adjType;
+ + " to " + curSchedGroup + ": " + state.getAdjType();
reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
}
- if (app.waitingToKill != null && app.curReceivers.isEmpty()
- && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
- app.kill(app.waitingToKill, ApplicationExitInfo.REASON_USER_REQUESTED,
+ if (app.getWaitingToKill() != null && app.mReceivers.numberOfCurReceivers() == 0
+ && state.getSetSchedGroup() == ProcessList.SCHED_GROUP_BACKGROUND) {
+ app.killLocked(app.getWaitingToKill(), ApplicationExitInfo.REASON_USER_REQUESTED,
ApplicationExitInfo.SUBREASON_UNKNOWN, true);
success = false;
} else {
@@ -2425,22 +2493,23 @@ public final class OomAdjuster {
break;
}
mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
- 0 /* unused */, app.pid, processGroup, app.processName));
+ 0 /* unused */, app.getPid(), processGroup, app.processName));
try {
+ final int renderThreadTid = app.getRenderThreadTid();
if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
// do nothing if we already switched to RT
if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
app.getWindowProcessController().onTopProcChanged();
if (mService.mUseFifoUiScheduling) {
// Switch UI pipeline for app to SCHED_FIFO
- app.savedPriority = Process.getThreadPriority(app.pid);
- mService.scheduleAsFifoPriority(app.pid, /* suppressLogs */true);
- if (app.renderThreadTid != 0) {
- mService.scheduleAsFifoPriority(app.renderThreadTid,
+ state.setSavedPriority(Process.getThreadPriority(app.getPid()));
+ mService.scheduleAsFifoPriority(app.getPid(), true);
+ if (renderThreadTid != 0) {
+ mService.scheduleAsFifoPriority(renderThreadTid,
/* suppressLogs */true);
if (DEBUG_OOM_ADJ) {
Slog.d("UI_FIFO", "Set RenderThread (TID " +
- app.renderThreadTid + ") to FIFO");
+ renderThreadTid + ") to FIFO");
}
} else {
if (DEBUG_OOM_ADJ) {
@@ -2449,10 +2518,10 @@ public final class OomAdjuster {
}
} else {
// Boost priority for top app UI and render threads
- setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
- if (app.renderThreadTid != 0) {
+ setThreadPriority(app.getPid(), TOP_APP_PRIORITY_BOOST);
+ if (renderThreadTid != 0) {
try {
- setThreadPriority(app.renderThreadTid,
+ setThreadPriority(renderThreadTid,
TOP_APP_PRIORITY_BOOST);
} catch (IllegalArgumentException e) {
// thread died, ignore
@@ -2466,10 +2535,10 @@ public final class OomAdjuster {
if (mService.mUseFifoUiScheduling) {
try {
// Reset UI pipeline to SCHED_OTHER
- setThreadScheduler(app.pid, SCHED_OTHER, 0);
- setThreadPriority(app.pid, app.savedPriority);
- if (app.renderThreadTid != 0) {
- setThreadScheduler(app.renderThreadTid,
+ setThreadScheduler(app.getPid(), SCHED_OTHER, 0);
+ setThreadPriority(app.getPid(), state.getSavedPriority());
+ if (renderThreadTid != 0) {
+ setThreadScheduler(renderThreadTid,
SCHED_OTHER, 0);
}
} catch (IllegalArgumentException e) {
@@ -2481,139 +2550,141 @@ public final class OomAdjuster {
}
} else {
// Reset priority for top app UI and render threads
- setThreadPriority(app.pid, 0);
+ setThreadPriority(app.getPid(), 0);
}
- if (app.renderThreadTid != 0) {
- setThreadPriority(app.renderThreadTid, THREAD_PRIORITY_DISPLAY);
+ if (renderThreadTid != 0) {
+ setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
}
}
} catch (Exception e) {
if (DEBUG_ALL) {
- Slog.w(TAG, "Failed setting thread priority of " + app.pid, e);
+ Slog.w(TAG, "Failed setting thread priority of " + app.getPid(), e);
}
}
}
}
- if (app.repForegroundActivities != app.hasForegroundActivities()) {
- app.repForegroundActivities = app.hasForegroundActivities();
+ if (state.hasRepForegroundActivities() != state.hasForegroundActivities()) {
+ state.setRepForegroundActivities(state.hasForegroundActivities());
changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
}
- updateAppFreezeStateLocked(app);
+ updateAppFreezeStateLSP(app);
- if (app.getReportedProcState() != app.getCurProcState()) {
- app.setReportedProcState(app.getCurProcState());
- if (app.thread != null) {
+ if (state.getReportedProcState() != state.getCurProcState()) {
+ state.setReportedProcState(state.getCurProcState());
+ if (app.getThread() != null) {
try {
if (false) {
//RuntimeException h = new RuntimeException("here");
- Slog.i(TAG, "Sending new process state " + app.getReportedProcState()
+ Slog.i(TAG, "Sending new process state " + state.getReportedProcState()
+ " to " + app /*, h*/);
}
- app.thread.setProcessState(app.getReportedProcState());
+ app.getThread().setProcessState(state.getReportedProcState());
} catch (RemoteException e) {
}
}
}
boolean forceUpdatePssTime = false;
- if (app.setProcState == PROCESS_STATE_NONEXISTENT
- || ProcessList.procStatesDifferForMem(app.getCurProcState(), app.setProcState)) {
- app.lastStateTime = now;
+ if (state.getSetProcState() == PROCESS_STATE_NONEXISTENT
+ || ProcessList.procStatesDifferForMem(
+ state.getCurProcState(), state.getSetProcState())) {
+ state.setLastStateTime(now);
forceUpdatePssTime = true;
if (DEBUG_PSS) {
Slog.d(TAG_PSS, "Process state change from "
- + ProcessList.makeProcStateString(app.setProcState) + " to "
- + ProcessList.makeProcStateString(app.getCurProcState()) + " next pss in "
+ + ProcessList.makeProcStateString(state.getSetProcState()) + " to "
+ + ProcessList.makeProcStateString(state.getCurProcState()) + " next pss in "
+ (app.mProfile.getNextPssTime() - now) + ": " + app);
}
}
synchronized (mService.mAppProfiler.mProfilerLock) {
- app.mProfile.updateProcState(app);
+ app.mProfile.updateProcState(app.mState);
mService.mAppProfiler.updateNextPssTimeLPf(
- app.getCurProcState(), app.mProfile, now, forceUpdatePssTime);
+ state.getCurProcState(), app.mProfile, now, forceUpdatePssTime);
}
- if (app.setProcState != app.getCurProcState()) {
+ if (state.getSetProcState() != state.getCurProcState()) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.uid) {
String msg = "Proc state change of " + app.processName
- + " to " + ProcessList.makeProcStateString(app.getCurProcState())
- + " (" + app.getCurProcState() + ")" + ": " + app.adjType;
+ + " to " + ProcessList.makeProcStateString(state.getCurProcState())
+ + " (" + state.getCurProcState() + ")" + ": " + state.getAdjType();
reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
}
- boolean setImportant = app.setProcState < PROCESS_STATE_SERVICE;
- boolean curImportant = app.getCurProcState() < PROCESS_STATE_SERVICE;
+ boolean setImportant = state.getSetProcState() < PROCESS_STATE_SERVICE;
+ boolean curImportant = state.getCurProcState() < PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
// This app is no longer something we consider important enough to allow to use
// arbitrary amounts of battery power. Note its current CPU time to later know to
// kill it if it is not behaving well.
- app.setWhenUnimportant(now);
+ state.setWhenUnimportant(now);
app.mProfile.mLastCpuTime.set(0);
}
// Inform UsageStats of important process state change
// Must be called before updating setProcState
- maybeUpdateUsageStatsLocked(app, nowElapsed);
+ maybeUpdateUsageStatsLSP(app, nowElapsed);
- maybeUpdateLastTopTime(app, now);
+ maybeUpdateLastTopTime(state, now);
- app.setProcState = app.getCurProcState();
- if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
- app.notCachedSinceIdle = false;
+ state.setSetProcState(state.getCurProcState());
+ if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
+ state.setNotCachedSinceIdle(false);
}
if (!doingAll) {
- mService.setProcessTrackerStateLocked(app,
+ mService.setProcessTrackerStateLOSP(app,
mService.mProcessStats.getMemFactorLocked(), now);
} else {
- app.procStateChanged = true;
+ state.setProcStateChanged(true);
}
- } else if (app.reportedInteraction && (nowElapsed - app.getInteractionEventTime())
+ } else if (state.hasReportedInteraction() && (nowElapsed - state.getInteractionEventTime())
> mConstants.USAGE_STATS_INTERACTION_INTERVAL) {
// For apps that sit around for a long time in the interactive state, we need
// to report this at least once a day so they don't go idle.
- maybeUpdateUsageStatsLocked(app, nowElapsed);
- } else if (!app.reportedInteraction && (nowElapsed - app.getFgInteractionTime())
+ maybeUpdateUsageStatsLSP(app, nowElapsed);
+ } else if (!state.hasReportedInteraction() && (nowElapsed - state.getFgInteractionTime())
> mConstants.SERVICE_USAGE_INTERACTION_TIME) {
// For foreground services that sit around for a long time but are not interacted with.
- maybeUpdateUsageStatsLocked(app, nowElapsed);
+ maybeUpdateUsageStatsLSP(app, nowElapsed);
}
- if (app.curCapability != app.setCapability) {
+ if (state.getCurCapability() != state.getSetCapability()) {
changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY;
- app.setCapability = app.curCapability;
+ state.setSetCapability(state.getCurCapability());
}
if (changes != 0) {
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Changes in " + app + ": " + changes);
ActivityManagerService.ProcessChangeItem item =
- mProcessList.enqueueProcessChangeItemLocked(app.pid, app.info.uid);
+ mProcessList.enqueueProcessChangeItemLocked(app.getPid(), app.info.uid);
item.changes |= changes;
- item.foregroundActivities = app.repForegroundActivities;
- item.capability = app.setCapability;
+ item.foregroundActivities = state.hasRepForegroundActivities();
+ item.capability = state.getSetCapability();
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Item " + Integer.toHexString(System.identityHashCode(item))
+ " " + app.toShortString() + ": changes=" + item.changes
+ " foreground=" + item.foregroundActivities
- + " type=" + app.adjType + " source=" + app.adjSource
- + " target=" + app.adjTarget + " capability=" + item.capability);
+ + " type=" + state.getAdjType() + " source=" + state.getAdjSource()
+ + " target=" + state.getAdjTarget() + " capability=" + item.capability);
}
return success;
}
- @GuardedBy("mService")
- void setAttachingSchedGroupLocked(ProcessRecord app) {
+ @GuardedBy({"mService", "mProcLock"})
+ void setAttachingSchedGroupLSP(ProcessRecord app) {
int initialSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ final ProcessStateRecord state = app.mState;
// If the process has been marked as foreground via Zygote.START_FLAG_USE_TOP_APP_PRIORITY,
// then verify that the top priority is actually is applied.
- if (app.hasForegroundActivities()) {
+ if (state.hasForegroundActivities()) {
String fallbackReason = null;
try {
- // The priority must be the same as how does {@link #applyOomAdjLocked} set for
+ // The priority must be the same as how does {@link #applyOomAdjLSP} set for
// {@link ProcessList.SCHED_GROUP_TOP_APP}. We don't check render thread because it
// is not ready when attaching.
- if (Process.getProcessGroup(app.pid) == THREAD_GROUP_TOP_APP) {
+ if (Process.getProcessGroup(app.getPid()) == THREAD_GROUP_TOP_APP) {
app.getWindowProcessController().onTopProcChanged();
- setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
+ setThreadPriority(app.getPid(), TOP_APP_PRIORITY_BOOST);
} else {
fallbackReason = "not expected top priority";
}
@@ -2629,23 +2700,27 @@ public final class OomAdjuster {
}
}
- app.setCurrentSchedulingGroup(app.setSchedGroup = initialSchedGroup);
+ state.setSetSchedGroup(initialSchedGroup);
+ state.setCurrentSchedulingGroup(initialSchedGroup);
}
// ONLY used for unit testing in OomAdjusterTests.java
@VisibleForTesting
void maybeUpdateUsageStats(ProcessRecord app, long nowElapsed) {
synchronized (mService) {
- maybeUpdateUsageStatsLocked(app, nowElapsed);
+ synchronized (mProcLock) {
+ maybeUpdateUsageStatsLSP(app, nowElapsed);
+ }
}
}
- @GuardedBy("mService")
- private void maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed) {
+ @GuardedBy({"mService", "mProcLock"})
+ private void maybeUpdateUsageStatsLSP(ProcessRecord app, long nowElapsed) {
+ final ProcessStateRecord state = app.mState;
if (DEBUG_USAGE_STATS) {
Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
- + "] state changes: old = " + app.setProcState + ", new = "
- + app.getCurProcState());
+ + "] state changes: old = " + state.getSetProcState() + ", new = "
+ + state.getCurProcState());
}
if (mService.mUsageStatsService == null) {
return;
@@ -2654,27 +2729,28 @@ public final class OomAdjuster {
// To avoid some abuse patterns, we are going to be careful about what we consider
// to be an app interaction. Being the top activity doesn't count while the display
// is sleeping, nor do short foreground services.
- if (app.getCurProcState() <= PROCESS_STATE_TOP
- || app.getCurProcState() == PROCESS_STATE_BOUND_TOP) {
+ if (state.getCurProcState() <= PROCESS_STATE_TOP
+ || state.getCurProcState() == PROCESS_STATE_BOUND_TOP) {
isInteraction = true;
- app.setFgInteractionTime(0);
- } else if (app.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) {
- if (app.getFgInteractionTime() == 0) {
- app.setFgInteractionTime(nowElapsed);
+ state.setFgInteractionTime(0);
+ } else if (state.getCurProcState() <= PROCESS_STATE_FOREGROUND_SERVICE) {
+ if (state.getFgInteractionTime() == 0) {
+ state.setFgInteractionTime(nowElapsed);
isInteraction = false;
} else {
- isInteraction = nowElapsed > app.getFgInteractionTime()
+ isInteraction = nowElapsed > state.getFgInteractionTime()
+ mConstants.SERVICE_USAGE_INTERACTION_TIME;
}
} else {
isInteraction =
- app.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND;
- app.setFgInteractionTime(0);
+ state.getCurProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND;
+ state.setFgInteractionTime(0);
}
if (isInteraction
- && (!app.reportedInteraction || (nowElapsed - app.getInteractionEventTime())
- > mConstants.USAGE_STATS_INTERACTION_INTERVAL)) {
- app.setInteractionEventTime(nowElapsed);
+ && (!state.hasReportedInteraction()
+ || (nowElapsed - state.getInteractionEventTime())
+ > mConstants.USAGE_STATS_INTERACTION_INTERVAL)) {
+ state.setInteractionEventTime(nowElapsed);
String[] packages = app.getPackageList();
if (packages != null) {
for (int i = 0; i < packages.length; i++) {
@@ -2683,16 +2759,16 @@ public final class OomAdjuster {
}
}
}
- app.reportedInteraction = isInteraction;
+ state.setReportedInteraction(isInteraction);
if (!isInteraction) {
- app.setInteractionEventTime(0);
+ state.setInteractionEventTime(0);
}
}
- private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) {
- if (app.setProcState <= PROCESS_STATE_TOP
- && app.getCurProcState() > PROCESS_STATE_TOP) {
- app.lastTopTime = nowUptime;
+ private void maybeUpdateLastTopTime(ProcessStateRecord state, long nowUptime) {
+ if (state.getSetProcState() <= PROCESS_STATE_TOP
+ && state.getCurProcState() > PROCESS_STATE_TOP) {
+ state.setLastTopTime(nowUptime);
}
}
@@ -2714,13 +2790,15 @@ public final class OomAdjuster {
}
for (int i = N - 1; i >= 0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
- final long bgTime = uidRec.lastBackgroundTime;
- if (bgTime > 0 && !uidRec.idle) {
+ final long bgTime = uidRec.getLastBackgroundTime();
+ if (bgTime > 0 && !uidRec.isIdle()) {
if (bgTime <= maxBgTime) {
- EventLogTags.writeAmUidIdle(uidRec.uid);
- uidRec.idle = true;
- uidRec.setIdle = true;
- mService.doStopUidLocked(uidRec.uid, uidRec);
+ EventLogTags.writeAmUidIdle(uidRec.getUid());
+ synchronized (mProcLock) {
+ uidRec.setIdle(true);
+ uidRec.setSetIdle(true);
+ }
+ mService.doStopUidLocked(uidRec.getUid(), uidRec);
} else {
if (nextTime == 0 || nextTime > bgTime) {
nextTime = bgTime;
@@ -2738,35 +2816,35 @@ public final class OomAdjuster {
}
}
- @GuardedBy("mService")
- void setAppIdTempAllowlistStateLocked(int uid, boolean onAllowlist) {
+ @GuardedBy({"mService", "mProcLock"})
+ void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
boolean changed = false;
for (int i = mActiveUids.size() - 1; i >= 0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
- if (uidRec.uid == uid && uidRec.mCurAllowlist != onAllowlist) {
- uidRec.mCurAllowlist = onAllowlist;
+ if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
+ uidRec.setCurAllowListed(onAllowlist);
changed = true;
}
}
if (changed) {
- updateOomAdjLocked(OOM_ADJ_REASON_ALLOWLIST);
+ updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
}
}
- @GuardedBy("mService")
- void setUidTempAllowlistStateLocked(int uid, boolean onAllowlist) {
+ @GuardedBy({"mService", "mProcLock"})
+ void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
boolean changed = false;
final UidRecord uidRec = mActiveUids.get(uid);
- if (uidRec != null && uidRec.mCurAllowlist != onAllowlist) {
- uidRec.mCurAllowlist = onAllowlist;
- updateOomAdjLocked(OOM_ADJ_REASON_ALLOWLIST);
+ if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
+ uidRec.setCurAllowListed(onAllowlist);
+ updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
}
}
@GuardedBy("mService")
void dumpProcessListVariablesLocked(ProtoOutputStream proto) {
proto.write(ActivityManagerServiceDumpProcessesProto.ADJ_SEQ, mAdjSeq);
- proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.mLruSeq);
+ proto.write(ActivityManagerServiceDumpProcessesProto.LRU_SEQ, mProcessList.getLruSeqLOSP());
proto.write(ActivityManagerServiceDumpProcessesProto.NUM_NON_CACHED_PROCS,
mNumNonCachedProcs);
proto.write(ActivityManagerServiceDumpProcessesProto.NUM_SERVICE_PROCS, mNumServiceProcs);
@@ -2777,19 +2855,19 @@ public final class OomAdjuster {
@GuardedBy("mService")
void dumpSequenceNumbersLocked(PrintWriter pw) {
- pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.mLruSeq);
+ pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mProcessList.getLruSeqLOSP());
}
@GuardedBy("mService")
void dumpProcCountsLocked(PrintWriter pw) {
pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
- + " (" + mProcessList.getLruSizeLocked() + " total)"
+ + " (" + mProcessList.getLruSizeLOSP() + " total)"
+ " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
+ " mNumServiceProcs=" + mNumServiceProcs
+ " mNewNumServiceProcs=" + mNewNumServiceProcs);
}
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
void dumpCachedAppOptimizerSettings(PrintWriter pw) {
mCachedAppOptimizer.dump(pw);
}
@@ -2799,22 +2877,25 @@ public final class OomAdjuster {
mCacheOomRanker.dump(pw);
}
- @GuardedBy("mService")
- void updateAppFreezeStateLocked(ProcessRecord app) {
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateAppFreezeStateLSP(ProcessRecord app) {
if (!mCachedAppOptimizer.useFreezer()) {
return;
}
+ final ProcessCachedOptimizerRecord opt = app.mOptRecord;
// if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze
- if (app.frozen && app.shouldNotFreeze) {
- mCachedAppOptimizer.unfreezeAppLocked(app);
+ if (opt.isFrozen() && opt.shouldNotFreeze()) {
+ mCachedAppOptimizer.unfreezeAppLSP(app);
}
+ final ProcessStateRecord state = app.mState;
// Use current adjustment when freezing, set adjustment when unfreezing.
- if (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ && !app.frozen && !app.shouldNotFreeze) {
- mCachedAppOptimizer.freezeAppAsync(app);
- } else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ && app.frozen) {
- mCachedAppOptimizer.unfreezeAppLocked(app);
+ if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
+ && !opt.shouldNotFreeze()) {
+ mCachedAppOptimizer.freezeAppAsyncLSP(app);
+ } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ && opt.isFrozen()) {
+ mCachedAppOptimizer.unfreezeAppLSP(app);
}
}
}
diff --git a/services/core/java/com/android/server/am/PackageList.java b/services/core/java/com/android/server/am/PackageList.java
index 978bcb7afee45..aa10d52eb48c8 100644
--- a/services/core/java/com/android/server/am/PackageList.java
+++ b/services/core/java/com/android/server/am/PackageList.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.annotation.NonNull;
import android.content.pm.VersionedPackage;
import android.util.ArrayMap;
@@ -73,7 +74,7 @@ final class PackageList {
}
}
- void forEachPackage(Consumer callback) {
+ void forEachPackage(@NonNull Consumer callback) {
synchronized (this) {
for (int i = 0, size = mPkgList.size(); i < size; i++) {
callback.accept(mPkgList.keyAt(i));
@@ -81,7 +82,7 @@ final class PackageList {
}
}
- void forEachPackage(BiConsumer callback) {
+ void forEachPackage(@NonNull BiConsumer callback) {
synchronized (this) {
for (int i = 0, size = mPkgList.size(); i < size; i++) {
callback.accept(mPkgList.keyAt(i), mPkgList.valueAt(i));
@@ -89,7 +90,16 @@ final class PackageList {
}
}
- R forEachPackage(Function callback) {
+ /**
+ * Search in the package list, invoke the given {@code callback} with each of the package names
+ * in that list; if the callback returns a non-null object, halt the search, return that
+ * object as the return value of this search function.
+ *
+ * @param callback The callback interface to accept the current package name; if it returns
+ * a non-null object, the search will be halted and this object will be used
+ * as the return value of this search function.
+ */
+ R searchEachPackage(@NonNull Function callback) {
synchronized (this) {
for (int i = 0, size = mPkgList.size(); i < size; i++) {
R r = callback.apply(mPkgList.keyAt(i));
@@ -101,7 +111,7 @@ final class PackageList {
return null;
}
- void forEachPackageProcessStats(Consumer callback) {
+ void forEachPackageProcessStats(@NonNull Consumer callback) {
synchronized (this) {
for (int i = 0, size = mPkgList.size(); i < size; i++) {
callback.accept(mPkgList.valueAt(i));
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index 37b17411dac58..4f3438fe8706a 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -148,13 +148,14 @@ public final class PhantomProcessList {
@GuardedBy({"mLock", "mService.mPidsSelfLocked"})
private void lookForPhantomProcessesLocked(ProcessRecord app) {
- if (app.appZygote || app.killed || app.killedByAm) {
+ if (app.appZygote || app.isKilled() || app.isKilledByAm()) {
// process forked from app zygote doesn't have its own acct entry
return;
}
- InputStream input = mCgroupProcsFds.get(app.pid);
+ final int appPid = app.getPid();
+ InputStream input = mCgroupProcsFds.get(appPid);
if (input == null) {
- final String path = getCgroupFilePath(app.info.uid, app.pid);
+ final String path = getCgroupFilePath(app.info.uid, appPid);
try {
input = mInjector.openCgroupProcs(path);
} catch (FileNotFoundException | SecurityException e) {
@@ -164,7 +165,7 @@ public final class PhantomProcessList {
return;
}
// Keep the FD open for better performance
- mCgroupProcsFds.put(app.pid, input);
+ mCgroupProcsFds.put(appPid, input);
}
final byte[] buf = mDataBuffer;
try {
@@ -180,7 +181,7 @@ public final class PhantomProcessList {
for (int i = 0; i < read; i++) {
final byte b = buf[i];
if (b == '\n') {
- addChildPidLocked(app, pid);
+ addChildPidLocked(app, pid, appPid);
pid = 0;
} else {
pid = pid * 10 + (b - '0');
@@ -193,14 +194,14 @@ public final class PhantomProcessList {
}
} while (true);
if (pid != 0) {
- addChildPidLocked(app, pid);
+ addChildPidLocked(app, pid, appPid);
}
// rewind the fd for the next read
input.skip(-totalRead);
} catch (IOException e) {
Slog.e(TAG, "Error in reading cgroup procs from " + app, e);
IoUtils.closeQuietly(input);
- mCgroupProcsFds.delete(app.pid);
+ mCgroupProcsFds.delete(appPid);
}
}
@@ -232,8 +233,8 @@ public final class PhantomProcessList {
}
@GuardedBy({"mLock", "mService.mPidsSelfLocked"})
- private void addChildPidLocked(final ProcessRecord app, final int pid) {
- if (app.pid != pid) {
+ private void addChildPidLocked(final ProcessRecord app, final int pid, final int appPid) {
+ if (appPid != pid) {
// That's something else...
final ProcessRecord r = mService.mPidsSelfLocked.get(pid);
if (r != null) {
@@ -328,15 +329,16 @@ public final class PhantomProcessList {
if (r != null) {
// It's a phantom process, bookkeep it
try {
+ final int appPid = r.getPid();
final PhantomProcessRecord proc = new PhantomProcessRecord(
- processName, uid, pid, r.pid, mService,
+ processName, uid, pid, appPid, mService,
this::onPhantomProcessKilledLocked);
proc.mUpdateSeq = mUpdateSeq;
mPhantomProcesses.put(pid, proc);
- SparseArray array = mAppPhantomProcessMap.get(r.pid);
+ SparseArray array = mAppPhantomProcessMap.get(appPid);
if (array == null) {
array = new SparseArray<>();
- mAppPhantomProcessMap.put(r.pid, array);
+ mAppPhantomProcessMap.put(appPid, array);
}
array.put(pid, proc);
if (proc.mPidFd != null) {
@@ -414,40 +416,42 @@ public final class PhantomProcessList {
* order of the oom adjs of their parent process.
*/
void trimPhantomProcessesIfNecessary() {
- synchronized (mLock) {
- mTrimPhantomProcessScheduled = false;
- if (mService.mConstants.MAX_PHANTOM_PROCESSES < mPhantomProcesses.size()) {
- for (int i = mPhantomProcesses.size() - 1; i >= 0; i--) {
- mTempPhantomProcesses.add(mPhantomProcesses.valueAt(i));
+ synchronized (mService.mProcLock) {
+ synchronized (mLock) {
+ mTrimPhantomProcessScheduled = false;
+ if (mService.mConstants.MAX_PHANTOM_PROCESSES < mPhantomProcesses.size()) {
+ for (int i = mPhantomProcesses.size() - 1; i >= 0; i--) {
+ mTempPhantomProcesses.add(mPhantomProcesses.valueAt(i));
+ }
+ synchronized (mService.mPidsSelfLocked) {
+ Collections.sort(mTempPhantomProcesses, (a, b) -> {
+ final ProcessRecord ra = mService.mPidsSelfLocked.get(a.mPpid);
+ if (ra == null) {
+ // parent is gone, this process should have been killed too
+ return 1;
+ }
+ final ProcessRecord rb = mService.mPidsSelfLocked.get(b.mPpid);
+ if (rb == null) {
+ // parent is gone, this process should have been killed too
+ return -1;
+ }
+ if (ra.mState.getCurAdj() != rb.mState.getCurAdj()) {
+ return ra.mState.getCurAdj() - rb.mState.getCurAdj();
+ }
+ if (a.mKnownSince != b.mKnownSince) {
+ // In case of identical oom adj, younger one first
+ return a.mKnownSince < b.mKnownSince ? 1 : -1;
+ }
+ return 0;
+ });
+ }
+ for (int i = mTempPhantomProcesses.size() - 1;
+ i >= mService.mConstants.MAX_PHANTOM_PROCESSES; i--) {
+ final PhantomProcessRecord proc = mTempPhantomProcesses.get(i);
+ proc.killLocked("Trimming phantom processes", true);
+ }
+ mTempPhantomProcesses.clear();
}
- synchronized (mService.mPidsSelfLocked) {
- Collections.sort(mTempPhantomProcesses, (a, b) -> {
- final ProcessRecord ra = mService.mPidsSelfLocked.get(a.mPpid);
- if (ra == null) {
- // parent is gone, this process should have been killed too
- return 1;
- }
- final ProcessRecord rb = mService.mPidsSelfLocked.get(b.mPpid);
- if (rb == null) {
- // parent is gone, this process should have been killed too
- return -1;
- }
- if (ra.curAdj != rb.curAdj) {
- return ra.curAdj - rb.curAdj;
- }
- if (a.mKnownSince != b.mKnownSince) {
- // In case of identical oom adj, younger one first
- return a.mKnownSince < b.mKnownSince ? 1 : -1;
- }
- return 0;
- });
- }
- for (int i = mTempPhantomProcesses.size() - 1;
- i >= mService.mConstants.MAX_PHANTOM_PROCESSES; i--) {
- final PhantomProcessRecord proc = mTempPhantomProcesses.get(i);
- proc.killLocked("Trimming phantom processes", true);
- }
- mTempPhantomProcesses.clear();
}
}
}
@@ -498,7 +502,7 @@ public final class PhantomProcessList {
}
}
// Lastly, kill the parent process too
- app.kill("Caused by child process: " + msg, reasonCode, subReason, true);
+ app.killLocked("Caused by child process: " + msg, reasonCode, subReason, true);
}
/**
@@ -508,7 +512,7 @@ public final class PhantomProcessList {
void forEachPhantomProcessOfApp(final ProcessRecord app,
final Function callback) {
synchronized (mLock) {
- int index = mAppPhantomProcessMap.indexOfKey(app.pid);
+ int index = mAppPhantomProcessMap.indexOfKey(app.getPid());
if (index >= 0) {
final SparseArray array =
mAppPhantomProcessMap.valueAt(index);
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
new file mode 100644
index 0000000000000..464361076dc80
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+
+/**
+ * The state info of app when it's cached, used by the optimizer.
+ */
+final class ProcessCachedOptimizerRecord {
+ private final ProcessRecord mApp;
+
+ private final ActivityManagerGlobalLock mProcLock;
+
+ /**
+ * The last time that this process was compacted.
+ */
+ @GuardedBy("mProcLock")
+ private long mLastCompactTime;
+
+ /**
+ * The most recent compaction action requested for this app.
+ */
+ @GuardedBy("mProcLock")
+ private int mReqCompactAction;
+
+ /**
+ * The most recent compaction action performed for this app.
+ */
+ @GuardedBy("mProcLock")
+ private int mLastCompactAction;
+
+ /**
+ * True when the process is frozen.
+ */
+ @GuardedBy("mProcLock")
+ private boolean mFrozen;
+
+ /**
+ * An override on the freeze state is in progress.
+ */
+ @GuardedBy("mProcLock")
+ boolean mFreezerOverride;
+
+ /**
+ * Last time the app was (un)frozen, 0 for never.
+ */
+ @GuardedBy("mProcLock")
+ private long mFreezeUnfreezeTime;
+
+ /**
+ * True if a process has a WPRI binding from an unfrozen process.
+ */
+ @GuardedBy("mProcLock")
+ private boolean mShouldNotFreeze;
+
+ @GuardedBy("mProcLock")
+ long getLastCompactTime() {
+ return mLastCompactTime;
+ }
+
+ @GuardedBy("mProcLock")
+ void setLastCompactTime(long lastCompactTime) {
+ mLastCompactTime = lastCompactTime;
+ }
+
+ @GuardedBy("mProcLock")
+ int getReqCompactAction() {
+ return mReqCompactAction;
+ }
+
+ @GuardedBy("mProcLock")
+ void setReqCompactAction(int reqCompactAction) {
+ mReqCompactAction = reqCompactAction;
+ }
+
+ @GuardedBy("mProcLock")
+ int getLastCompactAction() {
+ return mLastCompactAction;
+ }
+
+ @GuardedBy("mProcLock")
+ void setLastCompactAction(int lastCompactAction) {
+ mLastCompactAction = lastCompactAction;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean isFrozen() {
+ return mFrozen;
+ }
+
+ @GuardedBy("mProcLock")
+ void setFrozen(boolean frozen) {
+ mFrozen = frozen;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasFreezerOverride() {
+ return mFreezerOverride;
+ }
+
+ @GuardedBy("mProcLock")
+ void setFreezerOverride(boolean freezerOverride) {
+ mFreezerOverride = freezerOverride;
+ }
+
+ @GuardedBy("mProcLock")
+ long getFreezeUnfreezeTime() {
+ return mFreezeUnfreezeTime;
+ }
+
+ @GuardedBy("mProcLock")
+ void setFreezeUnfreezeTime(long freezeUnfreezeTime) {
+ mFreezeUnfreezeTime = freezeUnfreezeTime;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean shouldNotFreeze() {
+ return mShouldNotFreeze;
+ }
+
+ @GuardedBy("mProcLock")
+ void setShouldNotFreeze(boolean shouldNotFreeze) {
+ mShouldNotFreeze = shouldNotFreeze;
+ }
+
+ ProcessCachedOptimizerRecord(ProcessRecord app) {
+ mApp = app;
+ mProcLock = app.mService.mProcLock;
+ }
+
+ void init(long nowUptime) {
+ mFreezeUnfreezeTime = nowUptime;
+ }
+
+ @GuardedBy("mProcLock")
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ pw.print(prefix); pw.print("lastCompactTime="); pw.print(mLastCompactTime);
+ pw.print(" lastCompactAction="); pw.println(mLastCompactAction);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
new file mode 100644
index 0000000000000..64e307a5f1820
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
+import static com.android.server.am.ActivityManagerService.MY_PID;
+import static com.android.server.am.ProcessRecord.TAG;
+
+import android.app.ActivityManager;
+import android.app.ApplicationErrorReport;
+import android.app.ApplicationExitInfo;
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IncrementalStatesInfo;
+import android.content.pm.PackageManagerInternal;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.EventLog;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.CompositeRWLock;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.MemoryPressureUtil;
+import com.android.server.wm.WindowProcessController;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+/**
+ * The error state of the process, such as if it's crashing/ANR etc.
+ */
+class ProcessErrorStateRecord {
+ final ProcessRecord mApp;
+ private final ActivityManagerService mService;
+
+ private final ActivityManagerGlobalLock mProcLock;
+
+ /**
+ * True if disabled in the bad process list.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mBad;
+
+ /**
+ * Are we in the process of crashing?
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mCrashing;
+
+ /**
+ * Suppress normal auto-dismiss of crash dialog & report UI?
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mForceCrashReport;
+
+ /**
+ * Does the app have a not responding dialog?
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mNotResponding;
+
+ /**
+ * The report about crash of the app, generated & stored when an app gets into a crash.
+ * Will be "null" when all is OK.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ActivityManager.ProcessErrorStateInfo mCrashingReport;
+
+ /**
+ * The report about ANR of the app, generated & stored when an app gets into an ANR.
+ * Will be "null" when all is OK.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ActivityManager.ProcessErrorStateInfo mNotRespondingReport;
+
+ /**
+ * Controller for error dialogs.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private final ErrorDialogController mDialogController;
+
+ /**
+ * Who will be notified of the error. This is usually an activity in the
+ * app that installed the package.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ComponentName mErrorReportReceiver;
+
+ /**
+ * Optional local handler to be invoked in the process crash.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private Runnable mCrashHandler;
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isBad() {
+ return mBad;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setBad(boolean bad) {
+ mBad = bad;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isCrashing() {
+ return mCrashing;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCrashing(boolean crashing) {
+ mCrashing = crashing;
+ mApp.getWindowProcessController().setCrashing(crashing);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isForceCrashReport() {
+ return mForceCrashReport;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setForceCrashReport(boolean forceCrashReport) {
+ mForceCrashReport = forceCrashReport;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isNotResponding() {
+ return mNotResponding;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setNotResponding(boolean notResponding) {
+ mNotResponding = notResponding;
+ mApp.getWindowProcessController().setNotResponding(notResponding);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ Runnable getCrashHandler() {
+ return mCrashHandler;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCrashHandler(Runnable crashHandler) {
+ mCrashHandler = crashHandler;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ActivityManager.ProcessErrorStateInfo getCrashingReport() {
+ return mCrashingReport;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCrashingReport(ActivityManager.ProcessErrorStateInfo crashingReport) {
+ mCrashingReport = crashingReport;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ActivityManager.ProcessErrorStateInfo getNotRespondingReport() {
+ return mNotRespondingReport;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setNotRespondingReport(ActivityManager.ProcessErrorStateInfo notRespondingReport) {
+ mNotRespondingReport = notRespondingReport;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ComponentName getErrorReportReceiver() {
+ return mErrorReportReceiver;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setErrorReportReceiver(ComponentName errorReportReceiver) {
+ mErrorReportReceiver = errorReportReceiver;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ErrorDialogController getDialogController() {
+ return mDialogController;
+ }
+
+ ProcessErrorStateRecord(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ mProcLock = mService.mProcLock;
+ mDialogController = new ErrorDialogController(app);
+ }
+
+ void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
+ String parentShortComponentName, WindowProcessController parentProcess,
+ boolean aboveSystem, String annotation, boolean onlyDumpSelf) {
+ ArrayList firstPids = new ArrayList<>(5);
+ SparseArray lastPids = new SparseArray<>(20);
+
+ mApp.getWindowProcessController().appEarlyNotResponding(annotation, () -> {
+ synchronized (mService) {
+ mApp.killLocked("anr", ApplicationExitInfo.REASON_ANR, true);
+ }
+ });
+
+ long anrTime = SystemClock.uptimeMillis();
+ if (isMonitorCpuUsage()) {
+ mService.updateCpuStatsNow();
+ }
+
+ final boolean isSilentAnr;
+ final int pid = mApp.getPid();
+ synchronized (mService) {
+ // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
+ if (mService.mAtmInternal.isShuttingDown()) {
+ Slog.i(TAG, "During shutdown skipping ANR: " + this + " " + annotation);
+ return;
+ } else if (isNotResponding()) {
+ Slog.i(TAG, "Skipping duplicate ANR: " + this + " " + annotation);
+ return;
+ } else if (isCrashing()) {
+ Slog.i(TAG, "Crashing app skipping ANR: " + this + " " + annotation);
+ return;
+ } else if (mApp.isKilledByAm()) {
+ Slog.i(TAG, "App already killed by AM skipping ANR: " + this + " " + annotation);
+ return;
+ } else if (mApp.isKilled()) {
+ Slog.i(TAG, "Skipping died app ANR: " + this + " " + annotation);
+ return;
+ }
+
+ // In case we come through here for the same app before completing
+ // this one, mark as anring now so we will bail out.
+ synchronized (mProcLock) {
+ setNotResponding(true);
+ }
+
+ // Log the ANR to the event log.
+ EventLog.writeEvent(EventLogTags.AM_ANR, mApp.userId, pid, mApp.processName,
+ mApp.info.flags, annotation);
+
+ // Dump thread traces as quickly as we can, starting with "interesting" processes.
+ firstPids.add(pid);
+
+ // Don't dump other PIDs if it's a background ANR or is requested to only dump self.
+ isSilentAnr = isSilentAnr();
+ if (!isSilentAnr && !onlyDumpSelf) {
+ int parentPid = pid;
+ if (parentProcess != null && parentProcess.getPid() > 0) {
+ parentPid = parentProcess.getPid();
+ }
+ if (parentPid != pid) firstPids.add(parentPid);
+
+ if (MY_PID != pid && MY_PID != parentPid) firstPids.add(MY_PID);
+
+ final int ppid = parentPid;
+ mService.mProcessList.forEachLruProcessesLOSP(false, r -> {
+ if (r != null && r.getThread() != null) {
+ int myPid = r.getPid();
+ if (myPid > 0 && myPid != pid && myPid != ppid && myPid != MY_PID) {
+ if (r.isPersistent()) {
+ firstPids.add(myPid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
+ } else if (r.mServices.isTreatedLikeActivity()) {
+ firstPids.add(myPid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
+ } else {
+ lastPids.put(myPid, Boolean.TRUE);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ // Check if package is still being loaded
+ boolean isPackageLoading = false;
+ final PackageManagerInternal packageManagerInternal = mService.getPackageManagerInternal();
+ if (aInfo != null && aInfo.packageName != null) {
+ IncrementalStatesInfo incrementalStatesInfo =
+ packageManagerInternal.getIncrementalStatesInfo(
+ aInfo.packageName, mApp.uid, mApp.userId);
+ if (incrementalStatesInfo != null) {
+ isPackageLoading = incrementalStatesInfo.isLoading();
+ }
+ }
+
+ // Log the ANR to the main log.
+ StringBuilder info = new StringBuilder();
+ info.setLength(0);
+ info.append("ANR in ").append(mApp.processName);
+ if (activityShortComponentName != null) {
+ info.append(" (").append(activityShortComponentName).append(")");
+ }
+ info.append("\n");
+ info.append("PID: ").append(pid).append("\n");
+ if (annotation != null) {
+ info.append("Reason: ").append(annotation).append("\n");
+ }
+ if (parentShortComponentName != null
+ && parentShortComponentName.equals(activityShortComponentName)) {
+ info.append("Parent: ").append(parentShortComponentName).append("\n");
+ }
+
+ if (isPackageLoading) {
+ // Report in the main log that the package is still loading
+ final float loadingProgress = packageManagerInternal.getIncrementalStatesInfo(
+ aInfo.packageName, mApp.uid, mApp.userId).getProgress();
+ info.append("Package is ").append((int) (loadingProgress * 100)).append("% loaded.\n");
+ }
+
+ StringBuilder report = new StringBuilder();
+ report.append(MemoryPressureUtil.currentPsiState());
+ ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
+
+ // don't dump native PIDs for background ANRs unless it is the process of interest
+ String[] nativeProcs = null;
+ if (isSilentAnr || onlyDumpSelf) {
+ for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
+ if (NATIVE_STACKS_OF_INTEREST[i].equals(mApp.processName)) {
+ nativeProcs = new String[] { mApp.processName };
+ break;
+ }
+ }
+ } else {
+ nativeProcs = NATIVE_STACKS_OF_INTEREST;
+ }
+
+ int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
+ ArrayList nativePids = null;
+
+ if (pids != null) {
+ nativePids = new ArrayList<>(pids.length);
+ for (int i : pids) {
+ nativePids.add(i);
+ }
+ }
+
+ // For background ANRs, don't pass the ProcessCpuTracker to
+ // avoid spending 1/2 second collecting stats to rank lastPids.
+ StringWriter tracesFileException = new StringWriter();
+ // To hold the start and end offset to the ANR trace file respectively.
+ final long[] offsets = new long[2];
+ File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
+ isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids,
+ nativePids, tracesFileException, offsets);
+
+ if (isMonitorCpuUsage()) {
+ mService.updateCpuStatsNow();
+ mService.mAppProfiler.printCurrentCpuState(report, anrTime);
+ info.append(processCpuTracker.printCurrentLoad());
+ info.append(report);
+ }
+ report.append(tracesFileException.getBuffer());
+
+ info.append(processCpuTracker.printCurrentState(anrTime));
+
+ Slog.e(TAG, info.toString());
+ if (tracesFile == null) {
+ // There is no trace file, so dump (only) the alleged culprit's threads to the log
+ Process.sendSignal(pid, Process.SIGNAL_QUIT);
+ } else if (offsets[1] > 0) {
+ // We've dumped into the trace file successfully
+ mService.mProcessList.mAppExitInfoTracker.scheduleLogAnrTrace(
+ pid, mApp.uid, mApp.getPackageList(), tracesFile, offsets[0], offsets[1]);
+ }
+
+ FrameworkStatsLog.write(FrameworkStatsLog.ANR_OCCURRED, mApp.uid, mApp.processName,
+ activityShortComponentName == null ? "unknown" : activityShortComponentName,
+ annotation,
+ (mApp.info != null) ? (mApp.info.isInstantApp()
+ ? FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
+ : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
+ : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
+ mApp.isInterestingToUserLocked()
+ ? FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
+ : FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND,
+ mApp.getProcessClassEnum(),
+ (mApp.info != null) ? mApp.info.packageName : "", isPackageLoading);
+ final ProcessRecord parentPr = parentProcess != null
+ ? (ProcessRecord) parentProcess.mOwner : null;
+ mService.addErrorToDropBox("anr", mApp, mApp.processName, activityShortComponentName,
+ parentShortComponentName, parentPr, annotation, report.toString(), tracesFile,
+ null);
+
+ if (mApp.getWindowProcessController().appNotResponding(info.toString(),
+ () -> {
+ synchronized (mService) {
+ mApp.killLocked("anr", ApplicationExitInfo.REASON_ANR, true);
+ }
+ },
+ () -> {
+ synchronized (mService) {
+ mService.mServices.scheduleServiceTimeoutLocked(mApp);
+ }
+ })) {
+ return;
+ }
+
+ synchronized (mService) {
+ // mBatteryStatsService can be null if the AMS is constructed with injector only. This
+ // will only happen in tests.
+ if (mService.mBatteryStatsService != null) {
+ mService.mBatteryStatsService.noteProcessAnr(mApp.processName, mApp.uid);
+ }
+
+ if (isSilentAnr() && !mApp.isDebugging()) {
+ mApp.killLocked("bg anr", ApplicationExitInfo.REASON_ANR, true);
+ return;
+ }
+
+ synchronized (mProcLock) {
+ // Set the app's notResponding state, and look up the errorReportReceiver
+ makeAppNotRespondingLSP(activityShortComponentName,
+ annotation != null ? "ANR " + annotation : "ANR", info.toString());
+ }
+
+ // Notify package manager service to possibly update package state
+ if (aInfo != null && aInfo.packageName != null) {
+ packageManagerInternal.notifyPackageCrashOrAnr(aInfo.packageName);
+ }
+
+ // mUiHandler can be null if the AMS is constructed with injector only. This will only
+ // happen in tests.
+ if (mService.mUiHandler != null) {
+ // Bring up the infamous App Not Responding dialog
+ Message msg = Message.obtain();
+ msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
+ msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem);
+
+ mService.mUiHandler.sendMessage(msg);
+ }
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private void makeAppNotRespondingLSP(String activity, String shortMsg, String longMsg) {
+ setNotResponding(true);
+ // mAppErrors can be null if the AMS is constructed with injector only. This will only
+ // happen in tests.
+ if (mService.mAppErrors != null) {
+ mNotRespondingReport = mService.mAppErrors.generateProcessError(mApp,
+ ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
+ activity, shortMsg, longMsg, null);
+ }
+ startAppProblemLSP();
+ mApp.getWindowProcessController().stopFreezingActivities();
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void startAppProblemLSP() {
+ // If this app is not running under the current user, then we can't give it a report button
+ // because that would require launching the report UI under a different user.
+ mErrorReportReceiver = null;
+
+ for (int userId : mService.mUserController.getCurrentProfileIds()) {
+ if (mApp.userId == userId) {
+ mErrorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+ mService.mContext, mApp.info.packageName, mApp.info.flags);
+ }
+ }
+ mService.skipCurrentReceiverLocked(mApp);
+ }
+
+ @GuardedBy("mService")
+ private boolean isInterestingForBackgroundTraces() {
+ // The system_server is always considered interesting.
+ if (mApp.getPid() == MY_PID) {
+ return true;
+ }
+
+ // A package is considered interesting if any of the following is true :
+ //
+ // - It's displaying an activity.
+ // - It's the SystemUI.
+ // - It has an overlay or a top UI visible.
+ //
+ // NOTE: The check whether a given ProcessRecord belongs to the systemui
+ // process is a bit of a kludge, but the same pattern seems repeated at
+ // several places in the system server.
+ return mApp.isInterestingToUserLocked()
+ || (mApp.info != null && "com.android.systemui".equals(mApp.info.packageName))
+ || (mApp.mState.hasTopUi() || mApp.mState.hasOverlayUi());
+ }
+
+ private boolean getShowBackground() {
+ return Settings.Secure.getInt(mService.mContext.getContentResolver(),
+ Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+ }
+
+ /**
+ * Unless configured otherwise, swallow ANRs in background processes & kill the process.
+ * Non-private access is for tests only.
+ */
+ @VisibleForTesting
+ @GuardedBy("mService")
+ boolean isSilentAnr() {
+ return !getShowBackground() && !isInterestingForBackgroundTraces();
+ }
+
+ /** Non-private access is for tests only. */
+ @VisibleForTesting
+ boolean isMonitorCpuUsage() {
+ return mService.mAppProfiler.MONITOR_CPU_USAGE;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void onCleanupApplicationRecordLSP() {
+ // Dismiss any open dialogs.
+ getDialogController().clearAllErrorDialogs();
+
+ setCrashing(false);
+ setNotResponding(false);
+ }
+
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ synchronized (mProcLock) {
+ if (mCrashing || mDialogController.hasCrashDialogs() || mNotResponding
+ || mDialogController.hasAnrDialogs() || mBad) {
+ pw.print(prefix);
+ pw.print(" mCrashing=" + mCrashing);
+ pw.print(" " + mDialogController.getCrashDialogs());
+ pw.print(" mNotResponding=" + mNotResponding);
+ pw.print(" " + mDialogController.getAnrDialogs());
+ pw.print(" bad=" + mBad);
+
+ // mCrashing or mNotResponding is always set before errorReportReceiver
+ if (mErrorReportReceiver != null) {
+ pw.print(" errorReportReceiver=");
+ pw.print(mErrorReportReceiver.flattenToShortString());
+ }
+ pw.println();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 8f994591f96c4..81bfde6ecf8e6 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -55,6 +55,7 @@ import static com.android.server.am.ActivityManagerService.TAG_PROCESSES;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
import static com.android.server.am.AppProfiler.TAG_PSS;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
@@ -114,6 +115,7 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ProcessMap;
@@ -149,6 +151,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Activity manager code dealing with processes.
@@ -466,34 +470,41 @@ public final class ProcessList {
* List of running applications, sorted by recent usage.
* The first entry in the list is the least recently used.
*/
- final ArrayList mLruProcesses = new ArrayList();
+ @CompositeRWLock({"mService", "mProcLock"})
+ private final ArrayList mLruProcesses = new ArrayList();
/**
* Where in mLruProcesses that the processes hosting activities start.
*/
- int mLruProcessActivityStart = 0;
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mLruProcessActivityStart = 0;
/**
* Where in mLruProcesses that the processes hosting services start.
* This is after (lower index) than mLruProcessesActivityStart.
*/
- int mLruProcessServiceStart = 0;
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mLruProcessServiceStart = 0;
/**
* Current sequence id for process LRU updating.
*/
- int mLruSeq = 0;
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mLruSeq = 0;
+ @CompositeRWLock({"mService", "mProcLock"})
ActiveUids mActiveUids;
/**
* The currently running isolated processes.
*/
+ @GuardedBy("mService")
final SparseArray mIsolatedProcesses = new SparseArray<>();
/**
* The currently running application zygotes.
*/
+ @GuardedBy("mService")
final ProcessMap mAppZygotes = new ProcessMap();
/**
@@ -505,6 +516,7 @@ public final class ProcessList {
/**
* The processes that are forked off an application zygote.
*/
+ @GuardedBy("mService")
final ArrayMap> mAppZygoteProcesses =
new ArrayMap>();
@@ -532,6 +544,8 @@ public final class ProcessList {
*/
private final int[] mZygoteSigChldMessage = new int[3];
+ ActivityManagerGlobalLock mProcLock;
+
final class IsolatedUidRange {
@VisibleForTesting
public final int mFirstUid;
@@ -640,6 +654,7 @@ public final class ProcessList {
* The available isolated UIDs for processes that are not spawned from an application zygote.
*/
@VisibleForTesting
+ @GuardedBy("mService")
IsolatedUidRange mGlobalIsolatedUids = new IsolatedUidRange(Process.FIRST_ISOLATED_UID,
Process.LAST_ISOLATED_UID);
@@ -647,6 +662,7 @@ public final class ProcessList {
* An allocator for isolated UID ranges for apps that use an application zygote.
*/
@VisibleForTesting
+ @GuardedBy("mService")
IsolatedUidRangeAllocator mAppIsolatedUidRangeAllocator =
new IsolatedUidRangeAllocator(Process.FIRST_APP_ZYGOTE_ISOLATED_UID,
Process.LAST_APP_ZYGOTE_ISOLATED_UID, Process.NUM_UIDS_PER_APP_ZYGOTE);
@@ -654,6 +670,7 @@ public final class ProcessList {
/**
* Processes that are being forcibly torn down.
*/
+ @GuardedBy("mService")
final ArrayList mRemovedProcesses = new ArrayList();
// Self locked with the inner lock within the RemoteCallbackList
@@ -674,14 +691,14 @@ public final class ProcessList {
*/
private final Object mProcessChangeLock = new Object();
-
/**
* All of the applications we currently have running organized by name.
* The keys are strings of the application package name (as
* returned by the package manager), and the keys are ApplicationRecord
* objects.
*/
- final MyProcessMap mProcessNames = new MyProcessMap();
+ @CompositeRWLock({"mService", "mProcLock"})
+ private final MyProcessMap mProcessNames = new MyProcessMap();
final class MyProcessMap extends ProcessMap {
@Override
@@ -749,6 +766,7 @@ public final class ProcessList {
mService = service;
mActiveUids = activeUids;
mPlatformCompat = platformCompat;
+ mProcLock = service.mProcLock;
// Get this after boot, and won't be changed until it's rebooted, as we don't
// want some apps enabled while some apps disabled
mAppDataIsolationEnabled =
@@ -842,13 +860,13 @@ public final class ProcessList {
*/
Map getProcessesWithPendingBindMounts(int userId) {
final Map pidPackageMap = new HashMap<>();
- synchronized (mService) {
+ synchronized (mProcLock) {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord record = mLruProcesses.get(i);
- if (record.userId != userId || !record.bindMountPending) {
+ if (record.userId != userId || !record.isBindMountPending()) {
continue;
}
- final int pid = record.pid;
+ final int pid = record.getPid();
// It can happen when app process is starting, but zygote work is not done yet so
// system does not this pid record yet.
if (pid == 0) {
@@ -857,8 +875,8 @@ public final class ProcessList {
}
pidPackageMap.put(pid, record.info.packageName);
}
- return pidPackageMap;
}
+ return pidPackageMap;
}
private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
@@ -1534,6 +1552,7 @@ public final class ProcessList {
}
}
+ @GuardedBy("mService")
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean
keepIfLarge) {
if (uid == SYSTEM_UID) {
@@ -1554,21 +1573,19 @@ public final class ProcessList {
}
ProcessRecord proc = mProcessNames.get(processName, uid);
if (false && proc != null && !keepIfLarge
- && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ && proc.mState.getSetProcState() >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
&& proc.mProfile.getLastCachedPss() >= 4000) {
// Turn this condition on to cause killing to happen regularly, for testing.
- final long lastCachedPss;
synchronized (mService.mAppProfiler.mProfilerLock) {
proc.mProfile.reportCachedKill();
- lastCachedPss = proc.mProfile.getLastCachedPss();
}
- proc.kill(Long.toString(lastCachedPss) + "k from cached",
+ proc.killLocked(Long.toString(proc.mProfile.getLastCachedPss()) + "k from cached",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_LARGE_CACHED,
true);
} else if (proc != null && !keepIfLarge
&& !mService.mAppProfiler.isLastMemoryLevelNormal()
- && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
+ && proc.mState.getSetProcState() >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
final long lastCachedPss;
boolean doKilling = false;
synchronized (mService.mAppProfiler.mProfilerLock) {
@@ -1582,7 +1599,7 @@ public final class ProcessList {
Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + lastCachedPss);
}
if (doKilling) {
- proc.kill(Long.toString(lastCachedPss) + "k from cached",
+ proc.killLocked(Long.toString(lastCachedPss) + "k from cached",
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_LARGE_CACHED,
true);
@@ -1604,14 +1621,16 @@ public final class ProcessList {
outInfo.foregroundAppThreshold = getMemLevel(FOREGROUND_APP_ADJ);
}
- ProcessRecord findAppProcessLocked(IBinder app, String reason) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ProcessRecord findAppProcessLOSP(IBinder app, String reason) {
final int NP = mProcessNames.getMap().size();
for (int ip = 0; ip < NP; ip++) {
SparseArray apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia = 0; ia < NA; ia++) {
ProcessRecord p = apps.valueAt(ia);
- if (p.thread != null && p.thread.asBinder() == app) {
+ final IApplicationThread thread = p.getThread();
+ if (thread != null && thread.asBinder() == app) {
return p;
}
}
@@ -1768,18 +1787,18 @@ public final class ProcessList {
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, String abiOverride) {
- if (app.pendingStart) {
+ if (app.isPendingStart()) {
return true;
}
long startTime = SystemClock.uptimeMillis();
- if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
+ if (app.getPid() > 0 && app.getPid() != ActivityManagerService.MY_PID) {
checkSlow(startTime, "startProcess: removing from pids map");
- mService.removePidLocked(app);
- app.bindMountPending = false;
+ mService.removePidLocked(app.getPid(), app);
+ app.setBindMountPending(false);
mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
checkSlow(startTime, "startProcess: done removing from pids map");
app.setPid(0);
- app.startSeq = 0;
+ app.setStartSeq(0);
}
if (DEBUG_PROCESSES && mService.mProcessesOnHold.contains(app)) Slog.v(
@@ -1834,7 +1853,7 @@ public final class ProcessList {
gids = computeGidsForProcess(mountExternal, uid, permGids);
}
- app.mountMode = mountExternal;
+ app.setMountMode(mountExternal);
checkSlow(startTime, "startProcess: building args");
if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
uid = 0;
@@ -1950,9 +1969,9 @@ public final class ProcessList {
instructionSet = VMRuntime.getInstructionSet(requiredAbi);
}
- app.gids = gids;
+ app.setGids(gids);
app.setRequiredAbi(requiredAbi);
- app.instructionSet = instructionSet;
+ app.setInstructionSet(instructionSet);
// If instructionSet is non-null, this indicates that the system_server is spawning a
// process with an ISA that may be different from its own. System (kernel and hardware)
@@ -2003,23 +2022,26 @@ public final class ProcessList {
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
- app.pendingStart = true;
- app.killedByAm = false;
- app.removed = false;
- app.killed = false;
- if (app.startSeq != 0) {
- Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
- + " with non-zero startSeq:" + app.startSeq);
+ app.setPendingStart(true);
+ app.setRemoved(false);
+ synchronized (mProcLock) {
+ app.setKilledByAm(false);
+ app.setKilled(false);
}
- if (app.pid != 0) {
+ if (app.getStartSeq() != 0) {
Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
- + " with non-zero pid:" + app.pid);
+ + " with non-zero startSeq:" + app.getStartSeq());
}
- app.mDisabledCompatChanges = null;
+ if (app.getPid() != 0) {
+ Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+ + " with non-zero pid:" + app.getPid());
+ }
+ app.setDisabledCompatChanges(null);
if (mPlatformCompat != null) {
- app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
+ app.setDisabledCompatChanges(mPlatformCompat.getDisabledChanges(app.info));
}
- final long startSeq = app.startSeq = ++mProcStartSeqCounter;
+ final long startSeq = ++mProcStartSeqCounter;
+ app.setStartSeq(startSeq);
app.setStartParams(uid, hostingRecord, seInfo, startTime);
app.setUsingWrapper(invokeWith != null
|| Zygote.getWrapProperty(app.processName) != null);
@@ -2043,11 +2065,11 @@ public final class ProcessList {
} catch (RuntimeException e) {
Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ app.processName, e);
- app.pendingStart = false;
+ app.setPendingStart(false);
mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
false, false, true, false, false, app.userId, "start failure");
}
- return app.pid > 0;
+ return app.getPid() > 0;
}
}
@@ -2060,11 +2082,11 @@ public final class ProcessList {
final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
final int mountExternal, final String requiredAbi, final String instructionSet,
final String invokeWith, final long startSeq) {
- // If there is a precede instance of the process, wait for its death with a timeout.
+ // If there is a preceding instance of the process, wait for its death with a timeout.
// Use local reference since we are not using locks here
- final ProcessRecord precedence = app.mPrecedence;
- if (precedence != null) {
- final int pid = precedence.pid;
+ final ProcessRecord predecessor = app.mPredecessor;
+ if (predecessor != null) {
+ final int pid = predecessor.getPid();
long now = System.currentTimeMillis();
final long end = now + PROC_KILL_TIMEOUT;
final int oldPolicy = StrictMode.getThreadPolicyMask();
@@ -2072,34 +2094,34 @@ public final class ProcessList {
StrictMode.setThreadPolicyMask(0);
Process.waitForProcessDeath(pid, PROC_KILL_TIMEOUT);
// It's killed successfully, but we'd make sure the cleanup work is done.
- synchronized (precedence) {
- if (app.mPrecedence != null) {
+ synchronized (predecessor) {
+ if (app.mPredecessor != null) {
now = System.currentTimeMillis();
if (now < end) {
try {
- precedence.wait(end - now);
+ predecessor.wait(end - now);
} catch (InterruptedException e) {
}
}
}
- if (app.mPrecedence != null) {
+ if (app.mPredecessor != null) {
// The cleanup work hasn't be done yet, let's log it and continue.
- Slog.w(TAG, precedence + " has died, but its cleanup isn't done");
+ Slog.w(TAG, predecessor + " has died, but its cleanup isn't done");
}
}
} catch (Exception e) {
// It's still alive... maybe blocked at uninterruptible sleep ?
- Slog.wtf(TAG, precedence.toString() + " refused to die, but we need to launch "
+ Slog.wtf(TAG, predecessor.toString() + " refused to die, but we need to launch "
+ app, e);
} finally {
StrictMode.setThreadPolicyMask(oldPolicy);
}
}
try {
- final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
- entryPoint, app, app.startUid, gids, runtimeFlags, zygotePolicyFlags,
- mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith,
- app.startTime);
+ final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
+ entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
+ mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
+ app.getStartTime());
synchronized (mService) {
handleProcessStartedLocked(app, startResult, startSeq);
@@ -2109,7 +2131,7 @@ public final class ProcessList {
Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ app.processName, e);
mPendingStarts.remove(startSeq);
- app.pendingStart = false;
+ app.setPendingStart(false);
mService.forceStopPackageLocked(app.info.packageName,
UserHandle.getAppId(app.uid),
false, false, true, false, false, app.userId, "start failure");
@@ -2135,19 +2157,19 @@ public final class ProcessList {
// Free the isolated uid for this process
final IsolatedUidRange appUidRange =
mAppIsolatedUidRangeAllocator.getIsolatedUidRangeLocked(app.info.processName,
- app.hostingRecord.getDefiningUid());
+ app.getHostingRecord().getDefiningUid());
if (appUidRange != null) {
appUidRange.freeIsolatedUidLocked(app.uid);
}
final AppZygote appZygote = mAppZygotes.get(app.info.processName,
- app.hostingRecord.getDefiningUid());
+ app.getHostingRecord().getDefiningUid());
if (appZygote != null) {
ArrayList zygoteProcesses = mAppZygoteProcesses.get(appZygote);
zygoteProcesses.remove(app);
if (zygoteProcesses.size() == 0) {
mService.mHandler.removeMessages(KILL_APP_ZYGOTE_MSG);
- if (app.removed) {
+ if (app.isRemoved()) {
// If we stopped this process because the package hosting it was removed,
// there's no point in delaying the app zygote kill.
killAppZygoteIfNeededLocked(appZygote, false /* force */);
@@ -2164,7 +2186,7 @@ public final class ProcessList {
synchronized (mService) {
// The UID for the app zygote should be the UID of the application hosting
// the service.
- final int uid = app.hostingRecord.getDefiningUid();
+ final int uid = app.getHostingRecord().getDefiningUid();
AppZygote appZygote = mAppZygotes.get(app.info.processName, uid);
final ArrayList zygoteProcessList;
if (appZygote == null) {
@@ -2173,7 +2195,7 @@ public final class ProcessList {
}
final IsolatedUidRange uidRange =
mAppIsolatedUidRangeAllocator.getIsolatedUidRangeLocked(
- app.info.processName, app.hostingRecord.getDefiningUid());
+ app.info.processName, app.getHostingRecord().getDefiningUid());
final int userId = UserHandle.getUserId(uid);
// Create the app-zygote and provide it with the UID-range it's allowed
// to setresuid/setresgid to.
@@ -2186,7 +2208,7 @@ public final class ProcessList {
// packageName and uid of the defining application. This is because the
// preloading only makes sense in the context of the defining application,
// not the calling one.
- appInfo.packageName = app.hostingRecord.getDefiningPackageName();
+ appInfo.packageName = app.getHostingRecord().getDefiningPackageName();
appInfo.uid = uid;
appZygote = new AppZygote(appInfo, uid, firstUid, lastUid);
mAppZygotes.put(app.info.processName, uid, appZygote);
@@ -2233,14 +2255,15 @@ public final class ProcessList {
private boolean needsStorageDataIsolation(StorageManagerInternal storageManagerInternal,
ProcessRecord app) {
+ final int mountMode = app.getMountMode();
return mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid)
&& !storageManagerInternal.isExternalStorageService(app.uid)
// Special mounting mode doesn't need to have data isolation as they won't
// access /mnt/user anyway.
- && app.mountMode != Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE
- && app.mountMode != Zygote.MOUNT_EXTERNAL_PASS_THROUGH
- && app.mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER
- && app.mountMode != Zygote.MOUNT_EXTERNAL_NONE;
+ && mountMode != Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE
+ && mountMode != Zygote.MOUNT_EXTERNAL_PASS_THROUGH
+ && mountMode != Zygote.MOUNT_EXTERNAL_INSTALLER
+ && mountMode != Zygote.MOUNT_EXTERNAL_NONE;
}
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
@@ -2256,7 +2279,7 @@ public final class ProcessList {
// Use has-foreground-activities as a temporary hint so the current scheduling
// group won't be lost when the process is attaching. The actual state will be
// refreshed when computing oom-adj.
- app.setHasForegroundActivities(true);
+ app.mState.setHasForegroundActivities(true);
}
Map> pkgDataInfoMap;
@@ -2306,7 +2329,7 @@ public final class ProcessList {
app.processName)) {
// Cannot prepare Android/app and Android/obb directory or inode == 0,
// so we won't mount it in zygote, but resume the mount after unlocking device.
- app.bindMountPending = true;
+ app.setBindMountPending(true);
bindMountAppStorageDirs = false;
}
}
@@ -2323,8 +2346,9 @@ public final class ProcessList {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
- new String[]{PROC_START_SEQ_IDENT + app.startSeq});
+ app.info.dataDir, null, app.info.packageName,
+ app.getDisabledCompatChanges(),
+ new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
@@ -2334,17 +2358,17 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
- app.mDisabledCompatChanges, pkgDataInfoMap, allowlistedAppDataInfoMap,
+ app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
false, false,
- new String[]{PROC_START_SEQ_IDENT + app.startSeq});
+ new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
- isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
+ isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
- new String[]{PROC_START_SEQ_IDENT + app.startSeq});
+ new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
@@ -2359,14 +2383,14 @@ public final class ProcessList {
}
@GuardedBy("mService")
- final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
+ boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, abiOverride);
}
@GuardedBy("mService")
- final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
+ ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
@@ -2399,7 +2423,7 @@ public final class ProcessList {
info.processName);
mService.mAppErrors.clearBadProcess(processName, info.uid);
if (app != null) {
- app.bad = false;
+ app.mErrorState.setBad(false);
}
}
}
@@ -2416,11 +2440,11 @@ public final class ProcessList {
// already running.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+ " app=" + app + " knownToBeDead=" + knownToBeDead
- + " thread=" + (app != null ? app.thread : null)
- + " pid=" + (app != null ? app.pid : -1));
- ProcessRecord precedence = null;
- if (app != null && app.pid > 0) {
- if ((!knownToBeDead && !app.killed) || app.thread == null) {
+ + " thread=" + (app != null ? app.getThread() : null)
+ + " pid=" + (app != null ? app.getPid() : -1));
+ ProcessRecord predecessor = null;
+ if (app != null && app.getPid() > 0) {
+ if ((!knownToBeDead && !app.isKilled()) || app.getThread() == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
@@ -2434,12 +2458,12 @@ public final class ProcessList {
// clean it up now.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
checkSlow(startTime, "startProcess: bad proc running, killing");
- ProcessList.killProcessGroup(app.uid, app.pid);
+ ProcessList.killProcessGroup(app.uid, app.getPid());
checkSlow(startTime, "startProcess: done killing old proc");
- if (!app.killed
+ if (!app.isKilled()
|| mService.mAppProfiler.isLastMemoryLevelNormal()
- || app.setProcState < ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ || app.mState.getSetProcState() < ActivityManager.PROCESS_STATE_CACHED_EMPTY
|| app.mProfile.getLastCachedPss() < getCachedRestoreThresholdKb()) {
// Throw a wtf if it's not killed, or killed but not because the system was in
// memory pressure + the app was in "cch-empty" and used large amount of memory
@@ -2448,8 +2472,8 @@ public final class ProcessList {
Slog.w(TAG_PROCESSES, app.toString() + " is attached to a previous process");
}
// We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup
- // routine of it yet, but we'd set it as the precedence of the new process.
- precedence = app;
+ // routine of it yet, but we'd set it as the predecessor of the new process.
+ predecessor = app;
app = null;
}
@@ -2461,12 +2485,12 @@ public final class ProcessList {
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
- app.crashHandler = crashHandler;
- app.isolatedEntryPoint = entryPoint;
- app.isolatedEntryPointArgs = entryPointArgs;
- if (precedence != null) {
- app.mPrecedence = precedence;
- precedence.mSuccessor = app;
+ app.mErrorState.setCrashHandler(crashHandler);
+ app.setIsolatedEntryPoint(entryPoint);
+ app.setIsolatedEntryPointArgs(entryPointArgs);
+ if (predecessor != null) {
+ app.mPredecessor = predecessor;
+ predecessor.mSuccessor = app;
}
checkSlow(startTime, "startProcess: done creating new process record");
} else {
@@ -2499,7 +2523,7 @@ public final class ProcessList {
@GuardedBy("mService")
private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
StringBuilder sb = null;
- if (app.killedByAm) {
+ if (app.isKilledByAm()) {
if (sb == null) sb = new StringBuilder();
sb.append("killedByAm=true;");
}
@@ -2507,13 +2531,13 @@ public final class ProcessList {
if (sb == null) sb = new StringBuilder();
sb.append("No entry in mProcessNames;");
}
- if (!app.pendingStart) {
+ if (!app.isPendingStart()) {
if (sb == null) sb = new StringBuilder();
sb.append("pendingStart=false;");
}
- if (app.startSeq > expectedStartSeq) {
+ if (app.getStartSeq() > expectedStartSeq) {
if (sb == null) sb = new StringBuilder();
- sb.append("seq=" + app.startSeq + ",expected=" + expectedStartSeq + ";");
+ sb.append("seq=" + app.getStartSeq() + ",expected=" + expectedStartSeq + ";");
}
try {
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, app.userId);
@@ -2536,7 +2560,7 @@ public final class ProcessList {
Process.ProcessStartResult startResult, long expectedStartSeq) {
// Indicates that this process start has been taken care of.
if (mPendingStarts.get(expectedStartSeq) == null) {
- if (pending.pid == startResult.pid) {
+ if (pending.getPid() == startResult.pid) {
pending.setUsingWrapper(startResult.usingWrapper);
// TODO: Update already existing clients of usingWrapper
}
@@ -2555,31 +2579,31 @@ public final class ProcessList {
Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" +
pid
+ ", " + reason);
- app.pendingStart = false;
+ app.setPendingStart(false);
killProcessQuiet(pid);
- Process.killProcessGroup(app.uid, app.pid);
+ Process.killProcessGroup(app.uid, app.getPid());
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_START, reason);
return false;
}
mService.mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
- checkSlow(app.startTime, "startProcess: done updating battery stats");
+ checkSlow(app.getStartTime(), "startProcess: done updating battery stats");
EventLog.writeEvent(EventLogTags.AM_PROC_START,
- UserHandle.getUserId(app.startUid), pid, app.startUid,
- app.processName, app.hostingRecord.getType(),
- app.hostingRecord.getName() != null ? app.hostingRecord.getName() : "");
+ UserHandle.getUserId(app.getStartUid()), pid, app.getStartUid(),
+ app.processName, app.getHostingRecord().getType(),
+ app.getHostingRecord().getName() != null ? app.getHostingRecord().getName() : "");
try {
AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.info.packageName,
- app.processName, app.uid, app.seInfo, app.info.sourceDir, pid);
+ app.processName, app.uid, app.getSeInfo(), app.info.sourceDir, pid);
} catch (RemoteException ex) {
// Ignore
}
Watchdog.getInstance().processStarted(app.processName, pid);
- checkSlow(app.startTime, "startProcess: building log message");
+ checkSlow(app.getStartTime(), "startProcess: building log message");
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
@@ -2587,23 +2611,25 @@ public final class ProcessList {
buf.append(':');
buf.append(app.processName);
buf.append('/');
- UserHandle.formatUid(buf, app.startUid);
- if (app.isolatedEntryPoint != null) {
+ UserHandle.formatUid(buf, app.getStartUid());
+ if (app.getIsolatedEntryPoint() != null) {
buf.append(" [");
- buf.append(app.isolatedEntryPoint);
+ buf.append(app.getIsolatedEntryPoint());
buf.append("]");
}
buf.append(" for ");
- buf.append(app.hostingRecord.getType());
- if (app.hostingRecord.getName() != null) {
+ buf.append(app.getHostingRecord().getType());
+ if (app.getHostingRecord().getName() != null) {
buf.append(" ");
- buf.append(app.hostingRecord.getName());
+ buf.append(app.getHostingRecord().getName());
}
- mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.startUid);
- app.setPid(pid);
- app.setUsingWrapper(usingWrapper);
- app.pendingStart = false;
- checkSlow(app.startTime, "startProcess: starting to update pids map");
+ mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.getStartUid());
+ synchronized (mProcLock) {
+ app.setPid(pid);
+ app.setUsingWrapper(usingWrapper);
+ app.setPendingStart(false);
+ }
+ checkSlow(app.getStartTime(), "startProcess: starting to update pids map");
ProcessRecord oldApp;
synchronized (mService.mPidsSelfLocked) {
oldApp = mService.mPidsSelfLocked.get(pid);
@@ -2612,11 +2638,11 @@ public final class ProcessList {
if (oldApp != null && !app.isolated) {
// Clean up anything relating to this pid first
Slog.wtf(TAG, "handleProcessStartedLocked process:" + app.processName
- + " startSeq:" + app.startSeq
+ + " startSeq:" + app.getStartSeq()
+ " pid:" + pid
+ " belongs to another existing app:" + oldApp.processName
- + " startSeq:" + oldApp.startSeq);
- mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+ + " startSeq:" + oldApp.getStartSeq());
+ mService.cleanUpApplicationRecordLocked(oldApp, pid, false, false, -1,
true /*replacingPid*/);
}
mService.addPidLocked(app);
@@ -2628,43 +2654,46 @@ public final class ProcessList {
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
- checkSlow(app.startTime, "startProcess: done updating pids map");
+ checkSlow(app.getStartTime(), "startProcess: done updating pids map");
return true;
}
- final void removeLruProcessLocked(ProcessRecord app) {
+ @GuardedBy("mService")
+ void removeLruProcessLocked(ProcessRecord app) {
int lrui = mLruProcesses.lastIndexOf(app);
if (lrui >= 0) {
- if (!app.killed) {
- if (app.isPersistent()) {
- Slog.w(TAG, "Removing persistent process that hasn't been killed: " + app);
- } else {
- Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
- if (app.pid > 0) {
- killProcessQuiet(app.pid);
- ProcessList.killProcessGroup(app.uid, app.pid);
- noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_REMOVE_LRU, "hasn't been killed");
+ synchronized (mProcLock) {
+ if (!app.isKilled()) {
+ if (app.isPersistent()) {
+ Slog.w(TAG, "Removing persistent process that hasn't been killed: " + app);
} else {
- app.pendingStart = false;
+ Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
+ if (app.getPid() > 0) {
+ killProcessQuiet(app.getPid());
+ ProcessList.killProcessGroup(app.uid, app.getPid());
+ noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_REMOVE_LRU, "hasn't been killed");
+ } else {
+ app.setPendingStart(false);
+ }
}
}
+ if (lrui < mLruProcessActivityStart) {
+ mLruProcessActivityStart--;
+ }
+ if (lrui < mLruProcessServiceStart) {
+ mLruProcessServiceStart--;
+ }
+ mLruProcesses.remove(lrui);
}
- if (lrui < mLruProcessActivityStart) {
- mLruProcessActivityStart--;
- }
- if (lrui < mLruProcessServiceStart) {
- mLruProcessServiceStart--;
- }
- mLruProcesses.remove(lrui);
- mService.removeOomAdjTargetLocked(app, true);
}
+ mService.removeOomAdjTargetLocked(app, true);
}
- @GuardedBy("mService")
- boolean killPackageProcessesLocked(String packageName, int appId, int userId, int minOomAdj,
+ @GuardedBy({"mService", "mProcLock"})
+ boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj,
int reasonCode, int subReason, String reason) {
- return killPackageProcessesLocked(packageName, appId, userId, minOomAdj,
+ return killPackageProcessesLSP(packageName, appId, userId, minOomAdj,
false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
false /* evenPersistent */, false /* setRemoved */, reasonCode,
subReason, reason);
@@ -2697,8 +2726,8 @@ public final class ProcessList {
}
}
- @GuardedBy("mService")
- final boolean killPackageProcessesLocked(String packageName, int appId,
+ @GuardedBy({"mService", "mProcLock"})
+ boolean killPackageProcessesLSP(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode,
int subReason, String reason) {
@@ -2717,7 +2746,7 @@ public final class ProcessList {
// we don't kill persistent processes
continue;
}
- if (app.removed) {
+ if (app.isRemoved()) {
if (doit) {
procs.add(app);
}
@@ -2725,7 +2754,7 @@ public final class ProcessList {
}
// Skip process if it doesn't meet our oom adj requirement.
- if (app.setAdj < minOomAdj) {
+ if (app.mState.getSetAdj() < minOomAdj) {
// Note it is still possible to have a process with oom adj 0 in the killed
// processes, but it does not mean misjudgment. E.g. a bound service process
// and its client activity process are both in the background, so they are
@@ -2747,8 +2776,8 @@ public final class ProcessList {
// that match it. We need to qualify this by the processes
// that are running under the specified app and user ID.
} else {
- final boolean isDep = app.pkgDeps != null
- && app.pkgDeps.contains(packageName);
+ final boolean isDep = app.getPkgDeps() != null
+ && app.getPkgDeps().contains(packageName);
if (!isDep && UserHandle.getAppId(app.uid) != appId) {
continue;
}
@@ -2765,7 +2794,7 @@ public final class ProcessList {
return true;
}
if (setRemoved) {
- app.removed = true;
+ app.setRemoved(true);
}
procs.add(app);
}
@@ -2806,12 +2835,12 @@ public final class ProcessList {
mService.mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
boolean needRestart = false;
- if ((app.pid > 0 && app.pid != ActivityManagerService.MY_PID) || (app.pid == 0 && app
- .pendingStart)) {
- int pid = app.pid;
+ final int pid = app.getPid();
+ if ((pid > 0 && pid != ActivityManagerService.MY_PID)
+ || (pid == 0 && app.isPendingStart())) {
if (pid > 0) {
- mService.removePidLocked(app);
- app.bindMountPending = false;
+ mService.removePidLocked(pid, app);
+ app.setBindMountPending(false);
mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
if (app.isolated) {
@@ -2827,8 +2856,8 @@ public final class ProcessList {
needRestart = true;
}
}
- app.kill(reason, reasonCode, subReason, true);
- mService.handleAppDiedLocked(app, willRestart, allowRestart);
+ app.killLocked(reason, reasonCode, subReason, true);
+ mService.handleAppDiedLocked(app, pid, willRestart, allowRestart);
if (willRestart) {
removeLruProcessLocked(app);
mService.addAppLocked(app.info, null, false, null /* ABI override */,
@@ -2842,48 +2871,51 @@ public final class ProcessList {
}
@GuardedBy("mService")
- final void addProcessNameLocked(ProcessRecord proc) {
+ void addProcessNameLocked(ProcessRecord proc) {
// We shouldn't already have a process under this name, but just in case we
// need to clean up whatever may be there now.
- ProcessRecord old = removeProcessNameLocked(proc.processName, proc.uid);
- if (old == proc && proc.isPersistent()) {
- // We are re-adding a persistent process. Whatevs! Just leave it there.
- Slog.w(TAG, "Re-adding persistent process " + proc);
- } else if (old != null) {
- if (old.killed) {
- // The old process has been killed, we probably haven't had
- // a chance to clean up the old record, just log a warning
- Slog.w(TAG, "Existing proc " + old + " was killed "
- + (SystemClock.uptimeMillis() - old.mKillTime)
- + "ms ago when adding " + proc);
- } else {
- Slog.wtf(TAG, "Already have existing proc " + old + " when adding " + proc);
+ synchronized (mProcLock) {
+ ProcessRecord old = removeProcessNameLocked(proc.processName, proc.uid);
+ if (old == proc && proc.isPersistent()) {
+ // We are re-adding a persistent process. Whatevs! Just leave it there.
+ Slog.w(TAG, "Re-adding persistent process " + proc);
+ } else if (old != null) {
+ if (old.isKilled()) {
+ // The old process has been killed, we probably haven't had
+ // a chance to clean up the old record, just log a warning
+ Slog.w(TAG, "Existing proc " + old + " was killed "
+ + (SystemClock.uptimeMillis() - old.getKillTime())
+ + "ms ago when adding " + proc);
+ } else {
+ Slog.wtf(TAG, "Already have existing proc " + old + " when adding " + proc);
+ }
}
- }
- UidRecord uidRec = mActiveUids.get(proc.uid);
- if (uidRec == null) {
- uidRec = new UidRecord(proc.uid);
- // This is the first appearance of the uid, report it now!
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "Creating new process uid: " + uidRec);
- if (Arrays.binarySearch(mService.mDeviceIdleTempAllowlist,
- UserHandle.getAppId(proc.uid)) >= 0
- || mService.mPendingTempAllowlist.indexOfKey(proc.uid) >= 0) {
- uidRec.mSetAllowlist = uidRec.mCurAllowlist = true;
+ UidRecord uidRec = mActiveUids.get(proc.uid);
+ if (uidRec == null) {
+ uidRec = new UidRecord(proc.uid, mService);
+ // This is the first appearance of the uid, report it now!
+ if (DEBUG_UID_OBSERVERS) {
+ Slog.i(TAG_UID_OBSERVERS, "Creating new process uid: " + uidRec);
+ }
+ if (Arrays.binarySearch(mService.mDeviceIdleTempAllowlist,
+ UserHandle.getAppId(proc.uid)) >= 0
+ || mService.mPendingTempAllowlist.indexOfKey(proc.uid) >= 0) {
+ uidRec.setCurAllowListed(true);
+ uidRec.setSetAllowListed(true);
+ }
+ uidRec.updateHasInternetPermission();
+ mActiveUids.put(proc.uid, uidRec);
+ EventLogTags.writeAmUidRunning(uidRec.getUid());
+ mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(),
+ uidRec.getCurCapability());
}
- uidRec.updateHasInternetPermission();
- mActiveUids.put(proc.uid, uidRec);
- EventLogTags.writeAmUidRunning(uidRec.uid);
- mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(),
- uidRec.curCapability);
- }
- proc.uidRecord = uidRec;
- uidRec.procRecords.add(proc);
+ proc.setUidRecord(uidRec);
+ uidRec.addProcess(proc);
- // Reset render thread tid if it was already set, so new process can set it again.
- proc.renderThreadTid = 0;
- uidRec.numProcs++;
- mProcessNames.put(proc.processName, proc.uid, proc);
+ // Reset render thread tid if it was already set, so new process can set it again.
+ proc.setRenderThreadTid(0);
+ mProcessNames.put(proc.processName, proc.uid, proc);
+ }
if (proc.isolated) {
mIsolatedProcesses.put(proc.uid, proc);
}
@@ -2902,7 +2934,7 @@ public final class ProcessList {
}
@GuardedBy("mService")
- final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
+ ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid, HostingRecord hostingRecord) {
String proc = customProcess != null ? customProcess : info.processName;
final int userId = UserHandle.getUserId(info.uid);
@@ -2936,58 +2968,63 @@ public final class ProcessList {
FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
}
final ProcessRecord r = new ProcessRecord(mService, info, proc, uid);
+ final ProcessStateRecord state = r.mState;
if (!mService.mBooted && !mService.mBooting
&& userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
- r.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
- r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
+ state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
r.setPersistent(true);
- r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
+ state.setMaxAdj(ProcessList.PERSISTENT_PROC_ADJ);
}
if (isolated && isolatedUid != 0) {
// Special case for startIsolatedProcess (internal only) - assume the process
// is required by the system server to prevent it being killed.
- r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
+ state.setMaxAdj(ProcessList.PERSISTENT_SERVICE_ADJ);
}
addProcessNameLocked(r);
return r;
}
@GuardedBy("mService")
- final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
+ ProcessRecord removeProcessNameLocked(final String name, final int uid) {
return removeProcessNameLocked(name, uid, null);
}
@GuardedBy("mService")
- final ProcessRecord removeProcessNameLocked(final String name, final int uid,
+ ProcessRecord removeProcessNameLocked(final String name, final int uid,
final ProcessRecord expecting) {
ProcessRecord old = mProcessNames.get(name, uid);
- // Only actually remove when the currently recorded value matches the
- // record that we expected; if it doesn't match then we raced with a
- // newly created process and we don't want to destroy the new one.
- if ((expecting == null) || (old == expecting)) {
- mProcessNames.remove(name, uid);
- }
final ProcessRecord record = expecting != null ? expecting : old;
- if (record != null && record.uidRecord != null) {
- final UidRecord uidRecord = record.uidRecord;
- uidRecord.numProcs--;
- uidRecord.procRecords.remove(record);
- if (uidRecord.numProcs == 0) {
- // No more processes using this uid, tell clients it is gone.
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "No more processes in " + uidRecord);
- mService.enqueueUidChangeLocked(uidRecord, -1,
- UidRecord.CHANGE_GONE);
- EventLogTags.writeAmUidStopped(uid);
- mActiveUids.remove(uid);
- mService.mFgsStartTempAllowList.remove(record.info.uid);
- mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT,
- ActivityManager.PROCESS_CAPABILITY_NONE);
+ synchronized (mProcLock) {
+ // Only actually remove when the currently recorded value matches the
+ // record that we expected; if it doesn't match then we raced with a
+ // newly created process and we don't want to destroy the new one.
+ if ((expecting == null) || (old == expecting)) {
+ mProcessNames.remove(name, uid);
+ }
+ if (record != null) {
+ final UidRecord uidRecord = record.getUidRecord();
+ if (uidRecord != null) {
+ uidRecord.removeProcess(record);
+ if (uidRecord.getNumOfProcs() == 0) {
+ // No more processes using this uid, tell clients it is gone.
+ if (DEBUG_UID_OBSERVERS) {
+ Slog.i(TAG_UID_OBSERVERS, "No more processes in " + uidRecord);
+ }
+ mService.enqueueUidChangeLocked(uidRecord, -1,
+ UidRecord.CHANGE_GONE);
+ EventLogTags.writeAmUidStopped(uid);
+ mActiveUids.remove(uid);
+ mService.mFgsStartTempAllowList.remove(record.info.uid);
+ mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
+ }
+ record.setUidRecord(null);
+ }
}
- record.uidRecord = null;
}
mIsolatedProcesses.remove(uid);
mGlobalIsolatedUids.freeIsolatedUidLocked(uid);
@@ -3000,13 +3037,14 @@ public final class ProcessList {
}
/** Call setCoreSettings on all LRU processes, with the new settings. */
- @GuardedBy("mService")
- void updateCoreSettingsLocked(Bundle settings) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void updateCoreSettingsLOSP(Bundle settings) {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord processRecord = mLruProcesses.get(i);
+ final IApplicationThread thread = processRecord.getThread();
try {
- if (processRecord.thread != null) {
- processRecord.thread.setCoreSettings(settings);
+ if (thread != null) {
+ thread.setCoreSettings(settings);
}
} catch (RemoteException re) {
/* ignore */
@@ -3020,8 +3058,8 @@ public final class ProcessList {
* @param minTargetSdk
* @param maxProcState
*/
- @GuardedBy("mService")
- void killAllBackgroundProcessesExceptLocked(int minTargetSdk, int maxProcState) {
+ @GuardedBy({"mService", "mProcLock"})
+ void killAllBackgroundProcessesExceptLSP(int minTargetSdk, int maxProcState) {
final ArrayList procs = new ArrayList<>();
final int NP = mProcessNames.getMap().size();
for (int ip = 0; ip < NP; ip++) {
@@ -3029,8 +3067,9 @@ public final class ProcessList {
final int NA = apps.size();
for (int ia = 0; ia < NA; ia++) {
final ProcessRecord app = apps.valueAt(ia);
- if (app.removed || ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
- && (maxProcState < 0 || app.setProcState > maxProcState))) {
+ if (app.isRemoved()
+ || ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
+ && (maxProcState < 0 || app.mState.getSetProcState() > maxProcState))) {
procs.add(app);
}
}
@@ -3047,13 +3086,14 @@ public final class ProcessList {
* Call updateTimePrefs on all LRU processes
* @param timePref The time pref to pass to each process
*/
- @GuardedBy("mService")
- void updateAllTimePrefsLocked(int timePref) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void updateAllTimePrefsLOSP(int timePref) {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
try {
- r.thread.updateTimePrefs(timePref);
+ thread.updateTimePrefs(timePref);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to update preferences for: "
+ r.info.processName);
@@ -3064,15 +3104,16 @@ public final class ProcessList {
void setAllHttpProxy() {
// Update the HTTP proxy for each application thread.
- synchronized (mService) {
+ synchronized (mProcLock) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = mLruProcesses.get(i);
+ IApplicationThread thread = r.getThread();
// Don't dispatch to isolated processes as they can't access ConnectivityManager and
// don't have network privileges anyway. Exclude system server and update it
// separately outside the AMS lock, to avoid deadlock with Connectivity Service.
- if (r.pid != ActivityManagerService.MY_PID && r.thread != null && !r.isolated) {
+ if (r.getPid() != ActivityManagerService.MY_PID && thread != null && !r.isolated) {
try {
- r.thread.updateHttpProxy();
+ thread.updateHttpProxy();
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to update http proxy for: "
+ r.info.processName);
@@ -3083,13 +3124,14 @@ public final class ProcessList {
ActivityThread.updateHttpProxy(mService.mContext);
}
- @GuardedBy("mService")
- void clearAllDnsCacheLocked() {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void clearAllDnsCacheLOSP() {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
try {
- r.thread.clearDnsCache();
+ thread.clearDnsCache();
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
}
@@ -3097,13 +3139,14 @@ public final class ProcessList {
}
}
- @GuardedBy("mService")
- void handleAllTrustStorageUpdateLocked() {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void handleAllTrustStorageUpdateLOSP() {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
+ final IApplicationThread thread = r.getThread();
+ if (thread != null) {
try {
- r.thread.handleTrustStorageUpdate();
+ thread.handleTrustStorageUpdate();
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to handle trust storage update for: " +
r.info.processName);
@@ -3112,10 +3155,10 @@ public final class ProcessList {
}
}
- @GuardedBy("mService")
- int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
+ @GuardedBy({"mService", "mProcLock"})
+ private int updateLruProcessInternalLSP(ProcessRecord app, long now, int index,
int lruSeq, String what, Object obj, ProcessRecord srcApp) {
- app.lastActivityTime = now;
+ app.setLastActivityTime(now);
if (app.hasActivitiesOrRecentTasks()) {
// Don't want to touch dependent processes that are hosting activities.
@@ -3147,7 +3190,7 @@ public final class ProcessList {
if (DEBUG_LRU) Slog.d(TAG_LRU, "Moving dep from " + lrui + " to " + index
+ " in LRU list: " + app);
mLruProcesses.add(index, app);
- app.lruSeq = lruSeq;
+ app.setLruSeq(lruSeq);
return index;
}
@@ -3167,45 +3210,51 @@ public final class ProcessList {
* @param endIndex The current end of the top being processed. Typically topI - 1. That is,
* where we are going to start potentially adjusting other entries in the list.
*/
- private void updateClientActivitiesOrdering(final ProcessRecord topApp, final int topI,
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateClientActivitiesOrderingLSP(final ProcessRecord topApp, final int topI,
final int bottomI, int endIndex) {
- if (topApp.hasActivitiesOrRecentTasks() || topApp.treatLikeActivity
- || !topApp.hasClientActivities()) {
+ final ProcessServiceRecord topPsr = topApp.mServices;
+ if (topApp.hasActivitiesOrRecentTasks() || topPsr.isTreatedLikeActivity()
+ || !topPsr.hasClientActivities()) {
// If this is not a special process that has client activities, then there is
// nothing to do.
return;
}
final int uid = topApp.info.uid;
- if (topApp.connectionGroup > 0) {
- int endImportance = topApp.connectionImportance;
+ final int topConnectionGroup = topPsr.getConnectionGroup();
+ if (topConnectionGroup > 0) {
+ int endImportance = topPsr.getConnectionImportance();
for (int i = endIndex; i >= bottomI; i--) {
final ProcessRecord subProc = mLruProcesses.get(i);
+ final ProcessServiceRecord subPsr = subProc.mServices;
+ final int subConnectionGroup = subPsr.getConnectionGroup();
+ final int subConnectionImportance = subPsr.getConnectionImportance();
if (subProc.info.uid == uid
- && subProc.connectionGroup == topApp.connectionGroup) {
- if (i == endIndex && subProc.connectionImportance >= endImportance) {
+ && subConnectionGroup == topConnectionGroup) {
+ if (i == endIndex && subConnectionImportance >= endImportance) {
// This process is already in the group, and its importance
// is not as strong as the process before it, so keep it
// correctly positioned in the group.
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Keeping in-place above " + subProc
+ " endImportance=" + endImportance
- + " group=" + subProc.connectionGroup
- + " importance=" + subProc.connectionImportance);
+ + " group=" + subConnectionGroup
+ + " importance=" + subConnectionImportance);
endIndex--;
- endImportance = subProc.connectionImportance;
+ endImportance = subConnectionImportance;
} else {
// We want to pull this up to be with the rest of the group,
// and order within the group by importance.
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Pulling up " + subProc
+ " to position in group with importance="
- + subProc.connectionImportance);
+ + subConnectionImportance);
boolean moved = false;
for (int pos = topI; pos > endIndex; pos--) {
final ProcessRecord posProc = mLruProcesses.get(pos);
- if (subProc.connectionImportance
- <= posProc.connectionImportance) {
+ if (subConnectionImportance
+ <= posProc.mServices.getConnectionImportance()) {
mLruProcesses.remove(i);
mLruProcesses.add(pos, subProc);
if (DEBUG_LRU) Slog.d(TAG_LRU,
@@ -3226,7 +3275,7 @@ public final class ProcessList {
+ " from position " + i + " to end of group @ "
+ endIndex);
endIndex--;
- endImportance = subProc.connectionImportance;
+ endImportance = subConnectionImportance;
}
}
}
@@ -3238,6 +3287,8 @@ public final class ProcessList {
int i = endIndex;
while (i >= bottomI) {
ProcessRecord subProc = mLruProcesses.get(i);
+ final ProcessServiceRecord subPsr = subProc.mServices;
+ final int subConnectionGroup = subPsr.getConnectionGroup();
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Looking to spread old procs, at " + subProc + " @ " + i);
if (subProc.info.uid != uid) {
@@ -3260,7 +3311,8 @@ public final class ProcessList {
subProc = mLruProcesses.get(i);
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Looking at next app at " + i + ": " + subProc);
- if (subProc.hasActivitiesOrRecentTasks() || subProc.treatLikeActivity) {
+ if (subProc.hasActivitiesOrRecentTasks()
+ || subPsr.isTreatedLikeActivity()) {
if (DEBUG_LRU) Slog.d(TAG_LRU,
"This is hosting an activity!");
if (hasActivity) {
@@ -3270,7 +3322,7 @@ public final class ProcessList {
break;
}
hasActivity = true;
- } else if (subProc.hasClientActivities()) {
+ } else if (subPsr.hasClientActivities()) {
if (DEBUG_LRU) Slog.d(TAG_LRU,
"This is a client of an activity");
if (hasActivity) {
@@ -3281,21 +3333,21 @@ public final class ProcessList {
"Already found a different activity: connUid="
+ connUid + " uid=" + subProc.info.uid);
break;
- } else if (connGroup == 0 || connGroup != subProc.connectionGroup) {
+ } else if (connGroup == 0 || connGroup != subConnectionGroup) {
// Previously saw a different group or not from a group,
// want to treat these as different things.
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Already found a different group: connGroup="
- + connGroup + " group=" + subProc.connectionGroup);
+ + connGroup + " group=" + subConnectionGroup);
break;
}
} else {
if (DEBUG_LRU) Slog.d(TAG_LRU,
"This is an activity client! uid="
- + subProc.info.uid + " group=" + subProc.connectionGroup);
+ + subProc.info.uid + " group=" + subConnectionGroup);
hasActivity = true;
connUid = subProc.info.uid;
- connGroup = subProc.connectionGroup;
+ connGroup = subConnectionGroup;
}
}
endIndex--;
@@ -3316,13 +3368,16 @@ public final class ProcessList {
}
if (endIndex >= bottomI) {
final ProcessRecord endProc = mLruProcesses.get(endIndex);
+ final ProcessServiceRecord endPsr = endProc.mServices;
+ final int endConnectionGroup = endPsr.getConnectionGroup();
for (endIndex--; endIndex >= bottomI; endIndex--) {
final ProcessRecord nextEndProc = mLruProcesses.get(endIndex);
+ final int nextConnectionGroup = nextEndProc.mServices.getConnectionGroup();
if (nextEndProc.info.uid != uid
- || nextEndProc.connectionGroup != endProc.connectionGroup) {
+ || nextConnectionGroup != endConnectionGroup) {
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Found next group or app: " + nextEndProc + " @ "
- + endIndex + " group=" + nextEndProc.connectionGroup);
+ + endIndex + " group=" + nextConnectionGroup);
break;
}
}
@@ -3336,10 +3391,11 @@ public final class ProcessList {
}
}
- final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
- ProcessRecord client) {
- final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities()
- || app.treatLikeActivity;
+ @GuardedBy("mService")
+ void updateLruProcessLocked(ProcessRecord app, boolean activityChange, ProcessRecord client) {
+ final ProcessServiceRecord psr = app.mServices;
+ final boolean hasActivity = app.hasActivitiesOrRecentTasks() || psr.hasClientActivities()
+ || psr.isTreatedLikeActivity();
final boolean hasService = false; // not impl yet. app.services.size() > 0;
if (!activityChange && hasActivity) {
// The process has activities, so we are only allowing activity-based adjustments
@@ -3349,9 +3405,18 @@ public final class ProcessList {
return;
}
+ synchronized (mProcLock) {
+ updateLruProcessLSP(app, client, hasActivity, hasService);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private void updateLruProcessLSP(ProcessRecord app, ProcessRecord client,
+ boolean hasActivity, boolean hasService) {
mLruSeq++;
final long now = SystemClock.uptimeMillis();
- app.lastActivityTime = now;
+ final ProcessServiceRecord psr = app.mServices;
+ app.setLastActivityTime(now);
// First a quick reject: if the app is already at the position we will
// put it, then there is nothing to do.
@@ -3445,14 +3510,14 @@ public final class ProcessList {
if (hasActivity) {
final int N = mLruProcesses.size();
nextIndex = mLruProcessServiceStart;
- if (!app.hasActivitiesOrRecentTasks() && !app.treatLikeActivity
+ if (!app.hasActivitiesOrRecentTasks() && !psr.isTreatedLikeActivity()
&& mLruProcessActivityStart < (N - 1)) {
// Process doesn't have activities, but has clients with
// activities... move it up, but below the app that is binding to it.
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Adding to second-top of LRU activity list: " + app
- + " group=" + app.connectionGroup
- + " importance=" + app.connectionImportance);
+ + " group=" + psr.getConnectionGroup()
+ + " importance=" + psr.getConnectionImportance());
int pos = N - 1;
while (pos > mLruProcessActivityStart) {
final ProcessRecord posproc = mLruProcesses.get(pos);
@@ -3472,7 +3537,7 @@ public final class ProcessList {
endIndex = mLruProcessActivityStart;
}
nextActivityIndex = endIndex;
- updateClientActivitiesOrdering(app, pos, mLruProcessActivityStart, endIndex);
+ updateClientActivitiesOrderingLSP(app, pos, mLruProcessActivityStart, endIndex);
} else {
// Process has activities, put it at the very tipsy-top.
if (DEBUG_LRU) Slog.d(TAG_LRU, "Adding to top of LRU activity list: " + app);
@@ -3509,46 +3574,48 @@ public final class ProcessList {
mLruProcessActivityStart++;
mLruProcessServiceStart++;
if (index > 1) {
- updateClientActivitiesOrdering(app, mLruProcessServiceStart - 1, 0, index - 1);
+ updateClientActivitiesOrderingLSP(app, mLruProcessServiceStart - 1, 0, index - 1);
}
}
- app.lruSeq = mLruSeq;
+ app.setLruSeq(mLruSeq);
// If the app is currently using a content provider or service,
// bump those processes as well.
- for (int j = app.connections.size() - 1; j >= 0; j--) {
- ConnectionRecord cr = app.connections.valueAt(j);
+ for (int j = psr.numberOfConnections() - 1; j >= 0; j--) {
+ ConnectionRecord cr = psr.getConnectionAt(j);
if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
&& cr.binding.service.app != null
- && cr.binding.service.app.lruSeq != mLruSeq
+ && cr.binding.service.app.getLruSeq() != mLruSeq
&& (cr.flags & Context.BIND_REDUCTION_FLAGS) == 0
&& !cr.binding.service.app.isPersistent()) {
- if (cr.binding.service.app.hasClientActivities()) {
+ if (cr.binding.service.app.mServices.hasClientActivities()) {
if (nextActivityIndex >= 0) {
- nextActivityIndex = updateLruProcessInternalLocked(cr.binding.service.app,
+ nextActivityIndex = updateLruProcessInternalLSP(cr.binding.service.app,
now,
nextActivityIndex, mLruSeq,
"service connection", cr, app);
}
} else {
- nextIndex = updateLruProcessInternalLocked(cr.binding.service.app,
+ nextIndex = updateLruProcessInternalLSP(cr.binding.service.app,
now,
nextIndex, mLruSeq,
"service connection", cr, app);
}
}
}
- for (int j = app.conProviders.size() - 1; j >= 0; j--) {
- ContentProviderRecord cpr = app.conProviders.get(j).provider;
- if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.isPersistent()) {
- nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex, mLruSeq,
+ final ProcessProviderRecord ppr = app.mProviders;
+ for (int j = ppr.numberOfProviderConnections() - 1; j >= 0; j--) {
+ ContentProviderRecord cpr = ppr.getProviderConnectionAt(j).provider;
+ if (cpr.proc != null && cpr.proc.getLruSeq() != mLruSeq && !cpr.proc.isPersistent()) {
+ nextIndex = updateLruProcessInternalLSP(cpr.proc, now, nextIndex, mLruSeq,
"provider reference", cpr, app);
}
}
}
- final ProcessRecord getLRURecordForAppLocked(IApplicationThread thread) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ProcessRecord getLRURecordForAppLOSP(IApplicationThread thread) {
if (thread == null) {
return null;
}
@@ -3556,18 +3623,20 @@ public final class ProcessList {
// Find the application record.
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
+ final IApplicationThread t = rec.getThread();
+ if (t != null && t.asBinder() == threadBinder) {
return rec;
}
}
return null;
}
- boolean haveBackgroundProcessLocked() {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean haveBackgroundProcessLOSP() {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null
- && rec.setProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
+ if (rec.getThread() != null
+ && rec.mState.getSetProcState() >= PROCESS_STATE_CACHED_ACTIVITY) {
return true;
}
}
@@ -3587,11 +3656,11 @@ public final class ProcessList {
return imp;
}
- @GuardedBy("mService")
- void fillInProcMemInfoLocked(ProcessRecord app,
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void fillInProcMemInfoLOSP(ProcessRecord app,
ActivityManager.RunningAppProcessInfo outInfo,
int clientTargetSdk) {
- outInfo.pid = app.pid;
+ outInfo.pid = app.getPid();
outInfo.uid = app.info.uid;
if (app.getWindowProcessController().isHeavyWeightProcess()) {
outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
@@ -3603,49 +3672,53 @@ public final class ProcessList {
outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
}
outInfo.lastTrimLevel = app.mProfile.getTrimMemoryLevel();
- int adj = app.curAdj;
- int procState = app.getCurProcState();
+ final ProcessStateRecord state = app.mState;
+ int adj = state.getCurAdj();
+ int procState = state.getCurProcState();
outInfo.importance = procStateToImportance(procState, adj, outInfo,
clientTargetSdk);
- outInfo.importanceReasonCode = app.adjTypeCode;
- outInfo.processState = app.getCurProcState();
+ outInfo.importanceReasonCode = state.getAdjTypeCode();
+ outInfo.processState = procState;
outInfo.isFocused = (app == mService.getTopApp());
- outInfo.lastActivityTime = app.lastActivityTime;
+ outInfo.lastActivityTime = app.getLastActivityTime();
}
- @GuardedBy("mService")
- List getRunningAppProcessesLocked(boolean allUsers,
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ List getRunningAppProcessesLOSP(boolean allUsers,
int userId, boolean allUids, int callingUid, int clientTargetSdk) {
// Lazy instantiation of list
List runList = null;
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord app = mLruProcesses.get(i);
+ final ProcessStateRecord state = app.mState;
+ final ProcessErrorStateRecord errState = app.mErrorState;
if ((!allUsers && app.userId != userId)
|| (!allUids && app.uid != callingUid)) {
continue;
}
- if ((app.thread != null) && (!app.isCrashing() && !app.isNotResponding())) {
+ if ((app.getThread() != null)
+ && (!errState.isCrashing() && !errState.isNotResponding())) {
// Generate process state info for running application
ActivityManager.RunningAppProcessInfo currApp =
new ActivityManager.RunningAppProcessInfo(app.processName,
- app.pid, app.getPackageList());
- fillInProcMemInfoLocked(app, currApp, clientTargetSdk);
- if (app.adjSource instanceof ProcessRecord) {
- currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+ app.getPid(), app.getPackageList());
+ fillInProcMemInfoLOSP(app, currApp, clientTargetSdk);
+ if (state.getAdjSource() instanceof ProcessRecord) {
+ currApp.importanceReasonPid = ((ProcessRecord) state.getAdjSource()).getPid();
currApp.importanceReasonImportance =
ActivityManager.RunningAppProcessInfo.procStateToImportance(
- app.adjSourceProcState);
- } else if (app.adjSource instanceof ActivityServiceConnectionsHolder) {
+ state.getAdjSourceProcState());
+ } else if (state.getAdjSource() instanceof ActivityServiceConnectionsHolder) {
final ActivityServiceConnectionsHolder r =
- (ActivityServiceConnectionsHolder) app.adjSource;
+ (ActivityServiceConnectionsHolder) state.getAdjSource();
final int pid = r.getActivityPid();
if (pid != -1) {
currApp.importanceReasonPid = pid;
}
}
- if (app.adjTarget instanceof ComponentName) {
- currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
+ if (state.getAdjTarget() instanceof ComponentName) {
+ currApp.importanceReasonComponent = (ComponentName) state.getAdjTarget();
}
//Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
// + " lru=" + currApp.lru);
@@ -3658,11 +3731,110 @@ public final class ProcessList {
return runList;
}
- @GuardedBy("mService")
- int getLruSizeLocked() {
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ int getLruSizeLOSP() {
return mLruProcesses.size();
}
+ /**
+ * Return the reference to the LRU list, call this function for read-only access
+ */
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ ArrayList getLruProcessesLOSP() {
+ return mLruProcesses;
+ }
+
+ /**
+ * Return the reference to the LRU list, call this function for read/write access
+ */
+ @GuardedBy({"mService", "mProfileLock"})
+ ArrayList getLruProcessesLSP() {
+ return mLruProcesses;
+ }
+
+ /**
+ * For test only
+ */
+ @VisibleForTesting
+ @GuardedBy({"mService", "mProfileLock"})
+ void setLruProcessServiceStartLSP(int pos) {
+ mLruProcessServiceStart = pos;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ int getLruProcessServiceStartLOSP() {
+ return mLruProcessServiceStart;
+ }
+
+ /**
+ * Iterate the whole LRU list, invoke the given {@code callback} with each of the ProcessRecord
+ * in that list.
+ *
+ * @param iterateForward If {@code true}, iterate the LRU list from the least recent used
+ * to most recent used ProcessRecord.
+ * @param callback The callback interface to accept the current ProcessRecord.
+ */
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ void forEachLruProcessesLOSP(boolean iterateForward,
+ @NonNull Consumer callback) {
+ if (iterateForward) {
+ for (int i = 0, size = mLruProcesses.size(); i < size; i++) {
+ callback.accept(mLruProcesses.get(i));
+ }
+ } else {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ callback.accept(mLruProcesses.get(i));
+ }
+ }
+ }
+
+ /**
+ * Search in the LRU list, invoke the given {@code callback} with each of the ProcessRecord
+ * in that list; if the callback returns a non-null object, halt the search, return that
+ * object as the return value of this search function.
+ *
+ * @param iterateForward If {@code true}, iterate the LRU list from the least recent used
+ * to most recent used ProcessRecord.
+ * @param callback The callback interface to accept the current ProcessRecord; if it returns
+ * a non-null object, the search will be halted and this object will be used
+ * as the return value of this search function.
+ */
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ R searchEachLruProcessesLOSP(boolean iterateForward,
+ @NonNull Function callback) {
+ if (iterateForward) {
+ for (int i = 0, size = mLruProcesses.size(); i < size; i++) {
+ R r;
+ if ((r = callback.apply(mLruProcesses.get(i))) != null) {
+ return r;
+ }
+ }
+ } else {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ R r;
+ if ((r = callback.apply(mLruProcesses.get(i))) != null) {
+ return r;
+ }
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ boolean isInLruListLOSP(ProcessRecord app) {
+ return mLruProcesses.contains(app);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ int getLruSeqLOSP() {
+ return mLruSeq;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProfileLock"})
+ MyProcessMap getProcessNamesLOSP() {
+ return mProcessNames;
+ }
+
@GuardedBy("mService")
void dumpLruListHeaderLocked(PrintWriter pw) {
pw.print(" Process LRU list (sorted by oom_adj, "); pw.print(mLruProcesses.size());
@@ -3673,7 +3845,8 @@ public final class ProcessList {
pw.println("):");
}
- void dumpLruEntryLocked(PrintWriter pw, int index, ProcessRecord proc, String prefix) {
+ @GuardedBy("mService")
+ private void dumpLruEntryLocked(PrintWriter pw, int index, ProcessRecord proc, String prefix) {
pw.print(prefix);
pw.print('#');
if (index < 10) {
@@ -3681,15 +3854,16 @@ public final class ProcessList {
}
pw.print(index);
pw.print(": ");
- pw.print(makeOomAdjString(proc.setAdj, false));
+ pw.print(makeOomAdjString(proc.mState.getSetAdj(), false));
pw.print(' ');
- pw.print(makeProcStateString(proc.getCurProcState()));
+ pw.print(makeProcStateString(proc.mState.getCurProcState()));
pw.print(' ');
- ActivityManager.printCapabilitiesSummary(pw, proc.curCapability);
+ ActivityManager.printCapabilitiesSummary(pw, proc.mState.getCurCapability());
pw.print(' ');
pw.print(proc.toShortString());
- if (proc.hasActivitiesOrRecentTasks() || proc.hasClientActivities()
- || proc.treatLikeActivity) {
+ final ProcessServiceRecord psr = proc.mServices;
+ if (proc.hasActivitiesOrRecentTasks() || psr.hasClientActivities()
+ || psr.isTreatedLikeActivity()) {
pw.print(" act:");
boolean printed = false;
if (proc.hasActivities()) {
@@ -3703,14 +3877,14 @@ public final class ProcessList {
pw.print("recents");
printed = true;
}
- if (proc.hasClientActivities()) {
+ if (psr.hasClientActivities()) {
if (printed) {
pw.print("|");
}
pw.print("client");
printed = true;
}
- if (proc.treatLikeActivity) {
+ if (psr.isTreatedLikeActivity()) {
if (printed) {
pw.print("|");
}
@@ -3720,6 +3894,7 @@ public final class ProcessList {
pw.println();
}
+ @GuardedBy("mService")
boolean dumpLruLocked(PrintWriter pw, String dumpPackage, String prefix) {
final int lruSize = mLruProcesses.size();
final String innerPrefix;
@@ -3786,8 +3961,8 @@ public final class ProcessList {
return true;
}
- @GuardedBy("mService")
- void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ @GuardedBy({"mService", "mProcLock"})
+ void dumpProcessesLSP(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage, int dumpAppId) {
boolean needSep = false;
int numPers = 0;
@@ -3861,7 +4036,7 @@ public final class ProcessList {
needSep = true;
}
- if (getLruSizeLocked() > 0) {
+ if (getLruSizeLOSP() > 0) {
if (needSep) {
pw.println();
}
@@ -3871,12 +4046,12 @@ public final class ProcessList {
needSep = true;
}
- mService.dumpOtherProcessesInfoLocked(fd, pw, dumpAll, dumpPackage, dumpAppId, numPers,
+ mService.dumpOtherProcessesInfoLSP(fd, pw, dumpAll, dumpPackage, dumpAppId, numPers,
needSep);
}
- @GuardedBy("this")
- void writeProcessesToProtoLocked(ProtoOutputStream proto, String dumpPackage) {
+ @GuardedBy({"mService", "mProcLock"})
+ void writeProcessesToProtoLSP(ProtoOutputStream proto, String dumpPackage) {
int numPers = 0;
final int numOfNames = mProcessNames.getMap().size();
@@ -3910,9 +4085,9 @@ public final class ProcessList {
mActiveUids.dumpProto(proto, dumpPackage, dumpAppId,
ActivityManagerServiceDumpProcessesProto.ACTIVE_UIDS);
- if (getLruSizeLocked() > 0) {
+ if (getLruSizeLOSP() > 0) {
long lruToken = proto.start(ActivityManagerServiceDumpProcessesProto.LRU_PROCS);
- int total = getLruSizeLocked();
+ int total = getLruSizeLOSP();
proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.SIZE, total);
proto.write(ActivityManagerServiceDumpProcessesProto.LruProcesses.NON_ACT_AT,
total - mLruProcessActivityStart);
@@ -3924,7 +4099,7 @@ public final class ProcessList {
proto.end(lruToken);
}
- mService.writeOtherProcessesInfoToProtoLocked(proto, dumpPackage, dumpAppId, numPers);
+ mService.writeOtherProcessesInfoToProtoLSP(proto, dumpPackage, dumpAppId, numPers);
}
private static ArrayList> sortProcessOomList(
@@ -3944,14 +4119,18 @@ public final class ProcessList {
@Override
public int compare(Pair object1,
Pair object2) {
- if (object1.first.setAdj != object2.first.setAdj) {
- return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
+ final int adj = object2.first.mState.getSetAdj() - object1.first.mState.getSetAdj();
+ if (adj != 0) {
+ return adj;
}
- if (object1.first.setProcState != object2.first.setProcState) {
- return object1.first.setProcState > object2.first.setProcState ? -1 : 1;
+ final int procState = object2.first.mState.getSetProcState()
+ - object1.first.mState.getSetProcState();
+ if (procState != 0) {
+ return procState;
}
- if (object1.second.intValue() != object2.second.intValue()) {
- return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
+ final int val = object2.second - object1.second;
+ if (val != 0) {
+ return val;
}
return 0;
}
@@ -3971,13 +4150,15 @@ public final class ProcessList {
for (int i = list.size() - 1; i >= 0; i--) {
ProcessRecord r = list.get(i).first;
+ final ProcessStateRecord state = r.mState;
+ final ProcessServiceRecord psr = r.mServices;
long token = proto.start(fieldId);
- String oomAdj = makeOomAdjString(r.setAdj, true);
+ String oomAdj = makeOomAdjString(state.getSetAdj(), true);
proto.write(ProcessOomProto.PERSISTENT, r.isPersistent());
proto.write(ProcessOomProto.NUM, (origList.size() - 1) - list.get(i).second);
proto.write(ProcessOomProto.OOM_ADJ, oomAdj);
int schedGroup = ProcessOomProto.SCHED_GROUP_UNKNOWN;
- switch (r.setSchedGroup) {
+ switch (state.getSetSchedGroup()) {
case SCHED_GROUP_BACKGROUND:
schedGroup = ProcessOomProto.SCHED_GROUP_BACKGROUND;
break;
@@ -3994,52 +4175,52 @@ public final class ProcessList {
if (schedGroup != ProcessOomProto.SCHED_GROUP_UNKNOWN) {
proto.write(ProcessOomProto.SCHED_GROUP, schedGroup);
}
- if (r.hasForegroundActivities()) {
+ if (state.hasForegroundActivities()) {
proto.write(ProcessOomProto.ACTIVITIES, true);
- } else if (r.hasForegroundServices()) {
+ } else if (psr.hasForegroundServices()) {
proto.write(ProcessOomProto.SERVICES, true);
}
proto.write(ProcessOomProto.STATE,
- makeProcStateProtoEnum(r.getCurProcState()));
+ makeProcStateProtoEnum(state.getCurProcState()));
proto.write(ProcessOomProto.TRIM_MEMORY_LEVEL, r.mProfile.getTrimMemoryLevel());
r.dumpDebug(proto, ProcessOomProto.PROC);
- proto.write(ProcessOomProto.ADJ_TYPE, r.adjType);
- if (r.adjSource != null || r.adjTarget != null) {
- if (r.adjTarget instanceof ComponentName) {
- ComponentName cn = (ComponentName) r.adjTarget;
+ proto.write(ProcessOomProto.ADJ_TYPE, state.getAdjType());
+ if (state.getAdjSource() != null || state.getAdjTarget() != null) {
+ if (state.getAdjTarget() instanceof ComponentName) {
+ ComponentName cn = (ComponentName) state.getAdjTarget();
cn.dumpDebug(proto, ProcessOomProto.ADJ_TARGET_COMPONENT_NAME);
- } else if (r.adjTarget != null) {
- proto.write(ProcessOomProto.ADJ_TARGET_OBJECT, r.adjTarget.toString());
+ } else if (state.getAdjTarget() != null) {
+ proto.write(ProcessOomProto.ADJ_TARGET_OBJECT, state.getAdjTarget().toString());
}
- if (r.adjSource instanceof ProcessRecord) {
- ProcessRecord p = (ProcessRecord) r.adjSource;
+ if (state.getAdjSource() instanceof ProcessRecord) {
+ ProcessRecord p = (ProcessRecord) state.getAdjSource();
p.dumpDebug(proto, ProcessOomProto.ADJ_SOURCE_PROC);
- } else if (r.adjSource != null) {
- proto.write(ProcessOomProto.ADJ_SOURCE_OBJECT, r.adjSource.toString());
+ } else if (state.getAdjSource() != null) {
+ proto.write(ProcessOomProto.ADJ_SOURCE_OBJECT, state.getAdjSource().toString());
}
}
if (inclDetails) {
long detailToken = proto.start(ProcessOomProto.DETAIL);
- proto.write(ProcessOomProto.Detail.MAX_ADJ, r.maxAdj);
- proto.write(ProcessOomProto.Detail.CUR_RAW_ADJ, r.getCurRawAdj());
- proto.write(ProcessOomProto.Detail.SET_RAW_ADJ, r.setRawAdj);
- proto.write(ProcessOomProto.Detail.CUR_ADJ, r.curAdj);
- proto.write(ProcessOomProto.Detail.SET_ADJ, r.setAdj);
+ proto.write(ProcessOomProto.Detail.MAX_ADJ, state.getMaxAdj());
+ proto.write(ProcessOomProto.Detail.CUR_RAW_ADJ, state.getCurRawAdj());
+ proto.write(ProcessOomProto.Detail.SET_RAW_ADJ, state.getSetRawAdj());
+ proto.write(ProcessOomProto.Detail.CUR_ADJ, state.getCurAdj());
+ proto.write(ProcessOomProto.Detail.SET_ADJ, state.getSetAdj());
proto.write(ProcessOomProto.Detail.CURRENT_STATE,
- makeProcStateProtoEnum(r.getCurProcState()));
+ makeProcStateProtoEnum(state.getCurProcState()));
proto.write(ProcessOomProto.Detail.SET_STATE,
- makeProcStateProtoEnum(r.setProcState));
+ makeProcStateProtoEnum(state.getSetProcState()));
proto.write(ProcessOomProto.Detail.LAST_PSS, DebugUtils.sizeValueToString(
r.mProfile.getLastPss() * 1024, new StringBuilder()));
proto.write(ProcessOomProto.Detail.LAST_SWAP_PSS, DebugUtils.sizeValueToString(
r.mProfile.getLastSwapPss() * 1024, new StringBuilder()));
proto.write(ProcessOomProto.Detail.LAST_CACHED_PSS, DebugUtils.sizeValueToString(
r.mProfile.getLastCachedPss() * 1024, new StringBuilder()));
- proto.write(ProcessOomProto.Detail.CACHED, r.isCached());
- proto.write(ProcessOomProto.Detail.EMPTY, r.empty);
- proto.write(ProcessOomProto.Detail.HAS_ABOVE_CLIENT, r.hasAboveClient);
+ proto.write(ProcessOomProto.Detail.CACHED, state.isCached());
+ proto.write(ProcessOomProto.Detail.EMPTY, state.isEmpty());
+ proto.write(ProcessOomProto.Detail.HAS_ABOVE_CLIENT, psr.hasAboveClient());
- if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
+ if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
if (lastCpuTime != 0) {
long uptimeSince = curUptime - service.mLastPowerCheckUptime;
@@ -4073,9 +4254,11 @@ public final class ProcessList {
for (int i = list.size() - 1; i >= 0; i--) {
ProcessRecord r = list.get(i).first;
- String oomAdj = makeOomAdjString(r.setAdj, false);
+ final ProcessStateRecord state = r.mState;
+ final ProcessServiceRecord psr = r.mServices;
+ String oomAdj = makeOomAdjString(state.getSetAdj(), false);
char schedGroup;
- switch (r.setSchedGroup) {
+ switch (state.getSetSchedGroup()) {
case SCHED_GROUP_BACKGROUND:
schedGroup = 'b';
break;
@@ -4096,14 +4279,14 @@ public final class ProcessList {
break;
}
char foreground;
- if (r.hasForegroundActivities()) {
+ if (state.hasForegroundActivities()) {
foreground = 'A';
- } else if (r.hasForegroundServices()) {
+ } else if (psr.hasForegroundServices()) {
foreground = 'S';
} else {
foreground = ' ';
}
- String procState = makeProcStateString(r.getCurProcState());
+ String procState = makeProcStateString(state.getCurProcState());
pw.print(prefix);
pw.print(r.isPersistent() ? persistentLabel : normalLabel);
pw.print(" #");
@@ -4119,7 +4302,7 @@ public final class ProcessList {
pw.print('/');
pw.print(procState);
pw.print(' ');
- ActivityManager.printCapabilitiesSummary(pw, r.curCapability);
+ ActivityManager.printCapabilitiesSummary(pw, state.getCurCapability());
pw.print(' ');
pw.print(" t:");
if (r.mProfile.getTrimMemoryLevel() < 10) pw.print(' ');
@@ -4127,25 +4310,25 @@ public final class ProcessList {
pw.print(' ');
pw.print(r.toShortString());
pw.print(" (");
- pw.print(r.adjType);
+ pw.print(state.getAdjType());
pw.println(')');
- if (r.adjSource != null || r.adjTarget != null) {
+ if (state.getAdjSource() != null || state.getAdjTarget() != null) {
pw.print(prefix);
pw.print(" ");
- if (r.adjTarget instanceof ComponentName) {
- pw.print(((ComponentName) r.adjTarget).flattenToShortString());
- } else if (r.adjTarget != null) {
- pw.print(r.adjTarget.toString());
+ if (state.getAdjTarget() instanceof ComponentName) {
+ pw.print(((ComponentName) state.getAdjTarget()).flattenToShortString());
+ } else if (state.getAdjTarget() != null) {
+ pw.print(state.getAdjTarget().toString());
} else {
pw.print("{null}");
}
pw.print("<=");
- if (r.adjSource instanceof ProcessRecord) {
+ if (state.getAdjSource() instanceof ProcessRecord) {
pw.print("Proc{");
- pw.print(((ProcessRecord) r.adjSource).toShortString());
+ pw.print(((ProcessRecord) state.getAdjSource()).toShortString());
pw.println("}");
- } else if (r.adjSource != null) {
- pw.println(r.adjSource.toString());
+ } else if (state.getAdjSource() != null) {
+ pw.println(state.getAdjSource().toString());
} else {
pw.println("{null}");
}
@@ -4153,16 +4336,15 @@ public final class ProcessList {
if (inclDetails) {
pw.print(prefix);
pw.print(" ");
- pw.print("oom: max="); pw.print(r.maxAdj);
- pw.print(" curRaw="); pw.print(r.getCurRawAdj());
- pw.print(" setRaw="); pw.print(r.setRawAdj);
- pw.print(" cur="); pw.print(r.curAdj);
- pw.print(" set="); pw.println(r.setAdj);
+ pw.print("oom: max="); pw.print(state.getMaxAdj());
+ pw.print(" curRaw="); pw.print(state.getCurRawAdj());
+ pw.print(" setRaw="); pw.print(state.getSetRawAdj());
+ pw.print(" cur="); pw.print(state.getCurAdj());
+ pw.print(" set="); pw.println(state.getSetAdj());
pw.print(prefix);
pw.print(" ");
- pw.print("state: cur="); pw.print(
- makeProcStateString(r.getCurProcState()));
- pw.print(" set="); pw.print(makeProcStateString(r.setProcState));
+ pw.print("state: cur="); pw.print(makeProcStateString(state.getCurProcState()));
+ pw.print(" set="); pw.print(makeProcStateString(state.getSetProcState()));
pw.print(" lastPss=");
DebugUtils.printSizeValue(pw, r.mProfile.getLastPss() * 1024);
pw.print(" lastSwapPss=");
@@ -4172,11 +4354,11 @@ public final class ProcessList {
pw.println();
pw.print(prefix);
pw.print(" ");
- pw.print("cached="); pw.print(r.isCached());
- pw.print(" empty="); pw.print(r.empty);
- pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
+ pw.print("cached="); pw.print(state.isCached());
+ pw.print(" empty="); pw.print(state.isEmpty());
+ pw.print(" hasAboveClient="); pw.println(psr.hasAboveClient());
- if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
+ if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
long lastCpuTime = r.mProfile.mLastCpuTime.get();
if (lastCpuTime != 0) {
long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
@@ -4212,9 +4394,10 @@ public final class ProcessList {
pw.println(")");
}
+ @GuardedBy("mService")
boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String[] args,
int opti, boolean dumpAll, String dumpPackage, boolean inclGc) {
- if (getLruSizeLocked() > 0) {
+ if (getLruSizeLOSP() > 0) {
if (needSep) pw.println();
needSep = true;
pw.println(" OOM levels:");
@@ -4235,14 +4418,14 @@ public final class ProcessList {
printOomLevel(pw, "CACHED_APP_MAX_ADJ", CACHED_APP_MAX_ADJ);
if (needSep) pw.println();
- pw.print(" Process OOM control ("); pw.print(getLruSizeLocked());
+ pw.print(" Process OOM control ("); pw.print(getLruSizeLOSP());
pw.print(" total, non-act at ");
- pw.print(getLruSizeLocked() - mLruProcessActivityStart);
+ pw.print(getLruSizeLOSP() - mLruProcessActivityStart);
pw.print(", non-svc at ");
- pw.print(getLruSizeLocked() - mLruProcessServiceStart);
+ pw.print(getLruSizeLOSP() - mLruProcessServiceStart);
pw.println("):");
- dumpProcessOomList(pw, mService, mLruProcesses, " ", "Proc", "PERS", true,
- dumpPackage);
+ dumpProcessOomList(pw, mService, mLruProcesses,
+ " ", "Proc", "PERS", true, dumpPackage);
needSep = true;
}
@@ -4396,8 +4579,8 @@ public final class ProcessList {
mProcessObservers.finishBroadcast();
}
- @GuardedBy("mService")
- ArrayList collectProcessesLocked(int start, boolean allPkgs, String[] args) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ArrayList collectProcessesLOSP(int start, boolean allPkgs, String[] args) {
ArrayList procs;
if (args != null && args.length > start
&& args[start].charAt(0) != '-') {
@@ -4409,7 +4592,7 @@ public final class ProcessList {
}
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord proc = mLruProcesses.get(i);
- if (proc.pid > 0 && proc.pid == pid) {
+ if (proc.getPid() > 0 && proc.getPid() == pid) {
procs.add(proc);
} else if (allPkgs && proc.getPkgList() != null
&& proc.getPkgList().containsKey(args[start])) {
@@ -4427,12 +4610,12 @@ public final class ProcessList {
return procs;
}
- @GuardedBy("mService")
- void updateApplicationInfoLocked(List packagesToUpdate, int userId,
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void updateApplicationInfoLOSP(List packagesToUpdate, int userId,
boolean updateFrameworkRes) {
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mLruProcesses.get(i);
- if (app.thread == null) {
+ if (app.getThread() == null) {
continue;
}
@@ -4446,14 +4629,14 @@ public final class ProcessList {
final ApplicationInfo ai = AppGlobals.getPackageManager()
.getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);
if (ai != null) {
- app.thread.scheduleApplicationInfoChanged(ai);
+ app.getThread().scheduleApplicationInfoChanged(ai);
if (ai.packageName.equals(app.info.packageName)) {
app.info = ai;
}
}
} catch (RemoteException e) {
Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",
- packageName, app));
+ packageName, app));
}
}
});
@@ -4465,14 +4648,15 @@ public final class ProcessList {
boolean foundProcess = false;
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
+ final IApplicationThread thread = r.getThread();
+ if (thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
try {
for (int index = packages.length - 1; index >= 0 && !foundProcess; index--) {
if (packages[index].equals(r.info.packageName)) {
foundProcess = true;
}
}
- r.thread.dispatchPackageBroadcast(cmd, packages);
+ thread.dispatchPackageBroadcast(cmd, packages);
} catch (RemoteException ex) {
}
}
@@ -4487,15 +4671,15 @@ public final class ProcessList {
}
/** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */
- @GuardedBy("mService")
- int getUidProcStateLocked(int uid) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getUidProcStateLOSP(int uid) {
UidRecord uidRec = mActiveUids.get(uid);
return uidRec == null ? PROCESS_STATE_NONEXISTENT : uidRec.getCurProcState();
}
/** Returns the UidRecord for the given uid, if it exists. */
- @GuardedBy("mService")
- UidRecord getUidRecordLocked(int uid) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ UidRecord getUidRecordLOSP(int uid) {
return mActiveUids.get(uid);
}
@@ -4512,10 +4696,10 @@ public final class ProcessList {
continue;
}
final UidRecord uidRec = mActiveUids.valueAt(i);
- if (!uidRec.idle) {
+ if (!uidRec.isIdle()) {
continue;
}
- mService.doStopUidLocked(uidRec.uid, uidRec);
+ mService.doStopUidLocked(uidRec.getUid(), uidRec);
}
}
@@ -4529,14 +4713,16 @@ public final class ProcessList {
* {@link #NETWORK_STATE_NO_CHANGE}.
*/
@VisibleForTesting
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
int getBlockStateForUid(UidRecord uidRec) {
// Denotes whether uid's process state is currently allowed network access.
final boolean isAllowed =
isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
|| isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
// Denotes whether uid's process state was previously allowed network access.
- final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
- || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
+ final boolean wasAllowed =
+ isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getSetProcState())
+ || isProcStateAllowedWhileOnRestrictBackground(uidRec.getSetProcState());
// When the uid is coming to foreground, AMS should inform the app thread that it should
// block for the network rules to get updated before launching an activity.
@@ -4557,8 +4743,8 @@ public final class ProcessList {
* {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
*/
@VisibleForTesting
- @GuardedBy("mService")
- void incrementProcStateSeqAndNotifyAppsLocked(ActiveUids activeUids) {
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void incrementProcStateSeqAndNotifyAppsLOSP(ActiveUids activeUids) {
if (mService.mWaitForNetworkTimeoutMs <= 0) {
return;
}
@@ -4567,14 +4753,14 @@ public final class ProcessList {
for (int i = activeUids.size() - 1; i >= 0; --i) {
final UidRecord uidRec = activeUids.valueAt(i);
// If the network is not restricted for uid, then nothing to do here.
- if (!mService.mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
+ if (!mService.mInjector.isNetworkRestrictedForUid(uidRec.getUid())) {
continue;
}
- if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
+ if (!UserHandle.isApp(uidRec.getUid()) || !uidRec.hasInternetPermission) {
continue;
}
// If process state is not changed, then there's nothing to do.
- if (uidRec.setProcState == uidRec.getCurProcState()) {
+ if (uidRec.getSetProcState() == uidRec.getCurProcState()) {
continue;
}
final int blockState = getBlockStateForUid(uidRec);
@@ -4589,7 +4775,7 @@ public final class ProcessList {
if (blockingUids == null) {
blockingUids = new ArrayList<>();
}
- blockingUids.add(uidRec.uid);
+ blockingUids.add(uidRec.getUid());
} else {
if (DEBUG_NETWORK) {
Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
@@ -4612,15 +4798,16 @@ public final class ProcessList {
if (!blockingUids.contains(app.uid)) {
continue;
}
- if (!app.killedByAm && app.thread != null) {
- final UidRecord uidRec = getUidRecordLocked(app.uid);
+ final IApplicationThread thread = app.getThread();
+ if (!app.isKilledByAm() && thread != null) {
+ final UidRecord uidRec = getUidRecordLOSP(app.uid);
try {
if (DEBUG_NETWORK) {
Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
+ uidRec);
}
if (uidRec != null) {
- app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
+ thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
}
} catch (RemoteException ignored) {
}
@@ -4692,7 +4879,7 @@ public final class ProcessList {
Slog.i(TAG, "note: " + app + " died, saving the exit info");
}
- Watchdog.getInstance().processDied(app.processName, app.pid);
+ Watchdog.getInstance().processDied(app.processName, app.getPid());
mAppExitInfoTracker.scheduleNoteProcessDied(app);
}
@@ -4814,10 +5001,10 @@ public final class ProcessList {
}
final Bundle bundle = new Bundle();
- bundle.putInt(EXTRA_PID, app.pid);
+ bundle.putInt(EXTRA_PID, app.getPid());
bundle.putInt(EXTRA_UID, app.uid);
// Since the pid could be reused, let's get the actual start time of each process
- bundle.putLong(EXTRA_TIMESTAMP, app.startTime);
+ bundle.putLong(EXTRA_TIMESTAMP, app.getStartTime());
bundle.putString(EXTRA_REASON, reason);
bundle.putInt(EXTRA_REQUESTER, requester);
List list = mWorkItems.get(app.uid);
@@ -4909,13 +5096,14 @@ public final class ProcessList {
app = mService.mPidsSelfLocked.get(pid);
}
- if (app == null || app.pid != pid || app.uid != uid || app.startTime != timestamp) {
+ if (app == null || app.getPid() != pid || app.uid != uid
+ || app.getStartTime() != timestamp) {
// This process record has been reused for another process, meaning the old process
// has been gone.
return true;
}
- if (app.getPkgList().forEachPackage(pkgName -> {
+ if (app.getPkgList().searchEachPackage(pkgName -> {
if (mService.mConstants.IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.contains(pkgName)) {
// One of the packages in this process is exempted
return Boolean.TRUE;
@@ -4926,12 +5114,12 @@ public final class ProcessList {
}
if (mService.mConstants.IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.contains(
- app.getReportedProcState())) {
+ app.mState.getReportedProcState())) {
// We need to reschedule it.
return false;
}
- app.kill(reason, ApplicationExitInfo.REASON_OTHER,
+ app.killLocked(reason, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_IMPERCEPTIBLE, true);
if (!app.isolated) {
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 9fd2bd798c044..e533cc3512d35 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -26,6 +26,7 @@ import android.os.SystemClock;
import android.util.DebugUtils;
import android.util.TimeUtils;
+import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
@@ -141,13 +142,13 @@ final class ProcessProfileRecord {
/**
* Last selected memory trimming level.
*/
- @GuardedBy("mService")
+ @CompositeRWLock({"mService", "mProcLock"})
private int mTrimMemoryLevel;
/**
* Want to clean up resources from showing UI?
*/
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
private boolean mPendingUiClean;
/**
@@ -164,7 +165,7 @@ final class ProcessProfileRecord {
/**
* When we last told the app that memory is low.
*/
- @GuardedBy("mService")
+ @CompositeRWLock({"mService", "mProfilerLock"})
private long mLastLowMemory;
/**
@@ -193,9 +194,12 @@ final class ProcessProfileRecord {
@GuardedBy("mProfilerLock")
private long mLastStateTime;
+ private final ActivityManagerGlobalLock mProcLock;
+
ProcessProfileRecord(final ProcessRecord app) {
mApp = app;
mService = app.mService;
+ mProcLock = mService.mProcLock;
mProfilerLock = mService.mAppProfiler.mProfilerLock;
}
@@ -410,22 +414,22 @@ final class ProcessProfileRecord {
mPssStatType = pssStatType;
}
- @GuardedBy("mService")
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
int getTrimMemoryLevel() {
return mTrimMemoryLevel;
}
- @GuardedBy("mService")
+ @GuardedBy({"mService", "mProcLock"})
void setTrimMemoryLevel(int trimMemoryLevel) {
mTrimMemoryLevel = trimMemoryLevel;
}
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
boolean hasPendingUiClean() {
return mPendingUiClean;
}
- @GuardedBy("mService")
+ @GuardedBy("mProcLock")
void setPendingUiClean(boolean pendingUiClean) {
mPendingUiClean = pendingUiClean;
mApp.getWindowProcessController().setPendingUiClean(pendingUiClean);
@@ -449,12 +453,12 @@ final class ProcessProfileRecord {
mLastRequestedGc = lastRequestedGc;
}
- @GuardedBy("mService")
+ @GuardedBy(anyOf = {"mService", "mProfilerLock"})
long getLastLowMemory() {
return mLastLowMemory;
}
- @GuardedBy("mService")
+ @GuardedBy({"mService", "mProfilerLock"})
void setLastLowMemory(long lastLowMemory) {
mLastLowMemory = lastLowMemory;
}
@@ -593,11 +597,11 @@ final class ProcessProfileRecord {
}
@GuardedBy({"mService", "mProfilerLock"})
- void updateProcState(ProcessRecord app) {
- mSetProcState = app.getCurProcState();
- mSetAdj = app.curAdj;
- mCurRawAdj = app.getCurRawAdj();
- mLastStateTime = app.lastStateTime;
+ void updateProcState(ProcessStateRecord state) {
+ mSetProcState = state.getCurProcState();
+ mSetAdj = state.getCurAdj();
+ mCurRawAdj = state.getCurRawAdj();
+ mLastStateTime = state.getLastStateTime();
}
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/am/ProcessProviderRecord.java b/services/core/java/com/android/server/am/ProcessProviderRecord.java
new file mode 100644
index 0000000000000..751e8a821ab1f
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessProviderRecord.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.util.ArrayMap;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * The state info of all content providers in the process.
+ */
+final class ProcessProviderRecord {
+ final ProcessRecord mApp;
+ private final ActivityManagerService mService;
+
+ /**
+ * The last time someone else was using a provider in this process.
+ */
+ private long mLastProviderTime;
+
+ /**
+ * class (String) -> ContentProviderRecord.
+ */
+ private final ArrayMap mPubProviders = new ArrayMap<>();
+
+ /**
+ * All ContentProviderRecord process is using.
+ */
+ private final ArrayList mConProviders = new ArrayList<>();
+
+ long getLastProviderTime() {
+ return mLastProviderTime;
+ }
+
+ void setLastProviderTime(long lastProviderTime) {
+ mLastProviderTime = lastProviderTime;
+ }
+
+ boolean hasProvider(String name) {
+ return mPubProviders.containsKey(name);
+ }
+
+ ContentProviderRecord getProvider(String name) {
+ return mPubProviders.get(name);
+ }
+
+ int numberOfProviders() {
+ return mPubProviders.size();
+ }
+
+ ContentProviderRecord getProviderAt(int index) {
+ return mPubProviders.valueAt(index);
+ }
+
+ void installProvider(String name, ContentProviderRecord provider) {
+ mPubProviders.put(name, provider);
+ }
+
+ void removeProvider(String name) {
+ mPubProviders.remove(name);
+ }
+
+ void ensureProviderCapacity(int capacity) {
+ mPubProviders.ensureCapacity(capacity);
+ }
+
+ int numberOfProviderConnections() {
+ return mConProviders.size();
+ }
+
+ ContentProviderConnection getProviderConnectionAt(int index) {
+ return mConProviders.get(index);
+ }
+
+ void addProviderConnection(ContentProviderConnection connection) {
+ mConProviders.add(connection);
+ }
+
+ boolean removeProviderConnection(ContentProviderConnection connection) {
+ return mConProviders.remove(connection);
+ }
+
+ ProcessProviderRecord(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ }
+
+ /**
+ * @return Should the process restart or not.
+ */
+ @GuardedBy("mService")
+ boolean onCleanupApplicationRecordLocked(boolean allowRestart) {
+ boolean restart = false;
+ // Remove published content providers.
+ for (int i = mPubProviders.size() - 1; i >= 0; i--) {
+ final ContentProviderRecord cpr = mPubProviders.valueAt(i);
+ if (cpr.proc != mApp) {
+ // If the hosting process record isn't really us, bail out
+ continue;
+ }
+ final boolean alwaysRemove = mApp.mErrorState.isBad() || !allowRestart;
+ final boolean inLaunching = mService.mCpHelper
+ .removeDyingProviderLocked(mApp, cpr, alwaysRemove);
+ if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) {
+ // We left the provider in the launching list, need to
+ // restart it.
+ restart = true;
+ }
+
+ cpr.provider = null;
+ cpr.setProcess(null);
+ }
+ mPubProviders.clear();
+
+ // Take care of any launching providers waiting for this process.
+ if (mService.mCpHelper.cleanupAppInLaunchingProvidersLocked(mApp, false)) {
+ mService.mProcessList.noteProcessDiedLocked(mApp);
+ restart = true;
+ }
+
+ // Unregister from connected content providers.
+ if (!mConProviders.isEmpty()) {
+ for (int i = mConProviders.size() - 1; i >= 0; i--) {
+ final ContentProviderConnection conn = mConProviders.get(i);
+ conn.provider.connections.remove(conn);
+ mService.stopAssociationLocked(mApp.uid, mApp.processName, conn.provider.uid,
+ conn.provider.appInfo.longVersionCode, conn.provider.name,
+ conn.provider.info.processName);
+ }
+ mConProviders.clear();
+ }
+
+ return restart;
+ }
+
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ if (mLastProviderTime > 0) {
+ pw.print(prefix); pw.print("lastProviderTime=");
+ TimeUtils.formatDuration(mLastProviderTime, nowUptime, pw);
+ pw.println();
+ }
+ if (mPubProviders.size() > 0) {
+ pw.print(prefix); pw.println("Published Providers:");
+ for (int i = 0, size = mPubProviders.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mPubProviders.keyAt(i));
+ pw.print(prefix); pw.print(" -> "); pw.println(mPubProviders.valueAt(i));
+ }
+ }
+ if (mConProviders.size() > 0) {
+ pw.print(prefix); pw.println("Connected Providers:");
+ for (int i = 0, size = mConProviders.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - ");
+ pw.println(mConProviders.get(i).toShortString());
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessReceiverRecord.java b/services/core/java/com/android/server/am/ProcessReceiverRecord.java
new file mode 100644
index 0000000000000..8d3e9669ea004
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessReceiverRecord.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+
+/**
+ * The state info of all broadcast receivers in the process.
+ */
+final class ProcessReceiverRecord {
+ final ProcessRecord mApp;
+ private final ActivityManagerService mService;
+
+ /**
+ * mReceivers currently running in the app.
+ */
+ private final ArraySet mCurReceivers = new ArraySet();
+
+ /**
+ * All IIntentReceivers that are registered from this process.
+ */
+ private final ArraySet mReceivers = new ArraySet<>();
+
+ int numberOfCurReceivers() {
+ return mCurReceivers.size();
+ }
+
+ BroadcastRecord getCurReceiverAt(int index) {
+ return mCurReceivers.valueAt(index);
+ }
+
+ boolean hasCurReceiver(BroadcastRecord receiver) {
+ return mCurReceivers.contains(receiver);
+ }
+
+ void addCurReceiver(BroadcastRecord receiver) {
+ mCurReceivers.add(receiver);
+ }
+
+ void removeCurReceiver(BroadcastRecord receiver) {
+ mCurReceivers.remove(receiver);
+ }
+
+ int numberOfReceivers() {
+ return mReceivers.size();
+ }
+
+ ReceiverList getReceiverAt(int index) {
+ return mReceivers.valueAt(index);
+ }
+
+ void addReceiver(ReceiverList receiver) {
+ mReceivers.add(receiver);
+ }
+
+ void removeReceiver(ReceiverList receiver) {
+ mReceivers.remove(receiver);
+ }
+
+ ProcessReceiverRecord(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ }
+
+ @GuardedBy("mService")
+ void onCleanupApplicationRecordLocked() {
+ // Unregister any mReceivers.
+ for (int i = mReceivers.size() - 1; i >= 0; i--) {
+ mService.removeReceiverLocked(mReceivers.valueAt(i));
+ }
+ mReceivers.clear();
+ }
+
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ if (!mCurReceivers.isEmpty()) {
+ pw.print(prefix); pw.println("Current mReceivers:");
+ for (int i = 0, size = mCurReceivers.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mCurReceivers.valueAt(i));
+ }
+ }
+ if (mReceivers.size() > 0) {
+ pw.print(prefix); pw.println("mReceivers:");
+ for (int i = 0, size = mReceivers.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mReceivers.valueAt(i));
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 52ff427f3c84c..21be93a62173c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -16,89 +16,50 @@
package com.android.server.am;
-import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
-import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
-import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.Process.NFC_UID;
-import static android.os.Process.ROOT_UID;
-import static android.os.Process.SHELL_UID;
-import static android.os.Process.SYSTEM_UID;
-
-import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROC_STATE;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
-import static com.android.server.am.ActiveServices.FGS_FEATURE_DENIED;
-import static com.android.server.am.ActiveServices.fgsCodeToString;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.app.ApplicationExitInfo.Reason;
import android.app.ApplicationExitInfo.SubReason;
-import android.app.Dialog;
import android.app.IApplicationThread;
-import android.content.ComponentName;
-import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IncrementalStatesInfo;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ProcessInfo;
-import android.content.pm.ServiceInfo;
import android.content.pm.VersionedPackage;
import android.content.res.CompatibilityInfo;
import android.os.Binder;
import android.os.IBinder;
-import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.Settings;
import android.server.ServerProtoEnums;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.EventLog;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.CompositeRWLock;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
-import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.Zygote;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.MemoryPressureUtil;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;
-import java.io.File;
import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
-import java.util.function.Consumer;
/**
* Full information about a particular process that
@@ -108,6 +69,12 @@ class ProcessRecord implements WindowProcessListener {
static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
final ActivityManagerService mService; // where we came from
+ private final ActivityManagerGlobalLock mProcLock;
+
+ // =========================================================
+ // Basic info of the process, immutable or semi-immutable over
+ // the lifecycle of the process
+ // =========================================================
volatile ApplicationInfo info; // all about the first app in the process
final ProcessInfo processInfo; // if non-null, process-specific manifest info
final boolean isolated; // true if this is a special isolated process
@@ -117,239 +84,288 @@ class ProcessRecord implements WindowProcessListener {
final String processName; // name of the process
/**
- * List of packages running in the process
+ * Overall state of process's uid.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private UidRecord mUidRecord;
+
+ /**
+ * List of packages running in the process.
*/
private final PackageList mPkgList = new PackageList(this);
- UidRecord uidRecord; // overall state of process's uid.
- ArraySet pkgDeps; // additional packages we have a dependency on
- IApplicationThread thread; // the actual proc... may be null only if
- // 'persistent' is true (in which case we
- // are in the process of launching the app)
- int pid; // The process of this application; 0 if none
- String procStatFile; // path to /proc//stat
- int[] gids; // The gids this process was launched with
- private String mRequiredAbi;// The ABI this process was launched with
- String instructionSet; // The instruction set this process was launched with
- boolean starting; // True if the process is being started
- long lastActivityTime; // For managing the LRU list
- long lastStateTime; // Last time setProcState changed
- int maxAdj; // Maximum OOM adjustment for this process
- private int mCurRawAdj; // Current OOM unlimited adjustment for this process
- int setRawAdj; // Last set OOM unlimited adjustment for this process
- int curAdj; // Current OOM adjustment for this process
- int setAdj; // Last set OOM adjustment for this process
- int verifiedAdj; // The last adjustment that was verified as actually being set
- int curCapability; // Current capability flags of this process. For example,
- // PROCESS_CAPABILITY_FOREGROUND_LOCATION is one capability.
- int setCapability; // Last set capability flags.
- long lastCompactTime; // The last time that this process was compacted
- int reqCompactAction; // The most recent compaction action requested for this app.
- int lastCompactAction; // The most recent compaction action performed for this app.
- boolean frozen; // True when the process is frozen.
- boolean freezerOverride; // An override on the freeze state is in progress.
- long freezeUnfreezeTime; // Last time the app was (un)frozen, 0 for never
- boolean shouldNotFreeze; // True if a process has a WPRI binding from an unfrozen process
- private int mCurSchedGroup; // Currently desired scheduling class
- int setSchedGroup; // Last set to background scheduling class
- private int mCurProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state
- private int mRepProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
- private int mCurRawProcState = PROCESS_STATE_NONEXISTENT; // Temp state during computation
- int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
- int savedPriority; // Previous priority value if we're switching to non-SCHED_OTHER
- int renderThreadTid; // TID for RenderThread
- ServiceRecord connectionService; // Service that applied current connectionGroup/Importance
- int connectionGroup; // Last group set by a connection
- int connectionImportance; // Last importance set by a connection
- boolean serviceb; // Process currently is on the service B list
- boolean serviceHighRam; // We are forcing to service B list due to its RAM use
- boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
- private boolean mHasClientActivities; // Are there any client services with activities?
- boolean hasStartedServices; // Are there any started services running in this process?
- private boolean mHasForegroundServices; // Running any services that are foreground?
- private int mFgServiceTypes; // Type of foreground service, if there is a foreground service.
- private int mRepFgServiceTypes; // Last reported foreground service types.
- private boolean mHasForegroundActivities; // Running any activities that are foreground?
- boolean repForegroundActivities; // Last reported foreground activities.
- boolean systemNoUi; // This is a system process, but not currently showing UI.
- boolean hasShownUi; // Has UI been shown in this process since it was started?
- private boolean mHasTopUi; // Is this process currently showing a non-activity UI that the user
- // is interacting with? E.g. The status bar when it is expanded, but
- // not when it is minimized. When true the
- // process will be set to use the ProcessList#SCHED_GROUP_TOP_APP
- // scheduling group to boost performance.
- private boolean mHasOverlayUi; // Is the process currently showing a non-activity UI that
- // overlays on-top of activity UIs on screen. E.g. display a window
- // of type
- // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
- // When true the process will oom adj score will be set to
- // ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
- // of the process getting killed.
- boolean runningRemoteAnimation; // Is the process currently running a RemoteAnimation? When true
- // the process will be set to use the
- // ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost
- // performance, as well as oom adj score will be set to
- // ProcessList#VISIBLE_APP_ADJ at minimum to reduce the chance
- // of the process getting killed.
- boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
- boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY
- boolean bad; // True if disabled in the bad process list
- boolean killedByAm; // True when proc has been killed by activity manager, not for RAM
- boolean killed; // True once we know the process has been killed
- boolean procStateChanged; // Keep track of whether we changed 'setAdj'.
- boolean reportedInteraction;// Whether we have told usage stats about it being an interaction
- boolean unlocked; // True when proc was started in user unlocked state
- private long mInteractionEventTime; // The time we sent the last interaction event
- private long mFgInteractionTime; // When we became foreground for interaction purposes
- String waitingToKill; // Process is waiting to be killed when in the bg, and reason
- Object forcingToImportant; // Token that is forcing this process to be important
- int adjSeq; // Sequence id for identifying oom_adj assignment cycles
- int completedAdjSeq; // Sequence id for identifying oom_adj assignment cycles
- boolean containsCycle; // Whether this app has encountered a cycle in the most recent update
- int lruSeq; // Sequence id for identifying LRU update cycles
- CompatibilityInfo compat; // last used compatibility mode
- IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
- private ActiveInstrumentation mInstr; // Set to currently active instrumentation running in
- // process.
- private boolean mUsingWrapper; // Set to true when process was launched with a wrapper attached
- final ArraySet curReceivers = new ArraySet();// receivers currently running in the app
- private long mWhenUnimportant; // When (uptime) the process last became unimportant
- long lastProviderTime; // The last time someone else was using a provider in this process.
- long lastTopTime; // The last time the process was in the TOP state or greater.
- boolean empty; // Is this an empty background process?
- private boolean mCached; // Is this a cached process?
- String adjType; // Debugging: primary thing impacting oom_adj.
- int adjTypeCode; // Debugging: adj code to report to app.
- Object adjSource; // Debugging: option dependent object.
- int adjSourceProcState; // Debugging: proc state of adjSource's process.
- Object adjTarget; // Debugging: target component impacting oom_adj.
- Runnable crashHandler; // Optional local handler to be invoked in the process crash.
- boolean bindMountPending; // True if Android/obb and Android/data need to be bind mount .
+ /**
+ * Additional packages we have a dependency on.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ArraySet mPkgDeps;
- // Controller for error dialogs
- private final ErrorDialogController mDialogController = new ErrorDialogController();
- // Controller for driving the process state on the window manager side.
+ /**
+ * The process of this application; 0 if none.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ int mPid;
+
+ /**
+ * The gids this process was launched with.
+ */
+ @GuardedBy("mService")
+ private int[] mGids;
+
+ /**
+ * The ABI this process was launched with.
+ */
+ @GuardedBy("mService")
+ private String mRequiredAbi;
+
+ /**
+ * The instruction set this process was launched with.
+ */
+ @GuardedBy("mService")
+ private String mInstructionSet;
+
+ /**
+ * The actual proc... may be null only if 'persistent' is true
+ * (in which case we are in the process of launching the app).
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private IApplicationThread mThread;
+
+ /**
+ * Always keep this application running?
+ */
+ private volatile boolean mPersistent;
+
+ /**
+ * Caching of toShortString() result.
+ * Note: No lock here, it doesn't matter in case of race condition
+ */
+ private String mShortStringName;
+
+ /**
+ * Caching of toString() result.
+ * Note: No lock here, it doesn't matter in case of race condition
+ */
+ private String mStringName;
+
+ /**
+ * Process start is pending.
+ */
+ @GuardedBy("mService")
+ private boolean mPendingStart;
+
+ /**
+ * Seq no. Indicating the latest process start associated with this process record.
+ */
+ @GuardedBy("mService")
+ private long mStartSeq;
+
+ /**
+ * Params used in starting this process.
+ */
+ private volatile HostingRecord mHostingRecord;
+
+ /**
+ * Selinux info of this process.
+ */
+ private volatile String mSeInfo;
+
+ /**
+ * When the process is started.
+ */
+ private volatile long mStartTime;
+
+ /**
+ * This will be same as {@link #uid} usually except for some apps used during factory testing.
+ */
+ private volatile int mStartUid;
+
+ /**
+ * Indicates how the external storage was mounted for this process.
+ */
+ private volatile int mMountMode;
+
+ /**
+ * True if Android/obb and Android/data need to be bind mount.
+ */
+ private volatile boolean mBindMountPending;
+
+ /**
+ * True when proc was started in user unlocked state.
+ */
+ @GuardedBy("mProcLock")
+ private boolean mUnlocked;
+
+ /**
+ * TID for RenderThread.
+ */
+ @GuardedBy("mProcLock")
+ private int mRenderThreadTid;
+
+ /**
+ * Last used compatibility mode.
+ */
+ @GuardedBy("mService")
+ private CompatibilityInfo mCompat;
+
+ /**
+ * Set of disabled compat changes for the process (all others are enabled).
+ */
+ @GuardedBy("mService")
+ private long[] mDisabledCompatChanges;
+
+ /**
+ * Who is watching for the death.
+ */
+ @GuardedBy("mService")
+ private IBinder.DeathRecipient mDeathRecipient;
+
+ /**
+ * Set to currently active instrumentation running in process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ActiveInstrumentation mInstr;
+
+ /**
+ * True when proc has been killed by activity manager, not for RAM.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mKilledByAm;
+
+ /**
+ * True once we know the process has been killed.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mKilled;
+
+ /**
+ * The timestamp in uptime when this process was killed.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mKillTime;
+
+ /**
+ * Process is waiting to be killed when in the bg, and reason.
+ */
+ @GuardedBy("mService")
+ private String mWaitingToKill;
+
+ /**
+ * Whether this process should be killed and removed from process list.
+ * It is set when the package is force-stopped or the process has crashed too many times.
+ */
+ private volatile boolean mRemoved;
+
+ /**
+ * Was app launched for debugging?
+ */
+ @GuardedBy("mService")
+ private boolean mDebugging;
+
+ /**
+ * Has process show wait for debugger dialog?
+ */
+ @GuardedBy("mProcLock")
+ private boolean mWaitedForDebugger;
+
+ /**
+ * For managing the LRU list.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mLastActivityTime;
+
+ /**
+ * Set to true when process was launched with a wrapper attached.
+ */
+ @GuardedBy("mService")
+ private boolean mUsingWrapper;
+
+ /**
+ * Sequence id for identifying LRU update cycles.
+ */
+ @GuardedBy("mService")
+ private int mLruSeq;
+
+ /**
+ * Class to run on start if this is a special isolated process.
+ */
+ @GuardedBy("mService")
+ private String mIsolatedEntryPoint;
+
+ /**
+ * Arguments to pass to isolatedEntryPoint's main().
+ */
+ @GuardedBy("mService")
+ private String[] mIsolatedEntryPointArgs;
+
+ /**
+ * Process is currently hosting a backup agent for backup or restore.
+ */
+ @GuardedBy("mService")
+ private boolean mInFullBackup;
+
+ /**
+ * Controller for driving the process state on the window manager side.
+ */
private final WindowProcessController mWindowProcessController;
- // all ServiceRecord running in this process
- private final ArraySet mServices = new ArraySet<>();
- // services that are currently executing code (need to remain foreground).
- final ArraySet executingServices = new ArraySet<>();
- // All ConnectionRecord this process holds
- final ArraySet connections = new ArraySet<>();
- // all IIntentReceivers that are registered from this process.
- final ArraySet receivers = new ArraySet<>();
- // class (String) -> ContentProviderRecord
- final ArrayMap pubProviders = new ArrayMap<>();
- // All ContentProviderRecord process is using
- final ArrayList conProviders = new ArrayList<>();
- // a set of UIDs of all bound clients
- private ArraySet mBoundClientUids = new ArraySet<>();
-
- String isolatedEntryPoint; // Class to run on start if this is a special isolated process.
- String[] isolatedEntryPointArgs; // Arguments to pass to isolatedEntryPoint's main().
-
- boolean execServicesFg; // do we need to be executing services in the foreground?
- private boolean mPersistent;// always keep this application running?
- private boolean mCrashing; // are we in the process of crashing?
- boolean forceCrashReport; // suppress normal auto-dismiss of crash dialog & report UI?
- private boolean mNotResponding; // does the app have a not responding dialog?
- volatile boolean removed; // Whether this process should be killed and removed from process
- // list. It is set when the package is force-stopped or the process
- // has crashed too many times.
- private boolean mDebugging; // was app launched for debugging?
- boolean waitedForDebugger; // has process show wait for debugger dialog?
-
- String shortStringName; // caching of toShortString() result.
- String stringName; // caching of toString() result.
- boolean pendingStart; // Process start is pending.
- long startSeq; // Seq no. indicating the latest process start associated with
- // this process record.
- int mountMode; // Indicates how the external storage was mounted for this process.
-
- // These reports are generated & stored when an app gets into an error condition.
- // They will be "null" when all is OK.
- ActivityManager.ProcessErrorStateInfo crashingReport;
- ActivityManager.ProcessErrorStateInfo notRespondingReport;
-
- // Who will be notified of the error. This is usually an activity in the
- // app that installed the package.
- ComponentName errorReportReceiver;
-
- // Process is currently hosting a backup agent for backup or restore
- public boolean inFullBackup;
- // App is allowed to manage allowlists such as temporary Power Save mode allowlist.
- boolean mAllowlistManager;
-
- // Params used in starting this process.
- HostingRecord hostingRecord;
- String seInfo;
- long startTime;
- // This will be same as {@link #uid} usually except for some apps used during factory testing.
- int startUid;
- // set of disabled compat changes for the process (all others are enabled)
- long[] mDisabledCompatChanges;
-
- // The precede instance of the process, which would exist when the previous process is killed
- // but not fully dead yet; in this case, the new instance of the process should be held until
- // this precede instance is fully dead.
- volatile ProcessRecord mPrecedence;
- // The succeeding instance of the process, which is going to be started after this process
- // is killed successfully.
- volatile ProcessRecord mSuccessor;
-
- // Cached task info for OomAdjuster
- private static final int VALUE_INVALID = -1;
- private static final int VALUE_FALSE = 0;
- private static final int VALUE_TRUE = 1;
- private int mCachedHasActivities = VALUE_INVALID;
- private int mCachedIsHeavyWeight = VALUE_INVALID;
- private int mCachedHasVisibleActivities = VALUE_INVALID;
- private int mCachedIsHomeProcess = VALUE_INVALID;
- private int mCachedIsPreviousProcess = VALUE_INVALID;
- private int mCachedHasRecentTasks = VALUE_INVALID;
- private int mCachedIsReceivingBroadcast = VALUE_INVALID;
- int mCachedAdj = ProcessList.INVALID_ADJ;
- boolean mCachedForegroundActivities = false;
- int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
- int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
-
- // Approximates the usage count of the app, used for cache re-ranking by CacheOomRanker.
- //
- // Counts the number of times the process is re-added to the cache (i.e. setCached(false);
- // setCached(true)). This over counts, as setCached is sometimes reset while remaining in the
- // cache. However, this happens uniformly across processes, so ranking is not affected.
- private int mCacheOomRankerUseCount;
-
- boolean mReachable; // Whether or not this process is reachable from given process
-
- long mKillTime; // The timestamp in uptime when this process was killed.
-
- // If the proc state is PROCESS_STATE_BOUND_FOREGROUND_SERVICE or above, it can start FGS.
- // It must obtain the proc state from a persistent/top process or FGS, not transitive.
- int mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
-
- private final ArraySet mBackgroundFgsStartTokens = new ArraySet<>();
-
- // Does the process has permission to start FGS from background.
- @ActiveServices.FgsFeatureRetCode int mAllowStartFgsByPermission;
- // Can this process start FGS from background?
- // If this process has the ability to start FGS from background, this ability can be passed to
- // another process through service binding.
- @ActiveServices.FgsFeatureRetCode int mAllowStartFgs;
/**
* Profiling info of the process, such as PSS, cpu, etc.
*/
final ProcessProfileRecord mProfile;
+ /**
+ * All about the services in this process.
+ */
+ final ProcessServiceRecord mServices;
+
+ /**
+ * All about the providers in this process.
+ */
+ final ProcessProviderRecord mProviders;
+
+ /**
+ * All about the receivers in this process.
+ */
+ final ProcessReceiverRecord mReceivers;
+
+ /**
+ * All about the error state(crash, ANR) in this process.
+ */
+ final ProcessErrorStateRecord mErrorState;
+
+ /**
+ * All about the process state info (proc state, oom adj score) in this process.
+ */
+ final ProcessStateRecord mState;
+
+ /**
+ * All about the state info of the optimizer when the process is cached.
+ */
+ final ProcessCachedOptimizerRecord mOptRecord;
+
+ /**
+ * The preceding instance of the process, which would exist when the previous process is killed
+ * but not fully dead yet; in this case, the new instance of the process should be held until
+ * this preceding instance is fully dead.
+ */
+ volatile ProcessRecord mPredecessor;
+
+ /**
+ * The succeeding instance of the process, which is going to be started after this process
+ * is killed successfully.
+ */
+ volatile ProcessRecord mSuccessor;
+
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
long startTime) {
- this.startUid = startUid;
- this.hostingRecord = hostingRecord;
- this.seInfo = seInfo;
- this.startTime = startTime;
+ this.mStartUid = startUid;
+ this.mHostingRecord = hostingRecord;
+ this.mSeInfo = seInfo;
+ this.mStartTime = startTime;
}
+ @GuardedBy({"mService", "mProcLock"})
void dump(PrintWriter pw, String prefix) {
final long nowUptime = SystemClock.uptimeMillis();
@@ -359,10 +375,10 @@ class ProcessRecord implements WindowProcessListener {
pw.print(" ISOLATED uid="); pw.print(uid);
}
pw.print(" gids={");
- if (gids != null) {
- for (int gi=0; gi 0) pw.print(", ");
- pw.print(pkgDeps.valueAt(i));
+ pw.print(mPkgDeps.valueAt(i));
}
pw.println("}");
}
- pw.print(prefix); pw.print("compat="); pw.println(compat);
+ pw.print(prefix); pw.print("compat="); pw.println(mCompat);
if (mInstr != null) {
pw.print(prefix); pw.print("mInstr="); pw.println(mInstr);
}
- pw.print(prefix); pw.print("thread="); pw.println(thread);
- pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
- pw.println(starting);
+ pw.print(prefix); pw.print("thread="); pw.println(mThread);
+ pw.print(prefix); pw.print("pid="); pw.print(mPid);
pw.print(prefix); pw.print("lastActivityTime=");
- TimeUtils.formatDuration(lastActivityTime, nowUptime, pw);
- pw.println();
- pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
- pw.print(" lruSeq="); pw.println(lruSeq);
- pw.print(prefix); pw.print("oom adj: max="); pw.print(maxAdj);
- pw.print(" curRaw="); pw.print(mCurRawAdj);
- pw.print(" setRaw="); pw.print(setRawAdj);
- pw.print(" cur="); pw.print(curAdj);
- pw.print(" set="); pw.println(setAdj);
- pw.print(prefix); pw.print("lastCompactTime="); pw.print(lastCompactTime);
- pw.print(" lastCompactAction="); pw.println(lastCompactAction);
- pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
- pw.print(" setSchedGroup="); pw.print(setSchedGroup);
- pw.print(" systemNoUi="); pw.print(systemNoUi);
- pw.print(prefix); pw.print("curProcState="); pw.print(getCurProcState());
- pw.print(" mRepProcState="); pw.print(mRepProcState);
- pw.print(" setProcState="); pw.print(setProcState);
- pw.print(" lastStateTime=");
- TimeUtils.formatDuration(lastStateTime, nowUptime, pw);
- pw.println();
- pw.print(prefix); pw.print("curCapability=");
- ActivityManager.printCapabilitiesFull(pw, curCapability);
- pw.print(" setCapability=");
- ActivityManager.printCapabilitiesFull(pw, setCapability);
- pw.println();
- pw.print(prefix); pw.print("allowStartFgsState=");
- pw.println(mAllowStartFgsState);
- if (mAllowStartFgs != FGS_FEATURE_DENIED) {
- pw.print(prefix); pw.print("allowStartFgs=");
- pw.println(fgsCodeToString(mAllowStartFgs));
- }
- if (hasShownUi || mProfile.hasPendingUiClean() || hasAboveClient || treatLikeActivity) {
- pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
- pw.print(" pendingUiClean="); pw.print(mProfile.hasPendingUiClean());
- pw.print(" hasAboveClient="); pw.print(hasAboveClient);
- pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
- }
- pw.print(prefix); pw.print("cached="); pw.print(mCached);
- pw.print(" empty="); pw.println(empty);
- if (serviceb) {
- pw.print(prefix); pw.print("serviceb="); pw.print(serviceb);
- pw.print(" serviceHighRam="); pw.println(serviceHighRam);
- }
- if (notCachedSinceIdle) {
- pw.print(prefix); pw.print("notCachedSinceIdle="); pw.print(notCachedSinceIdle);
- pw.print(" initialIdlePss="); pw.println(mProfile.getInitialIdlePss());
- }
- if (connectionService != null || connectionGroup != 0) {
- pw.print(prefix); pw.print("connectionGroup="); pw.print(connectionGroup);
- pw.print(" Importance="); pw.print(connectionImportance);
- pw.print(" Service="); pw.println(connectionService);
- }
- if (hasTopUi() || hasOverlayUi() || runningRemoteAnimation) {
- pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi());
- pw.print(" hasOverlayUi="); pw.print(hasOverlayUi());
- pw.print(" runningRemoteAnimation="); pw.println(runningRemoteAnimation);
- }
- if (mHasForegroundServices || forcingToImportant != null) {
- pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
- pw.print(" forcingToImportant="); pw.println(forcingToImportant);
- }
- if (reportedInteraction || mFgInteractionTime != 0) {
- pw.print(prefix); pw.print("reportedInteraction=");
- pw.print(reportedInteraction);
- if (mInteractionEventTime != 0) {
- pw.print(" time=");
- TimeUtils.formatDuration(mInteractionEventTime, SystemClock.elapsedRealtime(), pw);
- }
- if (mFgInteractionTime != 0) {
- pw.print(" fgInteractionTime=");
- TimeUtils.formatDuration(mFgInteractionTime, SystemClock.elapsedRealtime(), pw);
- }
- pw.println();
- }
- if (mPersistent || removed) {
+ TimeUtils.formatDuration(mLastActivityTime, nowUptime, pw);
+ if (mPersistent || mRemoved) {
pw.print(prefix); pw.print("persistent="); pw.print(mPersistent);
- pw.print(" removed="); pw.println(removed);
+ pw.print(" removed="); pw.println(mRemoved);
}
- if (mHasClientActivities || mHasForegroundActivities || repForegroundActivities) {
- pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities);
- pw.print(" foregroundActivities="); pw.print(mHasForegroundActivities);
- pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")");
+ if (mDebugging) {
+ pw.print(prefix); pw.print("mDebugging="); pw.println(mDebugging);
}
- if (lastProviderTime > 0) {
- pw.print(prefix); pw.print("lastProviderTime=");
- TimeUtils.formatDuration(lastProviderTime, nowUptime, pw);
- pw.println();
+ if (mPendingStart) {
+ pw.print(prefix); pw.print("pendingStart="); pw.println(mPendingStart);
}
- if (lastTopTime > 0) {
- pw.print(prefix); pw.print("lastTopTime=");
- TimeUtils.formatDuration(lastTopTime, nowUptime, pw);
- pw.println();
- }
- if (hasStartedServices) {
- pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
- }
- if (pendingStart) {
- pw.print(prefix); pw.print("pendingStart="); pw.println(pendingStart);
- }
- pw.print(prefix); pw.print("startSeq="); pw.println(startSeq);
+ pw.print(prefix); pw.print("startSeq="); pw.println(mStartSeq);
pw.print(prefix); pw.print("mountMode="); pw.println(
- DebugUtils.valueToString(Zygote.class, "MOUNT_EXTERNAL_", mountMode));
- if (setProcState > ActivityManager.PROCESS_STATE_SERVICE) {
+ DebugUtils.valueToString(Zygote.class, "MOUNT_EXTERNAL_", mMountMode));
+ if (mKilled || mKilledByAm || mWaitingToKill != null) {
+ pw.print(prefix); pw.print("killed="); pw.print(mKilled);
+ pw.print(" killedByAm="); pw.print(mKilledByAm);
+ pw.print(" waitingToKill="); pw.println(mWaitingToKill);
+ }
+ if (mIsolatedEntryPoint != null || mIsolatedEntryPointArgs != null) {
+ pw.print(prefix); pw.print("isolatedEntryPoint="); pw.println(mIsolatedEntryPoint);
+ pw.print(prefix); pw.print("isolatedEntryPointArgs=");
+ pw.println(Arrays.toString(mIsolatedEntryPointArgs));
+ }
+ if (mState.getSetProcState() > ActivityManager.PROCESS_STATE_SERVICE) {
mProfile.dumpCputime(pw, prefix);
- pw.print(" whenUnimportant=");
- TimeUtils.formatDuration(mWhenUnimportant - nowUptime, pw);
- pw.println();
}
mProfile.dumpPss(pw, prefix, nowUptime);
- if (killed || killedByAm || waitingToKill != null) {
- pw.print(prefix); pw.print("killed="); pw.print(killed);
- pw.print(" killedByAm="); pw.print(killedByAm);
- pw.print(" waitingToKill="); pw.println(waitingToKill);
- }
- if (mDebugging || mCrashing || mDialogController.hasCrashDialogs() || mNotResponding
- || mDialogController.hasAnrDialogs() || bad) {
- pw.print(prefix); pw.print("mDebugging="); pw.print(mDebugging);
- pw.print(" mCrashing=" + mCrashing);
- pw.print(" " + mDialogController.mCrashDialogs);
- pw.print(" mNotResponding=" + mNotResponding);
- pw.print(" " + mDialogController.mAnrDialogs);
- pw.print(" bad=" + bad);
-
- // mCrashing or mNotResponding is always set before errorReportReceiver
- if (errorReportReceiver != null) {
- pw.print(" errorReportReceiver=");
- pw.print(errorReportReceiver.flattenToShortString());
- }
- pw.println();
- }
- if (mAllowlistManager) {
- pw.print(prefix); pw.print("allowlistManager="); pw.println(mAllowlistManager);
- }
- if (isolatedEntryPoint != null || isolatedEntryPointArgs != null) {
- pw.print(prefix); pw.print("isolatedEntryPoint="); pw.println(isolatedEntryPoint);
- pw.print(prefix); pw.print("isolatedEntryPointArgs=");
- pw.println(Arrays.toString(isolatedEntryPointArgs));
- }
+ mState.dump(pw, prefix, nowUptime);
+ mErrorState.dump(pw, prefix, nowUptime);
+ mServices.dump(pw, prefix, nowUptime);
+ mProviders.dump(pw, prefix, nowUptime);
+ mReceivers.dump(pw, prefix, nowUptime);
+ mOptRecord.dump(pw, prefix, nowUptime);
mWindowProcessController.dump(pw, prefix);
- if (mServices.size() > 0) {
- pw.print(prefix); pw.println("Services:");
- for (int i = 0; i < mServices.size(); i++) {
- pw.print(prefix); pw.print(" - "); pw.println(mServices.valueAt(i));
- }
- }
- if (executingServices.size() > 0) {
- pw.print(prefix); pw.print("Executing Services (fg=");
- pw.print(execServicesFg); pw.println(")");
- for (int i=0; i 0) {
- pw.print(prefix); pw.println("Connections:");
- for (int i=0; i 0) {
- pw.print(prefix); pw.println("Published Providers:");
- for (int i=0; i "); pw.println(pubProviders.valueAt(i));
- }
- }
- if (conProviders.size() > 0) {
- pw.print(prefix); pw.println("Connected Providers:");
- for (int i=0; i 0) {
- pw.print(prefix); pw.println("Receivers:");
- for (int i=0; i getPkgDeps() {
+ return mPkgDeps;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setPkgDeps(ArraySet pkgDeps) {
+ mPkgDeps = pkgDeps;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getPid() {
+ return mPid;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setPid(int pid) {
+ mPid = pid;
mWindowProcessController.setPid(pid);
- procStatFile = null;
- shortStringName = null;
- stringName = null;
+ mShortStringName = null;
+ mStringName = null;
synchronized (mProfile.mProfilerLock) {
mProfile.setPid(pid);
}
}
- public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
- mProfile.onProcessActive(_thread, tracker);
- thread = _thread;
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ IApplicationThread getThread() {
+ return mThread;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {
+ mProfile.onProcessActive(thread, tracker);
+ mThread = thread;
mWindowProcessController.setThread(thread);
}
+ @GuardedBy({"mService", "mProcLock"})
public void makeInactive(ProcessStatsService tracker) {
- thread = null;
+ mThread = null;
mWindowProcessController.setThread(null);
mProfile.onProcessInactive(tracker);
}
- /**
- * Records a service as running in the process. Note that this method does not actually start
- * the service, but records the service as started for bookkeeping.
- *
- * @return true if the service was added, false otherwise.
- */
- boolean startService(ServiceRecord record) {
- if (record == null) {
- return false;
+ @GuardedBy("mService")
+ int[] getGids() {
+ return mGids;
+ }
+
+ @GuardedBy("mService")
+ void setGids(int[] gids) {
+ mGids = gids;
+ }
+
+ @GuardedBy("mService")
+ String getRequiredAbi() {
+ return mRequiredAbi;
+ }
+
+ @GuardedBy("mService")
+ void setRequiredAbi(String requiredAbi) {
+ mRequiredAbi = requiredAbi;
+ mWindowProcessController.setRequiredAbi(requiredAbi);
+ }
+
+ @GuardedBy("mService")
+ String getInstructionSet() {
+ return mInstructionSet;
+ }
+
+ @GuardedBy("mService")
+ void setInstructionSet(String instructionSet) {
+ mInstructionSet = instructionSet;
+ }
+
+ void setPersistent(boolean persistent) {
+ mPersistent = persistent;
+ mWindowProcessController.setPersistent(persistent);
+ }
+
+ boolean isPersistent() {
+ return mPersistent;
+ }
+
+ @GuardedBy("mService")
+ boolean isPendingStart() {
+ return mPendingStart;
+ }
+
+ @GuardedBy("mService")
+ void setPendingStart(boolean pendingStart) {
+ mPendingStart = pendingStart;
+ }
+
+ @GuardedBy("mService")
+ long getStartSeq() {
+ return mStartSeq;
+ }
+
+ @GuardedBy("mService")
+ void setStartSeq(long startSeq) {
+ mStartSeq = startSeq;
+ }
+
+ HostingRecord getHostingRecord() {
+ return mHostingRecord;
+ }
+
+ void setHostingRecord(HostingRecord hostingRecord) {
+ mHostingRecord = hostingRecord;
+ }
+
+ String getSeInfo() {
+ return mSeInfo;
+ }
+
+ void setSeInfo(String seInfo) {
+ mSeInfo = seInfo;
+ }
+
+ long getStartTime() {
+ return mStartTime;
+ }
+
+ void setStartTime(long startTime) {
+ mStartTime = startTime;
+ }
+
+ int getStartUid() {
+ return mStartUid;
+ }
+
+ void setStartUid(int startUid) {
+ mStartUid = startUid;
+ }
+
+ int getMountMode() {
+ return mMountMode;
+ }
+
+ void setMountMode(int mountMode) {
+ mMountMode = mountMode;
+ }
+
+ boolean isBindMountPending() {
+ return mBindMountPending;
+ }
+
+ void setBindMountPending(boolean bindMountPending) {
+ mBindMountPending = bindMountPending;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean isUnlocked() {
+ return mUnlocked;
+ }
+
+ @GuardedBy("mProcLock")
+ void setUnlocked(boolean unlocked) {
+ mUnlocked = unlocked;
+ }
+
+ @GuardedBy("mProcLock")
+ int getRenderThreadTid() {
+ return mRenderThreadTid;
+ }
+
+ @GuardedBy("mProcLock")
+ void setRenderThreadTid(int renderThreadTid) {
+ mRenderThreadTid = renderThreadTid;
+ }
+
+ @GuardedBy("mService")
+ CompatibilityInfo getCompat() {
+ return mCompat;
+ }
+
+ @GuardedBy("mService")
+ void setCompat(CompatibilityInfo compat) {
+ mCompat = compat;
+ }
+
+ @GuardedBy("mService")
+ long[] getDisabledCompatChanges() {
+ return mDisabledCompatChanges;
+ }
+
+ @GuardedBy("mService")
+ void setDisabledCompatChanges(long[] disabledCompatChanges) {
+ mDisabledCompatChanges = disabledCompatChanges;
+ }
+
+ @GuardedBy("mService")
+ void unlinkDeathRecipient() {
+ if (mDeathRecipient != null && mThread != null) {
+ mThread.asBinder().unlinkToDeath(mDeathRecipient, 0);
}
- boolean added = mServices.add(record);
- if (added && record.serviceInfo != null) {
- mWindowProcessController.onServiceStarted(record.serviceInfo);
- }
- return added;
+ mDeathRecipient = null;
}
- /**
- * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method
- * does not actually stop the service, but records the service as stopped for bookkeeping.
- *
- * @return true if the service was removed, false otherwise.
- */
- boolean stopService(ServiceRecord record) {
- return mServices.remove(record);
+ @GuardedBy("mService")
+ void setDeathRecipient(IBinder.DeathRecipient deathRecipient) {
+ mDeathRecipient = deathRecipient;
}
- /**
- * The same as calling {@link #stopService(ServiceRecord)} on all current running services.
- */
- void stopAllServices() {
- mServices.clear();
+ @GuardedBy({"mService", "mProcLock"})
+ void setActiveInstrumentation(ActiveInstrumentation instr) {
+ mInstr = instr;
+ boolean isInstrumenting = instr != null;
+ mWindowProcessController.setInstrumenting(
+ isInstrumenting,
+ isInstrumenting ? instr.mSourceUid : -1,
+ isInstrumenting && instr.mHasBackgroundActivityStartsPermission);
}
- /**
- * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet
- * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}.
- *
- * @see #startService(ServiceRecord)
- * @see #stopService(ServiceRecord)
- */
- int numberOfRunningServices() {
- return mServices.size();
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ActiveInstrumentation getActiveInstrumentation() {
+ return mInstr;
}
- /**
- * Returns the service at the specified {@code index}.
- *
- * @see #numberOfRunningServices()
- */
- ServiceRecord getRunningServiceAt(int index) {
- return mServices.valueAt(index);
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isKilledByAm() {
+ return mKilledByAm;
}
- void setCached(boolean cached) {
- if (mCached != cached) {
- mCached = cached;
- if (cached) {
- ++mCacheOomRankerUseCount;
- }
- }
+ @GuardedBy({"mService", "mProcLock"})
+ void setKilledByAm(boolean killedByAm) {
+ mKilledByAm = killedByAm;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isKilled() {
+ return mKilled;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setKilled(boolean killed) {
+ mKilled = killed;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getKillTime() {
+ return mKillTime;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setKillTime(long killTime) {
+ mKillTime = killTime;
+ }
+
+ @GuardedBy("mService")
+ String getWaitingToKill() {
+ return mWaitingToKill;
+ }
+
+ @GuardedBy("mService")
+ void setWaitingToKill(String waitingToKill) {
+ mWaitingToKill = waitingToKill;
+ }
+
+ @Override
+ public boolean isRemoved() {
+ return mRemoved;
+ }
+
+ void setRemoved(boolean removed) {
+ mRemoved = removed;
+ }
+
+ @GuardedBy("mService")
+ boolean isDebugging() {
+ return mDebugging;
+ }
+
+ @GuardedBy("mService")
+ void setDebugging(boolean debugging) {
+ mDebugging = debugging;
+ mWindowProcessController.setDebugging(debugging);
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasWaitedForDebugger() {
+ return mWaitedForDebugger;
+ }
+
+ @GuardedBy("mProcLock")
+ void setWaitedForDebugger(boolean waitedForDebugger) {
+ mWaitedForDebugger = waitedForDebugger;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getLastActivityTime() {
+ return mLastActivityTime;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setLastActivityTime(long lastActivityTime) {
+ mLastActivityTime = lastActivityTime;
+ }
+
+ @GuardedBy("mService")
+ boolean isUsingWrapper() {
+ return mUsingWrapper;
+ }
+
+ @GuardedBy("mService")
+ void setUsingWrapper(boolean usingWrapper) {
+ mUsingWrapper = usingWrapper;
+ mWindowProcessController.setUsingWrapper(usingWrapper);
+ }
+
+ @GuardedBy("mService")
+ int getLruSeq() {
+ return mLruSeq;
+ }
+
+ @GuardedBy("mService")
+ void setLruSeq(int lruSeq) {
+ mLruSeq = lruSeq;
+ }
+
+ @GuardedBy("mService")
+ String getIsolatedEntryPoint() {
+ return mIsolatedEntryPoint;
+ }
+
+ @GuardedBy("mService")
+ void setIsolatedEntryPoint(String isolatedEntryPoint) {
+ mIsolatedEntryPoint = isolatedEntryPoint;
+ }
+
+ @GuardedBy("mService")
+ String[] getIsolatedEntryPointArgs() {
+ return mIsolatedEntryPointArgs;
+ }
+
+ @GuardedBy("mService")
+ void setIsolatedEntryPointArgs(String[] isolatedEntryPointArgs) {
+ mIsolatedEntryPointArgs = isolatedEntryPointArgs;
+ }
+
+ @GuardedBy("mService")
+ boolean isInFullBackup() {
+ return mInFullBackup;
+ }
+
+ @GuardedBy("mService")
+ void setInFullBackup(boolean inFullBackup) {
+ mInFullBackup = inFullBackup;
}
@Override
public boolean isCached() {
- return mCached;
- }
-
- int getCacheOomRankerUseCount() {
- return mCacheOomRankerUseCount;
+ return mState.isCached();
}
boolean hasActivities() {
@@ -746,6 +888,22 @@ class ProcessRecord implements WindowProcessListener {
return mWindowProcessController.hasRecentTasks();
}
+ @GuardedBy({"mService", "mProcLock"})
+ boolean onCleanupApplicationRecordLSP(ProcessStatsService processStats, boolean allowRestart) {
+ mErrorState.onCleanupApplicationRecordLSP();
+
+ resetPackageList(processStats);
+ unlinkDeathRecipient();
+ makeInactive(processStats);
+ setWaitingToKill(null);
+
+ mState.onCleanupApplicationRecordLSP();
+ mServices.onCleanupApplicationRecordLocked();
+ mReceivers.onCleanupApplicationRecordLocked();
+
+ return mProviders.onCleanupApplicationRecordLocked(allowRestart);
+ }
+
/**
* This method returns true if any of the activities within the process record are interesting
* to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -755,74 +913,26 @@ class ProcessRecord implements WindowProcessListener {
return true;
}
- final int servicesSize = mServices.size();
- for (int i = 0; i < servicesSize; i++) {
- ServiceRecord r = mServices.valueAt(i);
- if (r.isForeground) {
- return true;
- }
- }
- return false;
+ return mServices.hasForegroundServices();
}
- public void unlinkDeathRecipient() {
- if (deathRecipient != null && thread != null) {
- thread.asBinder().unlinkToDeath(deathRecipient, 0);
- }
- deathRecipient = null;
- }
-
- void updateHasAboveClientLocked() {
- hasAboveClient = false;
- for (int i=connections.size()-1; i>=0; i--) {
- ConnectionRecord cr = connections.valueAt(i);
- if ((cr.flags&Context.BIND_ABOVE_CLIENT) != 0) {
- hasAboveClient = true;
- break;
- }
- }
- }
-
- int modifyRawOomAdj(int adj) {
- if (hasAboveClient) {
- // If this process has bound to any services with BIND_ABOVE_CLIENT,
- // then we need to drop its adjustment to be lower than the service's
- // in order to honor the request. We want to drop it by one adjustment
- // level... but there is special meaning applied to various levels so
- // we will skip some of them.
- if (adj < ProcessList.FOREGROUND_APP_ADJ) {
- // System process will not get dropped, ever
- } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
- adj = ProcessList.VISIBLE_APP_ADJ;
- } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
- adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
- adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
- } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
- adj = ProcessList.CACHED_APP_MIN_ADJ;
- } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
- adj++;
- }
- }
- return adj;
- }
-
- void scheduleCrash(String message) {
+ @GuardedBy("mService")
+ void scheduleCrashLocked(String message) {
// Checking killedbyAm should keep it from showing the crash dialog if the process
// was already dead for a good / normal reason.
- if (!killedByAm) {
- if (thread != null) {
- if (pid == Process.myPid()) {
+ if (!mKilledByAm) {
+ if (mThread != null) {
+ if (mPid == Process.myPid()) {
Slog.w(TAG, "scheduleCrash: trying to crash system process!");
return;
}
final long ident = Binder.clearCallingIdentity();
try {
- thread.scheduleCrash(message);
+ mThread.scheduleCrash(message);
} catch (RemoteException e) {
// If it's already dead our work is done. If it's wedged just kill it.
// We won't get the crash dialog or the error reporting.
- kill("scheduleCrash for '" + message + "' failed",
+ killLocked("scheduleCrash for '" + message + "' failed",
ApplicationExitInfo.REASON_CRASH, true);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -831,30 +941,36 @@ class ProcessRecord implements WindowProcessListener {
}
}
- void kill(String reason, @Reason int reasonCode, boolean noisy) {
- kill(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy);
+ @GuardedBy("mService")
+ void killLocked(String reason, @Reason int reasonCode, boolean noisy) {
+ killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy);
}
- void kill(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) {
- if (!killedByAm) {
+ @GuardedBy("mService")
+ void killLocked(String reason, @Reason int reasonCode, @SubReason int subReason,
+ boolean noisy) {
+ if (!mKilledByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) {
mService.reportUidInfoMessageLocked(TAG,
- "Killing " + toShortString() + " (adj " + setAdj + "): " + reason,
- info.uid);
+ "Killing " + toShortString() + " (adj " + mState.getSetAdj()
+ + "): " + reason, info.uid);
}
- if (pid > 0) {
+ if (mPid > 0) {
mService.mProcessList.noteAppKill(this, reasonCode, subReason, reason);
- EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
- Process.killProcessQuiet(pid);
- ProcessList.killProcessGroup(uid, pid);
+ EventLog.writeEvent(EventLogTags.AM_KILL,
+ userId, mPid, processName, mState.getSetAdj(), reason);
+ Process.killProcessQuiet(mPid);
+ ProcessList.killProcessGroup(uid, mPid);
} else {
- pendingStart = false;
+ mPendingStart = false;
}
if (!mPersistent) {
- killed = true;
- killedByAm = true;
- mKillTime = SystemClock.uptimeMillis();
+ synchronized (mProcLock) {
+ mKilled = true;
+ mKilledByAm = true;
+ mKillTime = SystemClock.uptimeMillis();
+ }
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -867,7 +983,7 @@ class ProcessRecord implements WindowProcessListener {
public void dumpDebug(ProtoOutputStream proto, long fieldId, int lruIndex) {
long token = proto.start(fieldId);
- proto.write(ProcessRecordProto.PID, pid);
+ proto.write(ProcessRecordProto.PID, mPid);
proto.write(ProcessRecordProto.PROCESS_NAME, processName);
proto.write(ProcessRecordProto.UID, info.uid);
if (UserHandle.getAppId(info.uid) >= Process.FIRST_APPLICATION_UID) {
@@ -885,16 +1001,17 @@ class ProcessRecord implements WindowProcessListener {
}
public String toShortString() {
+ final String shortStringName = mShortStringName;
if (shortStringName != null) {
return shortStringName;
}
StringBuilder sb = new StringBuilder(128);
toShortString(sb);
- return shortStringName = sb.toString();
+ return mShortStringName = sb.toString();
}
void toShortString(StringBuilder sb) {
- sb.append(pid);
+ sb.append(mPid);
sb.append(':');
sb.append(processName);
sb.append('/');
@@ -919,6 +1036,7 @@ class ProcessRecord implements WindowProcessListener {
}
public String toString() {
+ final String stringName = mStringName;
if (stringName != null) {
return stringName;
}
@@ -928,33 +1046,7 @@ class ProcessRecord implements WindowProcessListener {
sb.append(' ');
toShortString(sb);
sb.append('}');
- return stringName = sb.toString();
- }
-
- public String makeAdjReason() {
- if (adjSource != null || adjTarget != null) {
- StringBuilder sb = new StringBuilder(128);
- sb.append(' ');
- if (adjTarget instanceof ComponentName) {
- sb.append(((ComponentName)adjTarget).flattenToShortString());
- } else if (adjTarget != null) {
- sb.append(adjTarget.toString());
- } else {
- sb.append("{null}");
- }
- sb.append("<=");
- if (adjSource instanceof ProcessRecord) {
- sb.append("Proc{");
- sb.append(((ProcessRecord)adjSource).toShortString());
- sb.append("}");
- } else if (adjSource != null) {
- sb.append(adjSource.toString());
- } else {
- sb.append("{null}");
- }
- return sb.toString();
- }
- return null;
+ return mStringName = sb.toString();
}
/*
@@ -984,29 +1076,6 @@ class ProcessRecord implements WindowProcessListener {
return false;
}
- public int getSetAdjWithServices() {
- if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- if (hasStartedServices) {
- return ProcessList.SERVICE_B_ADJ;
- }
- }
- return setAdj;
- }
-
- public void forceProcessStateUpTo(int newState) {
- if (mRepProcState > newState) {
- mRepProcState = newState;
- setCurProcState(newState);
- setCurRawProcState(newState);
- getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- uid, processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
- }
- }
-
/*
* Delete all packages from list except the package indicated in info
*/
@@ -1062,194 +1131,6 @@ class ProcessRecord implements WindowProcessListener {
return mWindowProcessController;
}
- void setCurrentSchedulingGroup(int curSchedGroup) {
- mCurSchedGroup = curSchedGroup;
- mWindowProcessController.setCurrentSchedulingGroup(curSchedGroup);
- }
-
- int getCurrentSchedulingGroup() {
- return mCurSchedGroup;
- }
-
- void setCurProcState(int curProcState) {
- mCurProcState = curProcState;
- mWindowProcessController.setCurrentProcState(mCurProcState);
- }
-
- int getCurProcState() {
- return mCurProcState;
- }
-
- void setCurRawProcState(int curRawProcState) {
- mCurRawProcState = curRawProcState;
- }
-
- int getCurRawProcState() {
- return mCurRawProcState;
- }
-
- void setReportedProcState(int repProcState) {
- mRepProcState = repProcState;
- getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- uid, processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
- mWindowProcessController.setReportedProcState(repProcState);
- }
-
- int getReportedProcState() {
- return mRepProcState;
- }
-
- void setCrashing(boolean crashing) {
- mCrashing = crashing;
- mWindowProcessController.setCrashing(crashing);
- }
-
- boolean isCrashing() {
- return mCrashing;
- }
-
- void setNotResponding(boolean notResponding) {
- mNotResponding = notResponding;
- mWindowProcessController.setNotResponding(notResponding);
- }
-
- boolean isNotResponding() {
- return mNotResponding;
- }
-
- void setPersistent(boolean persistent) {
- mPersistent = persistent;
- mWindowProcessController.setPersistent(persistent);
- }
-
- boolean isPersistent() {
- return mPersistent;
- }
-
- public void setRequiredAbi(String requiredAbi) {
- mRequiredAbi = requiredAbi;
- mWindowProcessController.setRequiredAbi(requiredAbi);
- }
-
- String getRequiredAbi() {
- return mRequiredAbi;
- }
-
- void setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes) {
- mHasForegroundServices = hasForegroundServices;
- mFgServiceTypes = fgServiceTypes;
- mWindowProcessController.setHasForegroundServices(hasForegroundServices);
- }
-
- boolean hasForegroundServices() {
- return mHasForegroundServices;
- }
-
- boolean hasLocationForegroundServices() {
- return mHasForegroundServices
- && (mFgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0;
- }
-
- boolean hasLocationCapability() {
- return (setCapability & ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0;
- }
-
- int getForegroundServiceTypes() {
- return mHasForegroundServices ? mFgServiceTypes : 0;
- }
-
- int getReportedForegroundServiceTypes() {
- return mRepFgServiceTypes;
- }
-
- void setReportedForegroundServiceTypes(int foregroundServiceTypes) {
- mRepFgServiceTypes = foregroundServiceTypes;
- }
-
- void setHasForegroundActivities(boolean hasForegroundActivities) {
- mHasForegroundActivities = hasForegroundActivities;
- }
-
- boolean hasForegroundActivities() {
- return mHasForegroundActivities;
- }
-
- void setHasClientActivities(boolean hasClientActivities) {
- mHasClientActivities = hasClientActivities;
- mWindowProcessController.setHasClientActivities(hasClientActivities);
- }
-
- boolean hasClientActivities() {
- return mHasClientActivities;
- }
-
- void setHasTopUi(boolean hasTopUi) {
- mHasTopUi = hasTopUi;
- mWindowProcessController.setHasTopUi(hasTopUi);
- }
-
- boolean hasTopUi() {
- return mHasTopUi;
- }
-
- void setHasOverlayUi(boolean hasOverlayUi) {
- mHasOverlayUi = hasOverlayUi;
- mWindowProcessController.setHasOverlayUi(hasOverlayUi);
- }
-
- boolean hasOverlayUi() {
- return mHasOverlayUi;
- }
-
- void setInteractionEventTime(long interactionEventTime) {
- mInteractionEventTime = interactionEventTime;
- mWindowProcessController.setInteractionEventTime(interactionEventTime);
- }
-
- long getInteractionEventTime() {
- return mInteractionEventTime;
- }
-
- void setFgInteractionTime(long fgInteractionTime) {
- mFgInteractionTime = fgInteractionTime;
- mWindowProcessController.setFgInteractionTime(fgInteractionTime);
- }
-
- long getFgInteractionTime() {
- return mFgInteractionTime;
- }
-
- void setWhenUnimportant(long whenUnimportant) {
- mWhenUnimportant = whenUnimportant;
- mWindowProcessController.setWhenUnimportant(whenUnimportant);
- }
-
- long getWhenUnimportant() {
- return mWhenUnimportant;
- }
-
- void setDebugging(boolean debugging) {
- mDebugging = debugging;
- mWindowProcessController.setDebugging(debugging);
- }
-
- boolean isDebugging() {
- return mDebugging;
- }
-
- void setUsingWrapper(boolean usingWrapper) {
- mUsingWrapper = usingWrapper;
- mWindowProcessController.setUsingWrapper(usingWrapper);
- }
-
- boolean isUsingWrapper() {
- return mUsingWrapper;
- }
-
/**
* Allows background activity starts using token {@param entity}. Optionally, you can provide
* {@param originatingToken} if you have one such originating token, this is useful for tracing
@@ -1267,75 +1148,6 @@ class ProcessRecord implements WindowProcessListener {
mWindowProcessController.removeAllowBackgroundActivityStartsToken(entity);
}
- void addBoundClientUid(int clientUid) {
- mBoundClientUids.add(clientUid);
- mWindowProcessController.setBoundClientUids(mBoundClientUids);
- }
-
- void updateBoundClientUids() {
- if (mServices.isEmpty()) {
- clearBoundClientUids();
- return;
- }
- // grab a set of clientUids of all connections of all services
- ArraySet boundClientUids = new ArraySet<>();
- final int serviceCount = mServices.size();
- for (int j = 0; j < serviceCount; j++) {
- ArrayMap> conns =
- mServices.valueAt(j).getConnections();
- final int N = conns.size();
- for (int conni = 0; conni < N; conni++) {
- ArrayList c = conns.valueAt(conni);
- for (int i = 0; i < c.size(); i++) {
- boundClientUids.add(c.get(i).clientUid);
- }
- }
- }
- mBoundClientUids = boundClientUids;
- mWindowProcessController.setBoundClientUids(mBoundClientUids);
- }
-
- void addBoundClientUidsOfNewService(ServiceRecord sr) {
- if (sr == null) {
- return;
- }
- ArrayMap> conns = sr.getConnections();
- for (int conni = conns.size() - 1; conni >= 0; conni--) {
- ArrayList c = conns.valueAt(conni);
- for (int i = 0; i < c.size(); i++) {
- mBoundClientUids.add(c.get(i).clientUid);
- }
- }
- mWindowProcessController.setBoundClientUids(mBoundClientUids);
- }
-
- void clearBoundClientUids() {
- mBoundClientUids.clear();
- mWindowProcessController.setBoundClientUids(mBoundClientUids);
- }
-
- void setActiveInstrumentation(ActiveInstrumentation instr) {
- mInstr = instr;
- boolean isInstrumenting = instr != null;
- mWindowProcessController.setInstrumenting(
- isInstrumenting,
- isInstrumenting ? instr.mSourceUid : -1,
- isInstrumenting && instr.mHasBackgroundActivityStartsPermission);
- }
-
- ActiveInstrumentation getActiveInstrumentation() {
- return mInstr;
- }
-
- void setCurRawAdj(int curRawAdj) {
- mCurRawAdj = curRawAdj;
- mWindowProcessController.setPerceptible(curRawAdj <= ProcessList.PERCEPTIBLE_APP_ADJ);
- }
-
- int getCurRawAdj() {
- return mCurRawAdj;
- }
-
@Override
public void clearProfilerIfNeeded() {
synchronized (mService.mAppProfiler.mProfilerLock) {
@@ -1346,13 +1158,13 @@ class ProcessRecord implements WindowProcessListener {
@Override
public void updateServiceConnectionActivities() {
synchronized (mService) {
- mService.mServices.updateServiceConnectionActivitiesLocked(this);
+ mService.mServices.updateServiceConnectionActivitiesLocked(mServices);
}
}
@Override
public void setPendingUiClean(boolean pendingUiClean) {
- synchronized (mService) {
+ synchronized (mProcLock) {
mProfile.setPendingUiClean(pendingUiClean);
}
}
@@ -1361,7 +1173,7 @@ class ProcessRecord implements WindowProcessListener {
public void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
synchronized (mService) {
setPendingUiClean(true);
- forceProcessStateUpTo(newState);
+ mState.forceProcessStateUpTo(newState);
}
}
@@ -1370,40 +1182,35 @@ class ProcessRecord implements WindowProcessListener {
boolean updateOomAdj) {
synchronized (mService) {
if (updateServiceConnectionActivities) {
- mService.mServices.updateServiceConnectionActivitiesLocked(this);
+ mService.mServices.updateServiceConnectionActivitiesLocked(mServices);
}
- if (thread == null) {
+ if (mThread == null) {
// Only update lru and oom-adj if the process is alive. Because it may be called
// when cleaning up the last activity from handling process died, the dead process
// should not be added to lru list again.
return;
}
- mService.mProcessList.updateLruProcessLocked(this, activityChange, null /* client */);
+ mService.updateLruProcessLocked(this, activityChange, null /* client */);
if (updateOomAdj) {
mService.updateOomAdjLocked(this, OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
}
}
}
- @Override
- public boolean isRemoved() {
- return removed;
- }
-
/**
* Returns the total time (in milliseconds) spent executing in both user and system code.
* Safe to call without lock held.
*/
@Override
public long getCpuTime() {
- return mService.mAppProfiler.getCpuTimeForPid(pid);
+ return mService.mAppProfiler.getCpuTimeForPid(mPid);
}
@Override
public void onStartActivity(int topProcessState, boolean setProfileProc, String packageName,
long versionCode) {
synchronized (mService) {
- waitingToKill = null;
+ mWaitingToKill = null;
if (setProfileProc) {
synchronized (mService.mAppProfiler.mProfilerLock) {
mService.mAppProfiler.setProfileProcLPf(this);
@@ -1416,9 +1223,9 @@ class ProcessRecord implements WindowProcessListener {
// Update oom adj first, we don't want the additional states are involved in this round.
updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */);
- hasShownUi = true;
setPendingUiClean(true);
- forceProcessStateUpTo(topProcessState);
+ mState.setHasShownUi(true);
+ mState.forceProcessStateUpTo(topProcessState);
}
}
@@ -1431,20 +1238,12 @@ class ProcessRecord implements WindowProcessListener {
@Override
public void setRunningRemoteAnimation(boolean runningRemoteAnimation) {
- if (pid == Process.myPid()) {
+ if (mPid == Process.myPid()) {
Slog.wtf(TAG, "system can't run remote animation");
return;
}
synchronized (mService) {
- if (this.runningRemoteAnimation == runningRemoteAnimation) {
- return;
- }
- this.runningRemoteAnimation = runningRemoteAnimation;
- if (DEBUG_OOM_ADJ) {
- Slog.i(TAG, "Setting runningRemoteAnimation=" + runningRemoteAnimation
- + " for pid=" + pid);
- }
- mService.updateOomAdjLocked(this, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+ mState.setRunningRemoteAnimation(runningRemoteAnimation);
}
}
@@ -1453,7 +1252,7 @@ class ProcessRecord implements WindowProcessListener {
}
public int getProcessClassEnum() {
- if (pid == MY_PID) {
+ if (mPid == MY_PID) {
return ServerProtoEnums.SYSTEM_SERVER;
}
if (info == null) {
@@ -1463,701 +1262,9 @@ class ProcessRecord implements WindowProcessListener {
ServerProtoEnums.DATA_APP;
}
- /**
- * Unless configured otherwise, swallow ANRs in background processes & kill the process.
- * Non-private access is for tests only.
- */
- @VisibleForTesting
- boolean isSilentAnr() {
- return !getShowBackground() && !isInterestingForBackgroundTraces();
- }
-
/** Non-private access is for tests only. */
@VisibleForTesting
List getLruProcessList() {
- return mService.mProcessList.mLruProcesses;
- }
-
- /** Non-private access is for tests only. */
- @VisibleForTesting
- boolean isMonitorCpuUsage() {
- return mService.mAppProfiler.MONITOR_CPU_USAGE;
- }
-
- void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
- String parentShortComponentName, WindowProcessController parentProcess,
- boolean aboveSystem, String annotation, boolean onlyDumpSelf) {
- ArrayList firstPids = new ArrayList<>(5);
- SparseArray lastPids = new SparseArray<>(20);
-
- mWindowProcessController.appEarlyNotResponding(annotation, () -> kill("anr",
- ApplicationExitInfo.REASON_ANR, true));
-
- long anrTime = SystemClock.uptimeMillis();
- if (isMonitorCpuUsage()) {
- mService.updateCpuStatsNow();
- }
-
- final boolean isSilentAnr;
- synchronized (mService) {
- // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
- if (mService.mAtmInternal.isShuttingDown()) {
- Slog.i(TAG, "During shutdown skipping ANR: " + this + " " + annotation);
- return;
- } else if (isNotResponding()) {
- Slog.i(TAG, "Skipping duplicate ANR: " + this + " " + annotation);
- return;
- } else if (isCrashing()) {
- Slog.i(TAG, "Crashing app skipping ANR: " + this + " " + annotation);
- return;
- } else if (killedByAm) {
- Slog.i(TAG, "App already killed by AM skipping ANR: " + this + " " + annotation);
- return;
- } else if (killed) {
- Slog.i(TAG, "Skipping died app ANR: " + this + " " + annotation);
- return;
- }
-
- // In case we come through here for the same app before completing
- // this one, mark as anring now so we will bail out.
- setNotResponding(true);
-
- // Log the ANR to the event log.
- EventLog.writeEvent(EventLogTags.AM_ANR, userId, pid, processName, info.flags,
- annotation);
-
- // Dump thread traces as quickly as we can, starting with "interesting" processes.
- firstPids.add(pid);
-
- // Don't dump other PIDs if it's a background ANR or is requested to only dump self.
- isSilentAnr = isSilentAnr();
- if (!isSilentAnr && !onlyDumpSelf) {
- int parentPid = pid;
- if (parentProcess != null && parentProcess.getPid() > 0) {
- parentPid = parentProcess.getPid();
- }
- if (parentPid != pid) firstPids.add(parentPid);
-
- if (MY_PID != pid && MY_PID != parentPid) firstPids.add(MY_PID);
-
- for (int i = getLruProcessList().size() - 1; i >= 0; i--) {
- ProcessRecord r = getLruProcessList().get(i);
- if (r != null && r.thread != null) {
- int myPid = r.pid;
- if (myPid > 0 && myPid != pid && myPid != parentPid && myPid != MY_PID) {
- if (r.isPersistent()) {
- firstPids.add(myPid);
- if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
- } else if (r.treatLikeActivity) {
- firstPids.add(myPid);
- if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
- } else {
- lastPids.put(myPid, Boolean.TRUE);
- if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
- }
- }
- }
- }
- }
- }
-
- // Check if package is still being loaded
- boolean isPackageLoading = false;
- final PackageManagerInternal packageManagerInternal =
- mService.getPackageManagerInternal();
- if (aInfo != null && aInfo.packageName != null) {
- IncrementalStatesInfo incrementalStatesInfo =
- packageManagerInternal.getIncrementalStatesInfo(
- aInfo.packageName, uid, userId);
- if (incrementalStatesInfo != null) {
- isPackageLoading = incrementalStatesInfo.isLoading();
- }
- }
-
- // Log the ANR to the main log.
- StringBuilder info = new StringBuilder();
- info.setLength(0);
- info.append("ANR in ").append(processName);
- if (activityShortComponentName != null) {
- info.append(" (").append(activityShortComponentName).append(")");
- }
- info.append("\n");
- info.append("PID: ").append(pid).append("\n");
- if (annotation != null) {
- info.append("Reason: ").append(annotation).append("\n");
- }
- if (parentShortComponentName != null
- && parentShortComponentName.equals(activityShortComponentName)) {
- info.append("Parent: ").append(parentShortComponentName).append("\n");
- }
-
- if (isPackageLoading) {
- // Report in the main log that the package is still loading
- final float loadingProgress = packageManagerInternal.getIncrementalStatesInfo(
- aInfo.packageName, uid, userId).getProgress();
- info.append("Package is ").append((int) (loadingProgress * 100)).append("% loaded.\n");
- }
-
- StringBuilder report = new StringBuilder();
- report.append(MemoryPressureUtil.currentPsiState());
- ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
-
- // don't dump native PIDs for background ANRs unless it is the process of interest
- String[] nativeProcs = null;
- if (isSilentAnr || onlyDumpSelf) {
- for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
- if (NATIVE_STACKS_OF_INTEREST[i].equals(processName)) {
- nativeProcs = new String[] { processName };
- break;
- }
- }
- } else {
- nativeProcs = NATIVE_STACKS_OF_INTEREST;
- }
-
- int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
- ArrayList nativePids = null;
-
- if (pids != null) {
- nativePids = new ArrayList<>(pids.length);
- for (int i : pids) {
- nativePids.add(i);
- }
- }
-
- // For background ANRs, don't pass the ProcessCpuTracker to
- // avoid spending 1/2 second collecting stats to rank lastPids.
- StringWriter tracesFileException = new StringWriter();
- // To hold the start and end offset to the ANR trace file respectively.
- final long[] offsets = new long[2];
- File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
- isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids,
- nativePids, tracesFileException, offsets);
-
- if (isMonitorCpuUsage()) {
- mService.updateCpuStatsNow();
- mService.mAppProfiler.printCurrentCpuState(report, anrTime);
- info.append(processCpuTracker.printCurrentLoad());
- info.append(report);
- }
- report.append(tracesFileException.getBuffer());
-
- info.append(processCpuTracker.printCurrentState(anrTime));
-
- Slog.e(TAG, info.toString());
- if (tracesFile == null) {
- // There is no trace file, so dump (only) the alleged culprit's threads to the log
- Process.sendSignal(pid, Process.SIGNAL_QUIT);
- } else if (offsets[1] > 0) {
- // We've dumped into the trace file successfully
- mService.mProcessList.mAppExitInfoTracker.scheduleLogAnrTrace(
- pid, uid, getPackageList(), tracesFile, offsets[0], offsets[1]);
- }
-
- FrameworkStatsLog.write(FrameworkStatsLog.ANR_OCCURRED, uid, processName,
- activityShortComponentName == null ? "unknown": activityShortComponentName,
- annotation,
- (this.info != null) ? (this.info.isInstantApp()
- ? FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
- : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
- : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
- isInterestingToUserLocked()
- ? FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
- : FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND,
- getProcessClassEnum(),
- (this.info != null) ? this.info.packageName : "", isPackageLoading);
- final ProcessRecord parentPr = parentProcess != null
- ? (ProcessRecord) parentProcess.mOwner : null;
- mService.addErrorToDropBox("anr", this, processName, activityShortComponentName,
- parentShortComponentName, parentPr, annotation, report.toString(), tracesFile,
- null);
-
- if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr",
- ApplicationExitInfo.REASON_ANR, true),
- () -> {
- synchronized (mService) {
- mService.mServices.scheduleServiceTimeoutLocked(this);
- }
- })) {
- return;
- }
-
- synchronized (mService) {
- // mBatteryStatsService can be null if the AMS is constructed with injector only. This
- // will only happen in tests.
- if (mService.mBatteryStatsService != null) {
- mService.mBatteryStatsService.noteProcessAnr(processName, uid);
- }
-
- if (isSilentAnr() && !isDebugging()) {
- kill("bg anr", ApplicationExitInfo.REASON_ANR, true);
- return;
- }
-
- // Set the app's notResponding state, and look up the errorReportReceiver
- makeAppNotRespondingLocked(activityShortComponentName,
- annotation != null ? "ANR " + annotation : "ANR", info.toString());
-
- // Notify package manager service to possibly update package state
- if (aInfo != null && aInfo.packageName != null) {
- packageManagerInternal.notifyPackageCrashOrAnr(aInfo.packageName);
- }
-
- // mUiHandler can be null if the AMS is constructed with injector only. This will only
- // happen in tests.
- if (mService.mUiHandler != null) {
- // Bring up the infamous App Not Responding dialog
- Message msg = Message.obtain();
- msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
- msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
-
- mService.mUiHandler.sendMessage(msg);
- }
- }
- }
-
- private void makeAppNotRespondingLocked(String activity, String shortMsg, String longMsg) {
- setNotResponding(true);
- // mAppErrors can be null if the AMS is constructed with injector only. This will only
- // happen in tests.
- if (mService.mAppErrors != null) {
- notRespondingReport = mService.mAppErrors.generateProcessError(this,
- ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
- activity, shortMsg, longMsg, null);
- }
- startAppProblemLocked();
- getWindowProcessController().stopFreezingActivities();
- }
-
- void startAppProblemLocked() {
- // If this app is not running under the current user, then we can't give it a report button
- // because that would require launching the report UI under a different user.
- errorReportReceiver = null;
-
- for (int userId : mService.mUserController.getCurrentProfileIds()) {
- if (this.userId == userId) {
- errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
- mService.mContext, info.packageName, info.flags);
- }
- }
- mService.skipCurrentReceiverLocked(this);
- }
-
- private boolean isInterestingForBackgroundTraces() {
- // The system_server is always considered interesting.
- if (pid == MY_PID) {
- return true;
- }
-
- // A package is considered interesting if any of the following is true :
- //
- // - It's displaying an activity.
- // - It's the SystemUI.
- // - It has an overlay or a top UI visible.
- //
- // NOTE: The check whether a given ProcessRecord belongs to the systemui
- // process is a bit of a kludge, but the same pattern seems repeated at
- // several places in the system server.
- return isInterestingToUserLocked() ||
- (info != null && "com.android.systemui".equals(info.packageName))
- || (hasTopUi() || hasOverlayUi());
- }
-
- private boolean getShowBackground() {
- return Settings.Secure.getInt(mService.mContext.getContentResolver(),
- Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
- }
-
- void resetCachedInfo() {
- mCachedHasActivities = VALUE_INVALID;
- mCachedIsHeavyWeight = VALUE_INVALID;
- mCachedHasVisibleActivities = VALUE_INVALID;
- mCachedIsHomeProcess = VALUE_INVALID;
- mCachedIsPreviousProcess = VALUE_INVALID;
- mCachedHasRecentTasks = VALUE_INVALID;
- mCachedIsReceivingBroadcast = VALUE_INVALID;
- mCachedAdj = ProcessList.INVALID_ADJ;
- mCachedForegroundActivities = false;
- mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
- mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- }
-
- boolean getCachedHasActivities() {
- if (mCachedHasActivities == VALUE_INVALID) {
- mCachedHasActivities = getWindowProcessController().hasActivities() ? VALUE_TRUE
- : VALUE_FALSE;
- }
- return mCachedHasActivities == VALUE_TRUE;
- }
-
- boolean getCachedIsHeavyWeight() {
- if (mCachedIsHeavyWeight == VALUE_INVALID) {
- mCachedIsHeavyWeight = getWindowProcessController().isHeavyWeightProcess()
- ? VALUE_TRUE : VALUE_FALSE;
- }
- return mCachedIsHeavyWeight == VALUE_TRUE;
- }
-
- boolean getCachedHasVisibleActivities() {
- if (mCachedHasVisibleActivities == VALUE_INVALID) {
- mCachedHasVisibleActivities = getWindowProcessController().hasVisibleActivities()
- ? VALUE_TRUE : VALUE_FALSE;
- }
- return mCachedHasVisibleActivities == VALUE_TRUE;
- }
-
- boolean getCachedIsHomeProcess() {
- if (mCachedIsHomeProcess == VALUE_INVALID) {
- if (getWindowProcessController().isHomeProcess()) {
- mCachedIsHomeProcess = VALUE_TRUE;
- mService.mAppProfiler.mHasHomeProcess = true;
- } else {
- mCachedIsHomeProcess = VALUE_FALSE;
- }
- }
- return mCachedIsHomeProcess == VALUE_TRUE;
- }
-
- boolean getCachedIsPreviousProcess() {
- if (mCachedIsPreviousProcess == VALUE_INVALID) {
- if (getWindowProcessController().isPreviousProcess()) {
- mCachedIsPreviousProcess = VALUE_TRUE;
- mService.mAppProfiler.mHasPreviousProcess = true;
- } else {
- mCachedIsPreviousProcess = VALUE_FALSE;
- }
- }
- return mCachedIsPreviousProcess == VALUE_TRUE;
- }
-
- boolean getCachedHasRecentTasks() {
- if (mCachedHasRecentTasks == VALUE_INVALID) {
- mCachedHasRecentTasks = getWindowProcessController().hasRecentTasks()
- ? VALUE_TRUE : VALUE_FALSE;
- }
- return mCachedHasRecentTasks == VALUE_TRUE;
- }
-
- boolean getCachedIsReceivingBroadcast(ArraySet tmpQueue) {
- if (mCachedIsReceivingBroadcast == VALUE_INVALID) {
- tmpQueue.clear();
- mCachedIsReceivingBroadcast = mService.isReceivingBroadcastLocked(this, tmpQueue)
- ? VALUE_TRUE : VALUE_FALSE;
- if (mCachedIsReceivingBroadcast == VALUE_TRUE) {
- mCachedSchedGroup = tmpQueue.contains(mService.mFgBroadcastQueue)
- ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
- }
- }
- return mCachedIsReceivingBroadcast == VALUE_TRUE;
- }
-
- void computeOomAdjFromActivitiesIfNecessary(OomAdjuster.ComputeOomAdjWindowCallback callback,
- int adj, boolean foregroundActivities, int procState, int schedGroup, int appUid,
- int logUid, int processCurTop) {
- if (mCachedAdj != ProcessList.INVALID_ADJ) {
- return;
- }
- callback.initialize(this, adj, foregroundActivities, procState, schedGroup, appUid, logUid,
- processCurTop);
- final int minLayer = Math.min(ProcessList.VISIBLE_APP_LAYER_MAX,
- getWindowProcessController().computeOomAdjFromActivities(callback));
-
- mCachedAdj = callback.adj;
- mCachedForegroundActivities = callback.foregroundActivities;
- mCachedProcState = callback.procState;
- mCachedSchedGroup = callback.schedGroup;
-
- if (mCachedAdj == ProcessList.VISIBLE_APP_ADJ) {
- mCachedAdj += minLayer;
- }
- }
-
- public void addAllowBackgroundFgsStartsToken(Binder entity) {
- mBackgroundFgsStartTokens.add(entity);
- }
-
- public void removeAllowBackgroundFgsStartsToken(Binder entity) {
- mBackgroundFgsStartTokens.remove(entity);
- }
-
- public boolean areBackgroundFgsStartsAllowedByToken() {
- return !mBackgroundFgsStartTokens.isEmpty();
- }
-
- ErrorDialogController getDialogController() {
- return mDialogController;
- }
-
- void resetAllowStartFgs() {
- mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
- mAllowStartFgs = mAllowStartFgsByPermission;
- }
-
- void bumpAllowStartFgsState(int newProcState) {
- if (newProcState < mAllowStartFgsState) {
- mAllowStartFgsState = newProcState;
- }
- }
-
- void setAllowStartFgsByPermission() {
- int ret = FGS_FEATURE_DENIED;
- if (ret == FGS_FEATURE_DENIED) {
- boolean isSystem = false;
- final int uid = UserHandle.getAppId(info.uid);
- switch (uid) {
- case ROOT_UID:
- case SYSTEM_UID:
- case NFC_UID:
- case SHELL_UID:
- isSystem = true;
- break;
- default:
- isSystem = false;
- break;
- }
-
- if (isSystem) {
- ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
- }
- }
-
- if (ret == FGS_FEATURE_DENIED) {
- if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
- info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
- } else if (ActivityManager.checkComponentPermission(
- START_FOREGROUND_SERVICES_FROM_BACKGROUND,
- info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
- } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW,
- info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
- }
- }
- mAllowStartFgs = mAllowStartFgsByPermission = ret;
- }
-
- boolean isAllowedStartFgsState() {
- return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- }
-
- void setAllowStartFgs() {
- if (mAllowStartFgs != FGS_FEATURE_DENIED) {
- return;
- }
- if (mAllowStartFgs == FGS_FEATURE_DENIED) {
- if (isAllowedStartFgsState()) {
- mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
- }
- }
-
- if (mAllowStartFgs == FGS_FEATURE_DENIED) {
- // Is the calling UID a device owner app?
- if (mService.mInternal != null) {
- if (mService.mInternal.isDeviceOwner(info.uid)) {
- mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
- }
- }
- }
-
- if (mAllowStartFgs == FGS_FEATURE_DENIED) {
- if (mService.mInternal != null) {
- final boolean isCompanionApp = mService.mInternal.isAssociatedCompanionApp(
- UserHandle.getUserId(info.uid), info.uid);
- if (isCompanionApp) {
- mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
- }
- }
- }
-
- if (mAllowStartFgs == FGS_FEATURE_DENIED) {
- // Is the calling UID a profile owner app?
- if (mService.mInternal != null) {
- if (mService.mInternal.isProfileOwner(info.uid)) {
- mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
- }
- }
- }
-
- if (mAllowStartFgs == FGS_FEATURE_DENIED) {
- // uid is on DeviceIdleController's user/system allowlist
- // or AMS's FgsStartTempAllowList.
- if (mService.isAllowlistedForFgsStartLocked(info.uid)) {
- mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
- }
- }
- }
-
- /** A controller to generate error dialogs in {@link ProcessRecord} */
- class ErrorDialogController {
- /** dialogs being displayed due to crash */
- private List mCrashDialogs;
- /** dialogs being displayed due to app not responding */
- private List mAnrDialogs;
- /** dialogs displayed due to strict mode violation */
- private List mViolationDialogs;
- /** current wait for debugger dialog */
- private AppWaitingForDebuggerDialog mWaitDialog;
-
- boolean hasCrashDialogs() {
- return mCrashDialogs != null;
- }
-
- boolean hasAnrDialogs() {
- return mAnrDialogs != null;
- }
-
- boolean hasViolationDialogs() {
- return mViolationDialogs != null;
- }
-
- boolean hasDebugWaitingDialog() {
- return mWaitDialog != null;
- }
-
- void clearAllErrorDialogs() {
- clearCrashDialogs();
- clearAnrDialogs();
- clearViolationDialogs();
- clearWaitingDialog();
- }
-
- void clearCrashDialogs() {
- clearCrashDialogs(true /* needDismiss */);
- }
-
- void clearCrashDialogs(boolean needDismiss) {
- if (mCrashDialogs == null) {
- return;
- }
- if (needDismiss) {
- forAllDialogs(mCrashDialogs, Dialog::dismiss);
- }
- mCrashDialogs = null;
- }
-
- void clearAnrDialogs() {
- if (mAnrDialogs == null) {
- return;
- }
- forAllDialogs(mAnrDialogs, Dialog::dismiss);
- mAnrDialogs = null;
- }
-
- void clearViolationDialogs() {
- if (mViolationDialogs == null) {
- return;
- }
- forAllDialogs(mViolationDialogs, Dialog::dismiss);
- mViolationDialogs = null;
- }
-
- void clearWaitingDialog() {
- if (mWaitDialog == null) {
- return;
- }
- mWaitDialog.dismiss();
- mWaitDialog = null;
- }
-
- void forAllDialogs(List extends BaseErrorDialog> dialogs, Consumer c) {
- for (int i = dialogs.size() - 1; i >= 0; i--) {
- c.accept(dialogs.get(i));
- }
- }
-
- void showCrashDialogs(AppErrorDialog.Data data) {
- List contexts = getDisplayContexts(false /* lastUsedOnly */);
- mCrashDialogs = new ArrayList<>();
- for (int i = contexts.size() - 1; i >= 0; i--) {
- final Context c = contexts.get(i);
- mCrashDialogs.add(new AppErrorDialog(c, mService, data));
- }
- mService.mUiHandler.post(() -> {
- List dialogs;
- synchronized (mService) {
- dialogs = mCrashDialogs;
- }
- if (dialogs != null) {
- forAllDialogs(dialogs, Dialog::show);
- }
- });
- }
-
- void showAnrDialogs(AppNotRespondingDialog.Data data) {
- List contexts = getDisplayContexts(isSilentAnr() /* lastUsedOnly */);
- mAnrDialogs = new ArrayList<>();
- for (int i = contexts.size() - 1; i >= 0; i--) {
- final Context c = contexts.get(i);
- mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
- }
- mService.mUiHandler.post(() -> {
- List dialogs;
- synchronized (mService) {
- dialogs = mAnrDialogs;
- }
- if (dialogs != null) {
- forAllDialogs(dialogs, Dialog::show);
- }
- });
- }
-
- void showViolationDialogs(AppErrorResult res) {
- List contexts = getDisplayContexts(false /* lastUsedOnly */);
- mViolationDialogs = new ArrayList<>();
- for (int i = contexts.size() - 1; i >= 0; i--) {
- final Context c = contexts.get(i);
- mViolationDialogs.add(
- new StrictModeViolationDialog(c, mService, res, ProcessRecord.this));
- }
- mService.mUiHandler.post(() -> {
- List dialogs;
- synchronized (mService) {
- dialogs = mViolationDialogs;
- }
- if (dialogs != null) {
- forAllDialogs(dialogs, Dialog::show);
- }
- });
- }
-
- void showDebugWaitingDialogs() {
- List contexts = getDisplayContexts(true /* lastUsedOnly */);
- final Context c = contexts.get(0);
- mWaitDialog = new AppWaitingForDebuggerDialog(mService, c, ProcessRecord.this);
-
- mService.mUiHandler.post(() -> {
- Dialog dialog;
- synchronized (mService) {
- dialog = mWaitDialog;
- }
- if (dialog != null) {
- dialog.show();
- }
- });
- }
-
- /**
- * Helper function to collect contexts from crashed app located displays
- *
- * @param lastUsedOnly Sets to {@code true} to indicate to only get last used context.
- * Sets to {@code false} to collect contexts from crashed app located
- * displays.
- *
- * @return display context list
- */
- private List getDisplayContexts(boolean lastUsedOnly) {
- List displayContexts = new ArrayList<>();
- if (!lastUsedOnly) {
- mWindowProcessController.getDisplayContextsWithErrorDialogs(displayContexts);
- }
- // If there is no foreground window display, fallback to last used display.
- if (displayContexts.isEmpty() || lastUsedOnly) {
- displayContexts.add(mService.mWmInternal != null
- ? mService.mWmInternal.getTopFocusedDisplayUiContext()
- : mService.mUiContext);
- }
- return displayContexts;
- }
+ return mService.mProcessList.getLruProcessesLOSP();
}
}
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
new file mode 100644
index 0000000000000..5c3bf605f71a0
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.IBinder;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * The state info of all services in the process.
+ */
+final class ProcessServiceRecord {
+ /**
+ * Are there any client services with activities?
+ */
+ private boolean mHasClientActivities;
+
+ /**
+ * Running any services that are foreground?
+ */
+ private boolean mHasForegroundServices;
+
+ /**
+ * Service that applied current connectionGroup/Importance.
+ */
+ private ServiceRecord mConnectionService;
+
+ /**
+ * Last group set by a connection.
+ */
+ private int mConnectionGroup;
+
+ /**
+ * Last importance set by a connection.
+ */
+ private int mConnectionImportance;
+
+ /**
+ * Type of foreground service, if there is a foreground service.
+ */
+ private int mFgServiceTypes;
+
+ /**
+ * Last reported foreground service types.
+ */
+ private int mRepFgServiceTypes;
+
+ /**
+ * Bound using BIND_ABOVE_CLIENT, so want to be lower.
+ */
+ private boolean mHasAboveClient;
+
+ /**
+ * Bound using BIND_TREAT_LIKE_ACTIVITY.
+ */
+ private boolean mTreatLikeActivity;
+
+ /**
+ * Do we need to be executing services in the foreground?
+ */
+ private boolean mExecServicesFg;
+
+ /**
+ * App is allowed to manage allowlists such as temporary Power Save mode allowlist.
+ */
+ boolean mAllowlistManager;
+
+ /**
+ * All ServiceRecord running in this process.
+ */
+ private final ArraySet mServices = new ArraySet<>();
+
+ /**
+ * Services that are currently executing code (need to remain foreground).
+ */
+ private final ArraySet mExecutingServices = new ArraySet<>();
+
+ /**
+ * All ConnectionRecord this process holds.
+ */
+ private final ArraySet mConnections = new ArraySet<>();
+
+ /**
+ * A set of UIDs of all bound clients.
+ */
+ private ArraySet mBoundClientUids = new ArraySet<>();
+
+ final ProcessRecord mApp;
+
+ private final ActivityManagerService mService;
+
+ ProcessServiceRecord(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ }
+
+ void setHasClientActivities(boolean hasClientActivities) {
+ mHasClientActivities = hasClientActivities;
+ mApp.getWindowProcessController().setHasClientActivities(hasClientActivities);
+ }
+
+ boolean hasClientActivities() {
+ return mHasClientActivities;
+ }
+
+ void setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes) {
+ mHasForegroundServices = hasForegroundServices;
+ mFgServiceTypes = fgServiceTypes;
+ mApp.getWindowProcessController().setHasForegroundServices(hasForegroundServices);
+ }
+
+ boolean hasForegroundServices() {
+ return mHasForegroundServices;
+ }
+
+ int getForegroundServiceTypes() {
+ return mHasForegroundServices ? mFgServiceTypes : 0;
+ }
+
+ int getReportedForegroundServiceTypes() {
+ return mRepFgServiceTypes;
+ }
+
+ void setReportedForegroundServiceTypes(int foregroundServiceTypes) {
+ mRepFgServiceTypes = foregroundServiceTypes;
+ }
+
+ ServiceRecord getConnectionService() {
+ return mConnectionService;
+ }
+
+ void setConnectionService(ServiceRecord connectionService) {
+ mConnectionService = connectionService;
+ }
+
+ int getConnectionGroup() {
+ return mConnectionGroup;
+ }
+
+ void setConnectionGroup(int connectionGroup) {
+ mConnectionGroup = connectionGroup;
+ }
+
+ int getConnectionImportance() {
+ return mConnectionImportance;
+ }
+
+ void setConnectionImportance(int connectionImportance) {
+ mConnectionImportance = connectionImportance;
+ }
+
+ void updateHasAboveClientLocked() {
+ mHasAboveClient = false;
+ for (int i = mConnections.size() - 1; i >= 0; i--) {
+ ConnectionRecord cr = mConnections.valueAt(i);
+ if ((cr.flags & Context.BIND_ABOVE_CLIENT) != 0) {
+ mHasAboveClient = true;
+ break;
+ }
+ }
+ }
+
+ void setHasAboveClient(boolean hasAboveClient) {
+ mHasAboveClient = hasAboveClient;
+ }
+
+ boolean hasAboveClient() {
+ return mHasAboveClient;
+ }
+
+ int modifyRawOomAdj(int adj) {
+ if (mHasAboveClient) {
+ // If this process has bound to any services with BIND_ABOVE_CLIENT,
+ // then we need to drop its adjustment to be lower than the service's
+ // in order to honor the request. We want to drop it by one adjustment
+ // level... but there is special meaning applied to various levels so
+ // we will skip some of them.
+ if (adj < ProcessList.FOREGROUND_APP_ADJ) {
+ // System process will not get dropped, ever
+ } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
+ adj = ProcessList.VISIBLE_APP_ADJ;
+ } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+ } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
+ adj = ProcessList.CACHED_APP_MIN_ADJ;
+ } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
+ adj++;
+ }
+ }
+ return adj;
+ }
+
+ boolean isTreatedLikeActivity() {
+ return mTreatLikeActivity;
+ }
+
+ void setTreatLikeActivity(boolean treatLikeActivity) {
+ mTreatLikeActivity = treatLikeActivity;
+ }
+
+ boolean shouldExecServicesFg() {
+ return mExecServicesFg;
+ }
+
+ void setExecServicesFg(boolean execServicesFg) {
+ mExecServicesFg = execServicesFg;
+ }
+
+ /**
+ * Records a service as running in the process. Note that this method does not actually start
+ * the service, but records the service as started for bookkeeping.
+ *
+ * @return true if the service was added, false otherwise.
+ */
+ boolean startService(ServiceRecord record) {
+ if (record == null) {
+ return false;
+ }
+ boolean added = mServices.add(record);
+ if (added && record.serviceInfo != null) {
+ mApp.getWindowProcessController().onServiceStarted(record.serviceInfo);
+ }
+ return added;
+ }
+
+ /**
+ * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method
+ * does not actually stop the service, but records the service as stopped for bookkeeping.
+ *
+ * @return true if the service was removed, false otherwise.
+ */
+ boolean stopService(ServiceRecord record) {
+ return mServices.remove(record);
+ }
+
+ /**
+ * The same as calling {@link #stopService(ServiceRecord)} on all current running services.
+ */
+ void stopAllServices() {
+ mServices.clear();
+ }
+
+ /**
+ * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet
+ * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}.
+ *
+ * @see #startService(ServiceRecord)
+ * @see #stopService(ServiceRecord)
+ */
+ int numberOfRunningServices() {
+ return mServices.size();
+ }
+
+ /**
+ * Returns the service at the specified {@code index}.
+ *
+ * @see #numberOfRunningServices()
+ */
+ ServiceRecord getRunningServiceAt(int index) {
+ return mServices.valueAt(index);
+ }
+
+ void startExecutingService(ServiceRecord service) {
+ mExecutingServices.add(service);
+ }
+
+ void stopExecutingService(ServiceRecord service) {
+ mExecutingServices.remove(service);
+ }
+
+ void stopAllExecutingServices() {
+ mExecutingServices.clear();
+ }
+
+ ServiceRecord getExecutingServiceAt(int index) {
+ return mExecutingServices.valueAt(index);
+ }
+
+ int numberOfExecutingServices() {
+ return mExecutingServices.size();
+ }
+
+ void addConnection(ConnectionRecord connection) {
+ mConnections.add(connection);
+ }
+
+ void removeConnection(ConnectionRecord connection) {
+ mConnections.remove(connection);
+ }
+
+ void removeAllConnections() {
+ mConnections.clear();
+ }
+
+ ConnectionRecord getConnectionAt(int index) {
+ return mConnections.valueAt(index);
+ }
+
+ int numberOfConnections() {
+ return mConnections.size();
+ }
+
+ void addBoundClientUid(int clientUid) {
+ mBoundClientUids.add(clientUid);
+ mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
+ }
+
+ void updateBoundClientUids() {
+ if (mServices.isEmpty()) {
+ clearBoundClientUids();
+ return;
+ }
+ // grab a set of clientUids of all mConnections of all services
+ final ArraySet boundClientUids = new ArraySet<>();
+ final int serviceCount = mServices.size();
+ for (int j = 0; j < serviceCount; j++) {
+ final ArrayMap> conns =
+ mServices.valueAt(j).getConnections();
+ final int size = conns.size();
+ for (int conni = 0; conni < size; conni++) {
+ ArrayList c = conns.valueAt(conni);
+ for (int i = 0; i < c.size(); i++) {
+ boundClientUids.add(c.get(i).clientUid);
+ }
+ }
+ }
+ mBoundClientUids = boundClientUids;
+ mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
+ }
+
+ void addBoundClientUidsOfNewService(ServiceRecord sr) {
+ if (sr == null) {
+ return;
+ }
+ ArrayMap> conns = sr.getConnections();
+ for (int conni = conns.size() - 1; conni >= 0; conni--) {
+ ArrayList c = conns.valueAt(conni);
+ for (int i = 0; i < c.size(); i++) {
+ mBoundClientUids.add(c.get(i).clientUid);
+ }
+ }
+ mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
+ }
+
+ void clearBoundClientUids() {
+ mBoundClientUids.clear();
+ mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
+ }
+
+ @GuardedBy("mService")
+ boolean incServiceCrashCountLocked(long now) {
+ final boolean procIsBoundForeground = mApp.mState.getCurProcState()
+ == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ boolean tryAgain = false;
+ // Bump up the crash count of any services currently running in the proc.
+ for (int i = numberOfRunningServices() - 1; i >= 0; i--) {
+ // Any services running in the application need to be placed
+ // back in the pending list.
+ ServiceRecord sr = getRunningServiceAt(i);
+ // If the service was restarted a while ago, then reset crash count, else increment it.
+ if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
+ sr.crashCount = 1;
+ } else {
+ sr.crashCount++;
+ }
+ // Allow restarting for started or bound foreground services that are crashing.
+ // This includes wallpapers.
+ if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
+ && (sr.isForeground || procIsBoundForeground)) {
+ tryAgain = true;
+ }
+ }
+ return tryAgain;
+ }
+
+ @GuardedBy("mService")
+ void onCleanupApplicationRecordLocked() {
+ mTreatLikeActivity = false;
+ mHasAboveClient = false;
+ setHasClientActivities(false);
+ }
+
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ if (mHasForegroundServices || mApp.mState.getForcingToImportant() != null) {
+ pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
+ pw.print(" forcingToImportant="); pw.println(mApp.mState.getForcingToImportant());
+ }
+ if (mHasClientActivities || mHasAboveClient || mTreatLikeActivity) {
+ pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities);
+ pw.print(" hasAboveClient="); pw.print(mHasAboveClient);
+ pw.print(" treatLikeActivity="); pw.println(mTreatLikeActivity);
+ }
+ if (mConnectionService != null || mConnectionGroup != 0) {
+ pw.print(prefix); pw.print("connectionGroup="); pw.print(mConnectionGroup);
+ pw.print(" Importance="); pw.print(mConnectionImportance);
+ pw.print(" Service="); pw.println(mConnectionService);
+ }
+ if (mAllowlistManager) {
+ pw.print(prefix); pw.print("allowlistManager="); pw.println(mAllowlistManager);
+ }
+ if (mServices.size() > 0) {
+ pw.print(prefix); pw.println("Services:");
+ for (int i = 0, size = mServices.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mServices.valueAt(i));
+ }
+ }
+ if (mExecutingServices.size() > 0) {
+ pw.print(prefix); pw.print("Executing Services (fg=");
+ pw.print(mExecServicesFg); pw.println(")");
+ for (int i = 0, size = mExecutingServices.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mExecutingServices.valueAt(i));
+ }
+ }
+ if (mConnections.size() > 0) {
+ pw.print(prefix); pw.println("mConnections:");
+ for (int i = 0, size = mConnections.size(); i < size; i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mConnections.valueAt(i));
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
new file mode 100644
index 0000000000000..e1a153dfa9203
--- /dev/null
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -0,0 +1,1337 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
+import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
+import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
+import static com.android.server.am.ActiveServices.FGS_FEATURE_DENIED;
+import static com.android.server.am.ActiveServices.fgsCodeToString;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
+import static com.android.server.am.ProcessRecord.TAG;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.os.Binder;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.CompositeRWLock;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.FrameworkStatsLog;
+
+
+import java.io.PrintWriter;
+
+/**
+ * The state info of the process, including proc state, oom adj score, et al.
+ */
+final class ProcessStateRecord {
+ private final ProcessRecord mApp;
+ private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
+
+ /**
+ * Maximum OOM adjustment for this process.
+ */
+ @GuardedBy("mService")
+ private int mMaxAdj = ProcessList.UNKNOWN_ADJ;
+
+ /**
+ * Current OOM unlimited adjustment for this process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurRawAdj = ProcessList.INVALID_ADJ;
+
+ /**
+ * Last set OOM unlimited adjustment for this process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetRawAdj = ProcessList.INVALID_ADJ;
+
+ /**
+ * Current OOM adjustment for this process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurAdj = ProcessList.INVALID_ADJ;
+
+ /**
+ * Last set OOM adjustment for this process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetAdj = ProcessList.INVALID_ADJ;
+
+ /**
+ * The last adjustment that was verified as actually being set.
+ */
+ @GuardedBy("mService")
+ private int mVerifiedAdj = ProcessList.INVALID_ADJ;
+
+ /**
+ * Current capability flags of this process.
+ * For example, PROCESS_CAPABILITY_FOREGROUND_LOCATION is one capability.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurCapability = PROCESS_CAPABILITY_NONE;
+
+ /**
+ * Last set capability flags.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetCapability = PROCESS_CAPABILITY_NONE;
+
+ /**
+ * Currently desired scheduling class.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+
+ /**
+ * Last set to background scheduling class.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+
+ /**
+ * Currently computed process state.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurProcState = PROCESS_STATE_NONEXISTENT;
+
+ /**
+ * Last reported process state.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mRepProcState = PROCESS_STATE_NONEXISTENT;
+
+ /**
+ * Temp state during computation.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurRawProcState = PROCESS_STATE_NONEXISTENT;
+
+ /**
+ * Last set process state in process tracker.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetProcState = PROCESS_STATE_NONEXISTENT;
+
+ /**
+ * Last time mSetProcState changed.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mLastStateTime;
+
+ /**
+ * Previous priority value if we're switching to non-SCHED_OTHER.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSavedPriority;
+
+ /**
+ * Process currently is on the service B list.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mServiceB;
+
+ /**
+ * We are forcing to service B list due to its RAM use.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mServiceHighRam;
+
+ /**
+ * Has this process not been in a cached state since last idle?
+ */
+ @GuardedBy("mProcLock")
+ private boolean mNotCachedSinceIdle;
+
+ /**
+ * Are there any started services running in this process?
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mHasStartedServices;
+
+ /**
+ * Running any activities that are foreground?
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mHasForegroundActivities;
+
+ /**
+ * Last reported foreground activities.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mRepForegroundActivities;
+
+ /**
+ * Has UI been shown in this process since it was started?
+ */
+ @GuardedBy("mService")
+ private boolean mHasShownUi;
+
+ /**
+ * Is this process currently showing a non-activity UI that the user
+ * is interacting with? E.g. The status bar when it is expanded, but
+ * not when it is minimized. When true the
+ * process will be set to use the ProcessList#SCHED_GROUP_TOP_APP
+ * scheduling group to boost performance.
+ */
+ @GuardedBy("mService")
+ private boolean mHasTopUi;
+
+ /**
+ * Is the process currently showing a non-activity UI that
+ * overlays on-top of activity UIs on screen. E.g. display a window
+ * of type android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
+ * When true the process will oom adj score will be set to
+ * ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
+ * of the process getting killed.
+ */
+ @GuardedBy("mService")
+ private boolean mHasOverlayUi;
+
+ /**
+ * Is the process currently running a RemoteAnimation? When true
+ * the process will be set to use the
+ * ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost
+ * performance, as well as oom adj score will be set to
+ * ProcessList#VISIBLE_APP_ADJ at minimum to reduce the chance
+ * of the process getting killed.
+ */
+ @GuardedBy("mService")
+ private boolean mRunningRemoteAnimation;
+
+ /**
+ * Keep track of whether we changed 'mSetAdj'.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mProcStateChanged;
+
+ /**
+ * Whether we have told usage stats about it being an interaction.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mReportedInteraction;
+
+ /**
+ * The time we sent the last interaction event.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mInteractionEventTime;
+
+ /**
+ * When we became foreground for interaction purposes.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mFgInteractionTime;
+
+ /**
+ * Token that is forcing this process to be important.
+ */
+ @GuardedBy("mService")
+ private Object mForcingToImportant;
+
+ /**
+ * Sequence id for identifying oom_adj assignment cycles.
+ */
+ @GuardedBy("mService")
+ private int mAdjSeq;
+
+ /**
+ * Sequence id for identifying oom_adj assignment cycles.
+ */
+ @GuardedBy("mService")
+ private int mCompletedAdjSeq;
+
+ /**
+ * Whether this app has encountered a cycle in the most recent update.
+ */
+ @GuardedBy("mService")
+ private boolean mContainsCycle;
+
+ /**
+ * When (uptime) the process last became unimportant.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mWhenUnimportant;
+
+ /**
+ * The last time the process was in the TOP state or greater.
+ */
+ @GuardedBy("mService")
+ private long mLastTopTime;
+
+ /**
+ * Is this an empty background process?
+ */
+ @GuardedBy("mService")
+ private boolean mEmpty;
+
+ /**
+ * Is this a cached process?
+ */
+ @GuardedBy("mService")
+ private boolean mCached;
+
+ /**
+ * This is a system process, but not currently showing UI.
+ */
+ @GuardedBy("mService")
+ private boolean mSystemNoUi;
+
+ /**
+ * If the proc state is PROCESS_STATE_BOUND_FOREGROUND_SERVICE or above, it can start FGS.
+ * It must obtain the proc state from a persistent/top process or FGS, not transitive.
+ */
+ @GuardedBy("mService")
+ private int mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
+
+ @GuardedBy("mService")
+ private final ArraySet mBackgroundFgsStartTokens = new ArraySet<>();
+
+ /**
+ * Does the process has permission to start FGS from background.
+ */
+ @GuardedBy("mService")
+ private @ActiveServices.FgsFeatureRetCode int mAllowStartFgsByPermission;
+
+ /**
+ * Can this process start FGS from background?
+ * If this process has the ability to start FGS from background, this ability can be passed to
+ * another process through service binding.
+ */
+ @GuardedBy("mService")
+ private @ActiveServices.FgsFeatureRetCode int mAllowStartFgs;
+
+ /**
+ * Debugging: primary thing impacting oom_adj.
+ */
+ @GuardedBy("mService")
+ private String mAdjType;
+
+ /**
+ * Debugging: adj code to report to app.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mAdjTypeCode;
+
+ /**
+ * Debugging: option dependent object.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private Object mAdjSource;
+
+ /**
+ * Debugging: proc state of mAdjSource's process.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mAdjSourceProcState;
+
+ /**
+ * Debugging: target component impacting oom_adj.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private Object mAdjTarget;
+
+ /**
+ * Approximates the usage count of the app, used for cache re-ranking by CacheOomRanker.
+ *
+ * Counts the number of times the process is re-added to the cache (i.e. setCached(false);
+ * setCached(true)). This over counts, as setCached is sometimes reset while remaining in the
+ * cache. However, this happens uniformly across processes, so ranking is not affected.
+ */
+ @GuardedBy("mService")
+ private int mCacheOomRankerUseCount;
+
+ /**
+ * Whether or not this process is reachable from given process.
+ */
+ @GuardedBy("mService")
+ private boolean mReachable;
+
+ // Below are the cached task info for OomAdjuster only
+ private static final int VALUE_INVALID = -1;
+ private static final int VALUE_FALSE = 0;
+ private static final int VALUE_TRUE = 1;
+
+ @GuardedBy("mService")
+ private int mCachedHasActivities = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedIsHeavyWeight = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedHasVisibleActivities = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedIsHomeProcess = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedIsPreviousProcess = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedHasRecentTasks = VALUE_INVALID;
+ @GuardedBy("mService")
+ private int mCachedIsReceivingBroadcast = VALUE_INVALID;
+
+ @GuardedBy("mService")
+ private int mCachedAdj = ProcessList.INVALID_ADJ;
+ @GuardedBy("mService")
+ private boolean mCachedForegroundActivities = false;
+ @GuardedBy("mService")
+ private int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ @GuardedBy("mService")
+ private int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+
+ ProcessStateRecord(ProcessRecord app) {
+ mApp = app;
+ mService = app.mService;
+ mProcLock = mService.mProcLock;
+ setAllowStartFgsByPermission();
+ }
+
+ void init(long now) {
+ mLastStateTime = now;
+ }
+
+ @GuardedBy("mService")
+ void setMaxAdj(int maxAdj) {
+ mMaxAdj = maxAdj;
+ }
+
+ @GuardedBy("mService")
+ int getMaxAdj() {
+ return mMaxAdj;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurRawAdj(int curRawAdj) {
+ mCurRawAdj = curRawAdj;
+ mApp.getWindowProcessController().setPerceptible(
+ curRawAdj <= ProcessList.PERCEPTIBLE_APP_ADJ);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurRawAdj() {
+ return mCurRawAdj;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetRawAdj(int setRawAdj) {
+ mSetRawAdj = setRawAdj;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetRawAdj() {
+ return mSetRawAdj;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurAdj(int curAdj) {
+ mCurAdj = curAdj;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurAdj() {
+ return mCurAdj;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetAdj(int setAdj) {
+ mSetAdj = setAdj;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetAdj() {
+ return mSetAdj;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetAdjWithServices() {
+ if (mSetAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ if (mHasStartedServices) {
+ return ProcessList.SERVICE_B_ADJ;
+ }
+ }
+ return mSetAdj;
+ }
+
+ @GuardedBy("mService")
+ void setVerifiedAdj(int verifiedAdj) {
+ mVerifiedAdj = verifiedAdj;
+ }
+
+ @GuardedBy("mService")
+ int getVerifiedAdj() {
+ return mVerifiedAdj;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurCapability(int curCapability) {
+ mCurCapability = curCapability;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurCapability() {
+ return mCurCapability;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetCapability(int setCapability) {
+ mSetCapability = setCapability;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetCapability() {
+ return mSetCapability;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurrentSchedulingGroup(int curSchedGroup) {
+ mCurSchedGroup = curSchedGroup;
+ mApp.getWindowProcessController().setCurrentSchedulingGroup(curSchedGroup);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurrentSchedulingGroup() {
+ return mCurSchedGroup;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetSchedGroup(int setSchedGroup) {
+ mSetSchedGroup = setSchedGroup;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetSchedGroup() {
+ return mSetSchedGroup;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurProcState(int curProcState) {
+ mCurProcState = curProcState;
+ mApp.getWindowProcessController().setCurrentProcState(mCurProcState);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurProcState() {
+ return mCurProcState;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurRawProcState(int curRawProcState) {
+ mCurRawProcState = curRawProcState;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurRawProcState() {
+ return mCurRawProcState;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setReportedProcState(int repProcState) {
+ mRepProcState = repProcState;
+ mApp.getPkgList().forEachPackage((pkgName, holder) ->
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
+ mApp.uid, mApp.processName, pkgName,
+ ActivityManager.processStateAmToProto(mRepProcState),
+ holder.appVersion)
+ );
+ mApp.getWindowProcessController().setReportedProcState(repProcState);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getReportedProcState() {
+ return mRepProcState;
+ }
+
+ @GuardedBy("mService")
+ void forceProcessStateUpTo(int newState) {
+ if (mRepProcState > newState) {
+ synchronized (mProcLock) {
+ mRepProcState = newState;
+ setCurProcState(newState);
+ setCurRawProcState(newState);
+ mApp.getPkgList().forEachPackage((pkgName, holder) ->
+ FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
+ mApp.uid, mApp.processName, pkgName,
+ ActivityManager.processStateAmToProto(mRepProcState),
+ holder.appVersion)
+ );
+ }
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetProcState(int setProcState) {
+ mSetProcState = setProcState;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetProcState() {
+ return mSetProcState;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setLastStateTime(long lastStateTime) {
+ mLastStateTime = lastStateTime;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getLastStateTime() {
+ return mLastStateTime;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSavedPriority(int savedPriority) {
+ mSavedPriority = savedPriority;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSavedPriority() {
+ return mSavedPriority;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setServiceB(boolean serviceb) {
+ mServiceB = serviceb;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isServiceB() {
+ return mServiceB;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setServiceHighRam(boolean serviceHighRam) {
+ mServiceHighRam = serviceHighRam;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isServiceHighRam() {
+ return mServiceHighRam;
+ }
+
+ @GuardedBy("mProcLock")
+ void setNotCachedSinceIdle(boolean notCachedSinceIdle) {
+ mNotCachedSinceIdle = notCachedSinceIdle;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean isNotCachedSinceIdle() {
+ return mNotCachedSinceIdle;
+ }
+
+ @GuardedBy("mProcLock")
+ void setHasStartedServices(boolean hasStartedServices) {
+ mHasStartedServices = hasStartedServices;
+ }
+
+ @GuardedBy("mProcLock")
+ boolean hasStartedServices() {
+ return mHasStartedServices;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setHasForegroundActivities(boolean hasForegroundActivities) {
+ mHasForegroundActivities = hasForegroundActivities;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasForegroundActivities() {
+ return mHasForegroundActivities;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setRepForegroundActivities(boolean repForegroundActivities) {
+ mRepForegroundActivities = repForegroundActivities;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasRepForegroundActivities() {
+ return mRepForegroundActivities;
+ }
+
+ @GuardedBy("mService")
+ void setHasShownUi(boolean hasShownUi) {
+ mHasShownUi = hasShownUi;
+ }
+
+ @GuardedBy("mService")
+ boolean hasShownUi() {
+ return mHasShownUi;
+ }
+
+ @GuardedBy("mService")
+ void setHasTopUi(boolean hasTopUi) {
+ mHasTopUi = hasTopUi;
+ mApp.getWindowProcessController().setHasTopUi(hasTopUi);
+ }
+
+ @GuardedBy("mService")
+ boolean hasTopUi() {
+ return mHasTopUi;
+ }
+
+ @GuardedBy("mService")
+ void setHasOverlayUi(boolean hasOverlayUi) {
+ mHasOverlayUi = hasOverlayUi;
+ mApp.getWindowProcessController().setHasOverlayUi(hasOverlayUi);
+ }
+
+ @GuardedBy("mService")
+ boolean hasOverlayUi() {
+ return mHasOverlayUi;
+ }
+
+ @GuardedBy("mService")
+ boolean isRunningRemoteAnimation() {
+ return mRunningRemoteAnimation;
+ }
+
+ @GuardedBy("mService")
+ void setRunningRemoteAnimation(boolean runningRemoteAnimation) {
+ if (mRunningRemoteAnimation == runningRemoteAnimation) {
+ return;
+ }
+ mRunningRemoteAnimation = runningRemoteAnimation;
+ if (DEBUG_OOM_ADJ) {
+ Slog.i(TAG, "Setting runningRemoteAnimation=" + runningRemoteAnimation
+ + " for pid=" + mApp.getPid());
+ }
+ mService.updateOomAdjLocked(mApp, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setProcStateChanged(boolean procStateChanged) {
+ mProcStateChanged = procStateChanged;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasProcStateChanged() {
+ return mProcStateChanged;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setReportedInteraction(boolean reportedInteraction) {
+ mReportedInteraction = reportedInteraction;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasReportedInteraction() {
+ return mReportedInteraction;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setInteractionEventTime(long interactionEventTime) {
+ mInteractionEventTime = interactionEventTime;
+ mApp.getWindowProcessController().setInteractionEventTime(interactionEventTime);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getInteractionEventTime() {
+ return mInteractionEventTime;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setFgInteractionTime(long fgInteractionTime) {
+ mFgInteractionTime = fgInteractionTime;
+ mApp.getWindowProcessController().setFgInteractionTime(fgInteractionTime);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getFgInteractionTime() {
+ return mFgInteractionTime;
+ }
+
+ @GuardedBy("mService")
+ void setForcingToImportant(Object forcingToImportant) {
+ mForcingToImportant = forcingToImportant;
+ }
+
+ @GuardedBy("mService")
+ Object getForcingToImportant() {
+ return mForcingToImportant;
+ }
+
+ @GuardedBy("mService")
+ void setAdjSeq(int adjSeq) {
+ mAdjSeq = adjSeq;
+ }
+
+ @GuardedBy("mService")
+ void decAdjSeq() {
+ mAdjSeq--;
+ }
+
+ @GuardedBy("mService")
+ int getAdjSeq() {
+ return mAdjSeq;
+ }
+
+ @GuardedBy("mService")
+ void setCompletedAdjSeq(int completedAdjSeq) {
+ mCompletedAdjSeq = completedAdjSeq;
+ }
+
+ @GuardedBy("mService")
+ void decCompletedAdjSeq() {
+ mCompletedAdjSeq--;
+ }
+
+ @GuardedBy("mService")
+ int getCompletedAdjSeq() {
+ return mCompletedAdjSeq;
+ }
+
+ @GuardedBy("mService")
+ void setContainsCycle(boolean containsCycle) {
+ mContainsCycle = containsCycle;
+ }
+
+ @GuardedBy("mService")
+ boolean containsCycle() {
+ return mContainsCycle;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setWhenUnimportant(long whenUnimportant) {
+ mWhenUnimportant = whenUnimportant;
+ mApp.getWindowProcessController().setWhenUnimportant(whenUnimportant);
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getWhenUnimportant() {
+ return mWhenUnimportant;
+ }
+
+ @GuardedBy("mService")
+ void setLastTopTime(long lastTopTime) {
+ mLastTopTime = lastTopTime;
+ }
+
+ @GuardedBy("mService")
+ long getLastTopTime() {
+ return mLastTopTime;
+ }
+
+ @GuardedBy("mService")
+ void setEmpty(boolean empty) {
+ mEmpty = empty;
+ }
+
+ @GuardedBy("mService")
+ boolean isEmpty() {
+ return mEmpty;
+ }
+
+ @GuardedBy("mService")
+ void setCached(boolean cached) {
+ if (mCached != cached) {
+ mCached = cached;
+ if (cached) {
+ ++mCacheOomRankerUseCount;
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ boolean isCached() {
+ return mCached;
+ }
+
+ @GuardedBy("mService")
+ int getCacheOomRankerUseCount() {
+ return mCacheOomRankerUseCount;
+ }
+
+ @GuardedBy("mService")
+ void setSystemNoUi(boolean systemNoUi) {
+ mSystemNoUi = systemNoUi;
+ }
+
+ @GuardedBy("mService")
+ boolean isSystemNoUi() {
+ return mSystemNoUi;
+ }
+
+ @GuardedBy("mService")
+ void setAdjType(String adjType) {
+ mAdjType = adjType;
+ }
+
+ @GuardedBy("mService")
+ String getAdjType() {
+ return mAdjType;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setAdjTypeCode(int adjTypeCode) {
+ mAdjTypeCode = adjTypeCode;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getAdjTypeCode() {
+ return mAdjTypeCode;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setAdjSource(Object adjSource) {
+ mAdjSource = adjSource;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ Object getAdjSource() {
+ return mAdjSource;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setAdjSourceProcState(int adjSourceProcState) {
+ mAdjSourceProcState = adjSourceProcState;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getAdjSourceProcState() {
+ return mAdjSourceProcState;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setAdjTarget(Object adjTarget) {
+ mAdjTarget = adjTarget;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ Object getAdjTarget() {
+ return mAdjTarget;
+ }
+
+ @GuardedBy("mService")
+ boolean isReachable() {
+ return mReachable;
+ }
+
+ @GuardedBy("mService")
+ void setReachable(boolean reachable) {
+ mReachable = reachable;
+ }
+
+ @GuardedBy("mService")
+ void resetCachedInfo() {
+ mCachedHasActivities = VALUE_INVALID;
+ mCachedIsHeavyWeight = VALUE_INVALID;
+ mCachedHasVisibleActivities = VALUE_INVALID;
+ mCachedIsHomeProcess = VALUE_INVALID;
+ mCachedIsPreviousProcess = VALUE_INVALID;
+ mCachedHasRecentTasks = VALUE_INVALID;
+ mCachedIsReceivingBroadcast = VALUE_INVALID;
+ mCachedAdj = ProcessList.INVALID_ADJ;
+ mCachedForegroundActivities = false;
+ mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedHasActivities() {
+ if (mCachedHasActivities == VALUE_INVALID) {
+ mCachedHasActivities = mApp.getWindowProcessController().hasActivities() ? VALUE_TRUE
+ : VALUE_FALSE;
+ }
+ return mCachedHasActivities == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedIsHeavyWeight() {
+ if (mCachedIsHeavyWeight == VALUE_INVALID) {
+ mCachedIsHeavyWeight = mApp.getWindowProcessController().isHeavyWeightProcess()
+ ? VALUE_TRUE : VALUE_FALSE;
+ }
+ return mCachedIsHeavyWeight == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedHasVisibleActivities() {
+ if (mCachedHasVisibleActivities == VALUE_INVALID) {
+ mCachedHasVisibleActivities = mApp.getWindowProcessController().hasVisibleActivities()
+ ? VALUE_TRUE : VALUE_FALSE;
+ }
+ return mCachedHasVisibleActivities == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedIsHomeProcess() {
+ if (mCachedIsHomeProcess == VALUE_INVALID) {
+ if (mApp.getWindowProcessController().isHomeProcess()) {
+ mCachedIsHomeProcess = VALUE_TRUE;
+ mService.mAppProfiler.mHasHomeProcess = true;
+ } else {
+ mCachedIsHomeProcess = VALUE_FALSE;
+ }
+ }
+ return mCachedIsHomeProcess == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedIsPreviousProcess() {
+ if (mCachedIsPreviousProcess == VALUE_INVALID) {
+ if (mApp.getWindowProcessController().isPreviousProcess()) {
+ mCachedIsPreviousProcess = VALUE_TRUE;
+ mService.mAppProfiler.mHasPreviousProcess = true;
+ } else {
+ mCachedIsPreviousProcess = VALUE_FALSE;
+ }
+ }
+ return mCachedIsPreviousProcess == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedHasRecentTasks() {
+ if (mCachedHasRecentTasks == VALUE_INVALID) {
+ mCachedHasRecentTasks = mApp.getWindowProcessController().hasRecentTasks()
+ ? VALUE_TRUE : VALUE_FALSE;
+ }
+ return mCachedHasRecentTasks == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedIsReceivingBroadcast(ArraySet tmpQueue) {
+ if (mCachedIsReceivingBroadcast == VALUE_INVALID) {
+ tmpQueue.clear();
+ mCachedIsReceivingBroadcast = mService.isReceivingBroadcastLocked(mApp, tmpQueue)
+ ? VALUE_TRUE : VALUE_FALSE;
+ if (mCachedIsReceivingBroadcast == VALUE_TRUE) {
+ mCachedSchedGroup = tmpQueue.contains(mService.mFgBroadcastQueue)
+ ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
+ }
+ }
+ return mCachedIsReceivingBroadcast == VALUE_TRUE;
+ }
+
+ @GuardedBy("mService")
+ void computeOomAdjFromActivitiesIfNecessary(OomAdjuster.ComputeOomAdjWindowCallback callback,
+ int adj, boolean foregroundActivities, int procState, int schedGroup, int appUid,
+ int logUid, int processCurTop) {
+ if (mCachedAdj != ProcessList.INVALID_ADJ) {
+ return;
+ }
+ callback.initialize(mApp, adj, foregroundActivities, procState, schedGroup, appUid, logUid,
+ processCurTop);
+ final int minLayer = Math.min(ProcessList.VISIBLE_APP_LAYER_MAX,
+ mApp.getWindowProcessController().computeOomAdjFromActivities(callback));
+
+ mCachedAdj = callback.adj;
+ mCachedForegroundActivities = callback.foregroundActivities;
+ mCachedProcState = callback.procState;
+ mCachedSchedGroup = callback.schedGroup;
+
+ if (mCachedAdj == ProcessList.VISIBLE_APP_ADJ) {
+ mCachedAdj += minLayer;
+ }
+ }
+
+ @GuardedBy("mService")
+ int getCachedAdj() {
+ return mCachedAdj;
+ }
+
+ @GuardedBy("mService")
+ boolean getCachedForegroundActivities() {
+ return mCachedForegroundActivities;
+ }
+
+ @GuardedBy("mService")
+ int getCachedProcState() {
+ return mCachedProcState;
+ }
+
+ @GuardedBy("mService")
+ int getCachedSchedGroup() {
+ return mCachedSchedGroup;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ public String makeAdjReason() {
+ if (mAdjSource != null || mAdjTarget != null) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append(' ');
+ if (mAdjTarget instanceof ComponentName) {
+ sb.append(((ComponentName) mAdjTarget).flattenToShortString());
+ } else if (mAdjTarget != null) {
+ sb.append(mAdjTarget.toString());
+ } else {
+ sb.append("{null}");
+ }
+ sb.append("<=");
+ if (mAdjSource instanceof ProcessRecord) {
+ sb.append("Proc{");
+ sb.append(((ProcessRecord) mAdjSource).toShortString());
+ sb.append("}");
+ } else if (mAdjSource != null) {
+ sb.append(mAdjSource.toString());
+ } else {
+ sb.append("{null}");
+ }
+ return sb.toString();
+ }
+ return null;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void onCleanupApplicationRecordLSP() {
+ setHasForegroundActivities(false);
+ mHasShownUi = false;
+ mForcingToImportant = null;
+ mCurRawAdj = mSetRawAdj = mCurAdj = mSetAdj = mVerifiedAdj = ProcessList.INVALID_ADJ;
+ mCurCapability = mSetCapability = PROCESS_CAPABILITY_NONE;
+ mCurSchedGroup = mSetSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+ mCurProcState = mRepProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState =
+ PROCESS_STATE_NONEXISTENT;
+ }
+
+ @GuardedBy("mService")
+ void addAllowBackgroundFgsStartsToken(Binder entity) {
+ mBackgroundFgsStartTokens.add(entity);
+ }
+
+ @GuardedBy("mService")
+ void removeAllowBackgroundFgsStartsToken(Binder entity) {
+ mBackgroundFgsStartTokens.remove(entity);
+ }
+
+ @GuardedBy("mService")
+ boolean areBackgroundFgsStartsAllowedByToken() {
+ return !mBackgroundFgsStartTokens.isEmpty();
+ }
+
+ @GuardedBy("mService")
+ void resetAllowStartFgs() {
+ mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
+ mAllowStartFgs = mAllowStartFgsByPermission;
+ }
+
+ @GuardedBy("mService")
+ void bumpAllowStartFgsState(int newProcState) {
+ if (newProcState < mAllowStartFgsState) {
+ mAllowStartFgsState = newProcState;
+ }
+ }
+
+ @GuardedBy("mService")
+ void setAllowStartFgsState(int allowStartFgsState) {
+ mAllowStartFgsState = allowStartFgsState;
+ }
+
+ @GuardedBy("mService")
+ boolean isAllowedStartFgsState() {
+ return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ }
+
+ @GuardedBy("mService")
+ void setAllowStartFgsByPermission() {
+ int ret = FGS_FEATURE_DENIED;
+ if (ret == FGS_FEATURE_DENIED) {
+ boolean isSystem = false;
+ final int uid = UserHandle.getAppId(mApp.info.uid);
+ switch (uid) {
+ case ROOT_UID:
+ case SYSTEM_UID:
+ case NFC_UID:
+ case SHELL_UID:
+ isSystem = true;
+ break;
+ default:
+ isSystem = false;
+ break;
+ }
+
+ if (isSystem) {
+ ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID;
+ }
+ }
+
+ if (ret == FGS_FEATURE_DENIED) {
+ if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
+ mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
+ ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_ACTIVITY_PERMISSION;
+ } else if (ActivityManager.checkComponentPermission(
+ START_FOREGROUND_SERVICES_FROM_BACKGROUND,
+ mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
+ ret = FGS_FEATURE_ALLOWED_BY_BACKGROUND_FGS_PERMISSION;
+ } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW,
+ mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
+ ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION;
+ }
+ }
+ mAllowStartFgs = mAllowStartFgsByPermission = ret;
+ }
+
+ @GuardedBy("mService")
+ void setAllowStartFgs() {
+ if (mAllowStartFgs != FGS_FEATURE_DENIED) {
+ return;
+ }
+ if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+ if (isAllowedStartFgsState()) {
+ mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROC_STATE;
+ }
+ }
+
+ if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+ // Is the calling UID a device owner app?
+ if (mService.mInternal != null) {
+ if (mService.mInternal.isDeviceOwner(mApp.info.uid)) {
+ mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER;
+ }
+ }
+ }
+
+ if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+ if (mService.mInternal != null) {
+ final boolean isCompanionApp = mService.mInternal.isAssociatedCompanionApp(
+ UserHandle.getUserId(mApp.info.uid), mApp.info.uid);
+ if (isCompanionApp) {
+ mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_COMPANION_APP;
+ }
+ }
+ }
+
+ if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+ // Is the calling UID a profile owner app?
+ if (mService.mInternal != null) {
+ if (mService.mInternal.isProfileOwner(mApp.info.uid)) {
+ mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
+ }
+ }
+ }
+
+ if (mAllowStartFgs == FGS_FEATURE_DENIED) {
+ // uid is on DeviceIdleController's user/system allowlist
+ // or AMS's FgsStartTempAllowList.
+ if (mService.isAllowlistedForFgsStartLOSP(mApp.info.uid)) {
+ mAllowStartFgs = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST;
+ }
+ }
+ }
+
+ @GuardedBy("mService")
+ void setAllowStartFgs(@ActiveServices.FgsFeatureRetCode int allowStartFgs) {
+ mAllowStartFgs = allowStartFgs;
+ }
+
+ @GuardedBy("mService")
+ @ActiveServices.FgsFeatureRetCode int getAllowedStartFgs() {
+ return mAllowStartFgs;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void dump(PrintWriter pw, String prefix, long nowUptime) {
+ if (mReportedInteraction || mFgInteractionTime != 0) {
+ pw.print(prefix); pw.print("reportedInteraction=");
+ pw.print(mReportedInteraction);
+ if (mInteractionEventTime != 0) {
+ pw.print(" time=");
+ TimeUtils.formatDuration(mInteractionEventTime, SystemClock.elapsedRealtime(), pw);
+ }
+ if (mFgInteractionTime != 0) {
+ pw.print(" fgInteractionTime=");
+ TimeUtils.formatDuration(mFgInteractionTime, SystemClock.elapsedRealtime(), pw);
+ }
+ pw.println();
+ }
+ pw.print(prefix); pw.print("adjSeq="); pw.print(mAdjSeq);
+ pw.print(" lruSeq="); pw.println(mApp.getLruSeq());
+ pw.print(prefix); pw.print("oom adj: max="); pw.print(mMaxAdj);
+ pw.print(" curRaw="); pw.print(mCurRawAdj);
+ pw.print(" setRaw="); pw.print(mSetRawAdj);
+ pw.print(" cur="); pw.print(mCurAdj);
+ pw.print(" set="); pw.println(mSetAdj);
+ pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
+ pw.print(" setSchedGroup="); pw.print(mSetSchedGroup);
+ pw.print(" systemNoUi="); pw.print(mSystemNoUi);
+ pw.print(prefix); pw.print("curProcState="); pw.print(getCurProcState());
+ pw.print(" mRepProcState="); pw.print(mRepProcState);
+ pw.print(" setProcState="); pw.print(mSetProcState);
+ pw.print(" lastStateTime=");
+ TimeUtils.formatDuration(getLastStateTime(), nowUptime, pw);
+ pw.println();
+ pw.print(prefix); pw.print("curCapability=");
+ ActivityManager.printCapabilitiesFull(pw, mCurCapability);
+ pw.print(" setCapability=");
+ ActivityManager.printCapabilitiesFull(pw, mSetCapability);
+ pw.println();
+ pw.print(prefix); pw.print("allowStartFgsState=");
+ pw.println(mAllowStartFgsState);
+ if (mAllowStartFgs != FGS_FEATURE_DENIED) {
+ pw.print(prefix); pw.print("allowStartFgs=");
+ pw.println(fgsCodeToString(mAllowStartFgs));
+ }
+ if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) {
+ pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi);
+ pw.print(" pendingUiClean="); pw.print(mApp.mProfile.hasPendingUiClean());
+ }
+ pw.print(prefix); pw.print("cached="); pw.print(mCached);
+ pw.print(" empty="); pw.println(mEmpty);
+ if (mServiceB) {
+ pw.print(prefix); pw.print("serviceb="); pw.print(mServiceB);
+ pw.print(" serviceHighRam="); pw.println(mServiceHighRam);
+ }
+ if (mNotCachedSinceIdle) {
+ pw.print(prefix); pw.print("notCachedSinceIdle="); pw.print(mNotCachedSinceIdle);
+ pw.print(" initialIdlePss="); pw.println(mApp.mProfile.getInitialIdlePss());
+ }
+ if (hasTopUi() || hasOverlayUi() || mRunningRemoteAnimation) {
+ pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi());
+ pw.print(" hasOverlayUi="); pw.print(hasOverlayUi());
+ pw.print(" runningRemoteAnimation="); pw.println(mRunningRemoteAnimation);
+ }
+ if (mHasForegroundActivities || mRepForegroundActivities) {
+ pw.print(prefix);
+ pw.print(" foregroundActivities="); pw.print(mHasForegroundActivities);
+ pw.print(" (rep="); pw.print(mRepForegroundActivities); pw.println(")");
+ }
+ if (mSetProcState > ActivityManager.PROCESS_STATE_SERVICE) {
+ pw.print(prefix);
+ pw.print(" whenUnimportant=");
+ TimeUtils.formatDuration(mWhenUnimportant - nowUptime, pw);
+ pw.println();
+ }
+ if (mLastTopTime > 0) {
+ pw.print(prefix); pw.print("lastTopTime=");
+ TimeUtils.formatDuration(mLastTopTime, nowUptime, pw);
+ pw.println();
+ }
+ if (mHasStartedServices) {
+ pw.print(prefix); pw.print("hasStartedServices="); pw.println(mHasStartedServices);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index c10a07862123b..34a0c1beec09b 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -313,8 +313,8 @@ public final class ProcessStatsService extends IProcessStats.Stub {
private void scheduleRequestPssAllProcs(boolean always, boolean memLowered) {
mAm.mHandler.post(() -> {
- synchronized (mAm) {
- mAm.mAppProfiler.requestPssAllProcsLocked(
+ synchronized (mAm.mProcLock) {
+ mAm.mAppProfiler.requestPssAllProcsLPr(
SystemClock.uptimeMillis(), always, memLowered);
}
});
diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java
index 29c165733808a..072eba5d1205c 100644
--- a/services/core/java/com/android/server/am/ProviderMap.java
+++ b/services/core/java/com/android/server/am/ProviderMap.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.ComponentName.WithComponentName;
import android.os.Binder;
@@ -23,6 +24,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseArray;
+
import com.android.internal.os.TransferPipe;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
@@ -372,10 +374,11 @@ public final class ProviderMap {
*/
private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
final ContentProviderRecord r, String[] args, boolean dumpAll) {
+ final IApplicationThread thread = r.proc != null ? r.proc.getThread() : null;
for (String s: args) {
if (!dumpAll && s.contains("--proto")) {
- if (r.proc != null && r.proc.thread != null) {
- dumpToTransferPipe(null , fd, pw, r, args);
+ if (thread != null) {
+ dumpToTransferPipe(null , fd, pw, r, thread, args);
}
return;
}
@@ -386,7 +389,7 @@ public final class ProviderMap {
pw.print(r);
pw.print(" pid=");
if (r.proc != null) {
- pw.println(r.proc.pid);
+ pw.println(r.proc.getPid());
} else {
pw.println("(not running)");
}
@@ -394,10 +397,10 @@ public final class ProviderMap {
r.dump(pw, innerPrefix, true);
}
}
- if (r.proc != null && r.proc.thread != null) {
+ if (thread != null) {
pw.println(" Client:");
pw.flush();
- dumpToTransferPipe(" ", fd, pw, r, args);
+ dumpToTransferPipe(" ", fd, pw, r, thread, args);
}
}
@@ -420,8 +423,9 @@ public final class ProviderMap {
// Only dump the first provider, since we are dumping in proto format
for (int i = 0; i < providers.size(); i++) {
final ContentProviderRecord r = providers.get(i);
- if (r.proc != null && r.proc.thread != null) {
- dumpToTransferPipe(null, fd, pw, r, newArgs);
+ IApplicationThread thread;
+ if (r.proc != null && (thread = r.proc.getThread()) != null) {
+ dumpToTransferPipe(null, fd, pw, r, thread, newArgs);
return true;
}
}
@@ -433,11 +437,11 @@ public final class ProviderMap {
* any meta string (e.g., provider info, indentation) written to the file descriptor.
*/
private void dumpToTransferPipe(String prefix, FileDescriptor fd, PrintWriter pw,
- final ContentProviderRecord r, String[] args) {
+ final ContentProviderRecord r, final IApplicationThread thread, String[] args) {
try {
TransferPipe tp = new TransferPipe();
try {
- r.proc.thread.dumpProvider(
+ thread.dumpProvider(
tp.getWriteFd(), r.provider.asBinder(), args);
tp.setBufferPrefix(prefix);
// Short timeout, since blocking here can
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 8a1b4e3e832ed..485087d294223 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import android.annotation.Nullable;
+import android.app.IApplicationThread;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -281,7 +282,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
proto.write(ServiceRecordProto.SHORT_NAME, this.shortInstanceName);
proto.write(ServiceRecordProto.IS_RUNNING, app != null);
if (app != null) {
- proto.write(ServiceRecordProto.PID, app.pid);
+ proto.write(ServiceRecordProto.PID, app.getPid());
}
if (intent != null) {
intent.getIntent().dumpDebug(proto, ServiceRecordProto.INTENT, false, true, false,
@@ -582,13 +583,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
restartTracker.setRestarting(true, memFactor, now);
}
- public void setProcess(ProcessRecord _proc) {
- if (_proc != null) {
+ public void setProcess(ProcessRecord proc, IApplicationThread thread, int pid,
+ UidRecord uidRecord) {
+ if (proc != null) {
// We're starting a new process for this service, but a previous one is allowed to start
// background activities. Remove that ability now (unless the new process is the same as
// the previous one, which is a common case).
if (mAppForAllowingBgActivityStartsByStart != null) {
- if (mAppForAllowingBgActivityStartsByStart != _proc) {
+ if (mAppForAllowingBgActivityStartsByStart != proc) {
mAppForAllowingBgActivityStartsByStart
.removeAllowBackgroundActivityStartsToken(this);
ams.mHandler.removeCallbacks(mCleanUpAllowBgActivityStartsByStartCallback);
@@ -596,34 +598,35 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
// Make sure the cleanup callback knows about the new process.
mAppForAllowingBgActivityStartsByStart = mIsAllowedBgActivityStartsByStart
- ? _proc : null;
+ ? proc : null;
if (mIsAllowedBgActivityStartsByStart
|| mIsAllowedBgActivityStartsByBinding) {
- _proc.addOrUpdateAllowBackgroundActivityStartsToken(this,
+ proc.addOrUpdateAllowBackgroundActivityStartsToken(this,
getExclusiveOriginatingToken());
} else {
- _proc.removeAllowBackgroundActivityStartsToken(this);
+ proc.removeAllowBackgroundActivityStartsToken(this);
}
if (mIsAllowedBgFgsStartsByBinding) {
- _proc.addAllowBackgroundFgsStartsToken(this);
+ proc.mState.addAllowBackgroundFgsStartsToken(this);
} else {
- _proc.removeAllowBackgroundFgsStartsToken(this);
+ proc.mState.removeAllowBackgroundFgsStartsToken(this);
}
}
- if (app != null && app != _proc) {
+ if (app != null && app != proc) {
// If the old app is allowed to start bg activities because of a service start, leave it
// that way until the cleanup callback runs. Otherwise we can remove its bg activity
// start ability immediately (it can't be bound now).
if (!mIsAllowedBgActivityStartsByStart) {
app.removeAllowBackgroundActivityStartsToken(this);
}
- app.updateBoundClientUids();
+ app.mServices.updateBoundClientUids();
}
- app = _proc;
- if (pendingConnectionGroup > 0 && _proc != null) {
- _proc.connectionService = this;
- _proc.connectionGroup = pendingConnectionGroup;
- _proc.connectionImportance = pendingConnectionImportance;
+ app = proc;
+ if (pendingConnectionGroup > 0 && proc != null) {
+ final ProcessServiceRecord psr = proc.mServices;
+ psr.setConnectionService(this);
+ psr.setConnectionGroup(pendingConnectionGroup);
+ psr.setConnectionImportance(pendingConnectionImportance);
pendingConnectionGroup = pendingConnectionImportance = 0;
}
if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS) {
@@ -631,7 +634,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
ArrayList cr = connections.valueAt(conni);
for (int i = 0; i < cr.size(); i++) {
final ConnectionRecord conn = cr.get(i);
- if (_proc != null) {
+ if (proc != null) {
conn.startAssociationIfNeeded();
} else {
conn.stopAssociation();
@@ -639,8 +642,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
}
}
- if (_proc != null) {
- _proc.updateBoundClientUids();
+ if (proc != null) {
+ proc.mServices.updateBoundClientUids();
}
}
@@ -658,7 +661,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// if we have a process attached, add bound client uid of this connection to it
if (app != null) {
- app.addBoundClientUid(c.clientUid);
+ app.mServices.addBoundClientUid(c.clientUid);
}
}
@@ -666,7 +669,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
connections.remove(binder);
// if we have a process attached, tell it to update the state of bound clients
if (app != null) {
- app.updateBoundClientUids();
+ app.mServices.updateBoundClientUids();
}
}
@@ -820,9 +823,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
return;
}
if (mIsAllowedBgFgsStartsByBinding) {
- app.addAllowBackgroundFgsStartsToken(this);
+ app.mState.addAllowBackgroundFgsStartsToken(this);
} else {
- app.removeAllowBackgroundFgsStartsToken(this);
+ app.mState.removeAllowBackgroundFgsStartsToken(this);
}
}
@@ -937,7 +940,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
public void postNotification() {
final int appUid = appInfo.uid;
- final int appPid = app.pid;
+ final int appPid = app.getPid();
if (foregroundId != 0 && foregroundNoti != null) {
// Do asynchronous communication with notification manager to
// avoid deadlocks.
@@ -1057,7 +1060,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
final String localPackageName = packageName;
final int localForegroundId = foregroundId;
final int appUid = appInfo.uid;
- final int appPid = app != null ? app.pid : 0;
+ final int appPid = app != null ? app.getPid() : 0;
ams.mHandler.post(new Runnable() {
public void run() {
NotificationManagerInternal nm = LocalServices.getService(
diff --git a/services/core/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
index 22e7faa4bad90..4cc1fc1b7d093 100644
--- a/services/core/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
@@ -49,7 +49,7 @@ final class StrictModeViolationDialog extends BaseErrorDialog {
mProc = app;
mResult = result;
CharSequence name;
- if ((app.getPkgList().size() == 1)
+ if (app.getPkgList().size() == 1
&& (name = context.getPackageManager().getApplicationLabel(app.info)) != null) {
setMessage(res.getString(
com.android.internal.R.string.smv_application,
@@ -67,7 +67,7 @@ final class StrictModeViolationDialog extends BaseErrorDialog {
res.getText(com.android.internal.R.string.dlg_ok),
mHandler.obtainMessage(ACTION_OK));
- if (app.errorReportReceiver != null) {
+ if (app.mErrorState.getErrorReportReceiver() != null) {
setButton(DialogInterface.BUTTON_NEGATIVE,
res.getText(com.android.internal.R.string.report),
mHandler.obtainMessage(ACTION_OK_AND_REPORT));
@@ -84,9 +84,9 @@ final class StrictModeViolationDialog extends BaseErrorDialog {
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
- synchronized (mService) {
+ synchronized (mService.mProcLock) {
if (mProc != null) {
- mProc.getDialogController().clearViolationDialogs();
+ mProc.mErrorState.getDialogController().clearViolationDialogs();
}
}
mResult.set(msg.what);
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index b3150d1489bb7..df65ee6e3a280 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -204,16 +204,18 @@ public class UidObserverController {
} else {
UidRecord validateUid = mValidateUids.get(item.uid);
if (validateUid == null) {
- validateUid = new UidRecord(item.uid);
+ validateUid = new UidRecord(item.uid, null);
mValidateUids.put(item.uid, validateUid);
}
if ((item.change & UidRecord.CHANGE_IDLE) != 0) {
- validateUid.idle = true;
+ validateUid.setIdle(true);
} else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) {
- validateUid.idle = false;
+ validateUid.setIdle(false);
}
- validateUid.setCurProcState(validateUid.setProcState = item.procState);
- validateUid.curCapability = validateUid.setCapability = item.capability;
+ validateUid.setSetProcState(item.procState);
+ validateUid.setCurProcState(item.procState);
+ validateUid.setSetCapability(item.capability);
+ validateUid.setCurCapability(item.capability);
validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 36d22bf0f5da7..2fb662f5ee69b 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -26,27 +26,58 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
+import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.server.am.UidObserverController.ChangeRecord;
+import java.util.function.Consumer;
+
/**
* Overall information about a uid that has actively running processes.
*/
public final class UidRecord {
- final int uid;
- int mCurProcState;
- int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
- int curCapability;
- int setCapability;
- long lastBackgroundTime;
- boolean ephemeral;
- boolean foregroundServices;
- boolean mCurAllowlist;
- boolean mSetAllowlist;
- boolean idle;
- boolean setIdle;
- int numProcs;
- ArraySet procRecords = new ArraySet<>();
+ private final ActivityManagerService mService;
+ private final ActivityManagerGlobalLock mProcLock;
+ private final int mUid;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurProcState;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mCurCapability;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetCapability;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private long mLastBackgroundTime;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mEphemeral;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mForegroundServices;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mCurAllowList;;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mSetAllowList;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mIdle;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private boolean mSetIdle;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mNumProcs;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private ArraySet mProcRecords = new ArraySet<>();
/**
* Sequence number associated with the {@link #mCurProcState}. This is incremented using
@@ -111,32 +142,168 @@ public final class UidRecord {
// UidObserverController is the only thing that should modify this.
final ChangeRecord pendingChange = new ChangeRecord();
- int lastReportedChange;
+ @GuardedBy("mService")
+ private int mLastReportedChange;
- public UidRecord(int _uid) {
- uid = _uid;
- idle = true;
+ public UidRecord(int uid, ActivityManagerService service) {
+ mUid = uid;
+ mService = service;
+ mProcLock = service != null ? service.mProcLock : null;
+ mIdle = true;
reset();
}
- public int getCurProcState() {
+ int getUid() {
+ return mUid;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurProcState() {
return mCurProcState;
}
- public void setCurProcState(int curProcState) {
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurProcState(int curProcState) {
mCurProcState = curProcState;
}
- public void reset() {
- setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- foregroundServices = false;
- curCapability = 0;
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetProcState() {
+ return mSetProcState;
+ }
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetProcState(int setProcState) {
+ mSetProcState = setProcState;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getCurCapability() {
+ return mCurCapability;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurCapability(int curCapability) {
+ mCurCapability = curCapability;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getSetCapability() {
+ return mSetCapability;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetCapability(int setCapability) {
+ mSetCapability = setCapability;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ long getLastBackgroundTime() {
+ return mLastBackgroundTime;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setLastBackgroundTime(long lastBackgroundTime) {
+ mLastBackgroundTime = lastBackgroundTime;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isEphemeral() {
+ return mEphemeral;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setEphemeral(boolean ephemeral) {
+ mEphemeral = ephemeral;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasForegroundServices() {
+ return mForegroundServices;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setForegroundServices(boolean foregroundServices) {
+ mForegroundServices = foregroundServices;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isCurAllowListed() {
+ return mCurAllowList;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setCurAllowListed(boolean curAllowList) {
+ mCurAllowList = curAllowList;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isSetAllowListed() {
+ return mSetAllowList;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetAllowListed(boolean setAllowlist) {
+ mSetAllowList = setAllowlist;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isIdle() {
+ return mIdle;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setIdle(boolean idle) {
+ mIdle = idle;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean isSetIdle() {
+ return mSetIdle;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void setSetIdle(boolean setIdle) {
+ mSetIdle = setIdle;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getNumOfProcs() {
+ return mProcRecords.size();
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ void forEachProcess(Consumer callback) {
+ for (int i = mProcRecords.size() - 1; i >= 0; i--) {
+ callback.accept(mProcRecords.valueAt(i));
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void addProcess(ProcessRecord app) {
+ mProcRecords.add(app);
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void removeProcess(ProcessRecord app) {
+ mProcRecords.remove(app);
+ }
+
+ @GuardedBy("mService")
+ void setLastReportedChange(int lastReportedChange) {
+ mLastReportedChange = lastReportedChange;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void reset() {
+ setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mForegroundServices = false;
+ mCurCapability = 0;
}
public void updateHasInternetPermission() {
hasInternetPermission = ActivityManager.checkUidPermission(Manifest.permission.INTERNET,
- uid) == PackageManager.PERMISSION_GRANTED;
+ mUid) == PackageManager.PERMISSION_GRANTED;
}
/**
@@ -153,19 +320,19 @@ public final class UidRecord {
void dumpDebug(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
- proto.write(UidRecordProto.UID, uid);
+ proto.write(UidRecordProto.UID, mUid);
proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(mCurProcState));
- proto.write(UidRecordProto.EPHEMERAL, ephemeral);
- proto.write(UidRecordProto.FG_SERVICES, foregroundServices);
- proto.write(UidRecordProto.WHILELIST, mCurAllowlist);
+ proto.write(UidRecordProto.EPHEMERAL, mEphemeral);
+ proto.write(UidRecordProto.FG_SERVICES, mForegroundServices);
+ proto.write(UidRecordProto.WHILELIST, mCurAllowList);
ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
- lastBackgroundTime, SystemClock.elapsedRealtime());
- proto.write(UidRecordProto.IDLE, idle);
- if (lastReportedChange != 0) {
+ mLastBackgroundTime, SystemClock.elapsedRealtime());
+ proto.write(UidRecordProto.IDLE, mIdle);
+ if (mLastReportedChange != 0) {
ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidRecordProto.LAST_REPORTED_CHANGES,
- lastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
+ mLastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
}
- proto.write(UidRecordProto.NUM_PROCS, numProcs);
+ proto.write(UidRecordProto.NUM_PROCS, mNumProcs);
long seqToken = proto.start(UidRecordProto.NETWORK_STATE_UPDATE);
proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
@@ -182,54 +349,54 @@ public final class UidRecord {
sb.append("UidRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
- UserHandle.formatUid(sb, uid);
+ UserHandle.formatUid(sb, mUid);
sb.append(' ');
sb.append(ProcessList.makeProcStateString(mCurProcState));
- if (ephemeral) {
+ if (mEphemeral) {
sb.append(" ephemeral");
}
- if (foregroundServices) {
+ if (mForegroundServices) {
sb.append(" fgServices");
}
- if (mCurAllowlist) {
+ if (mCurAllowList) {
sb.append(" allowlist");
}
- if (lastBackgroundTime > 0) {
+ if (mLastBackgroundTime > 0) {
sb.append(" bg:");
- TimeUtils.formatDuration(SystemClock.elapsedRealtime()-lastBackgroundTime, sb);
+ TimeUtils.formatDuration(SystemClock.elapsedRealtime() - mLastBackgroundTime, sb);
}
- if (idle) {
+ if (mIdle) {
sb.append(" idle");
}
- if (lastReportedChange != 0) {
+ if (mLastReportedChange != 0) {
sb.append(" change:");
boolean printed = false;
- if ((lastReportedChange & CHANGE_GONE) != 0) {
+ if ((mLastReportedChange & CHANGE_GONE) != 0) {
printed = true;
sb.append("gone");
}
- if ((lastReportedChange & CHANGE_IDLE) != 0) {
+ if ((mLastReportedChange & CHANGE_IDLE) != 0) {
if (printed) {
sb.append("|");
}
printed = true;
sb.append("idle");
}
- if ((lastReportedChange & CHANGE_ACTIVE) != 0) {
+ if ((mLastReportedChange & CHANGE_ACTIVE) != 0) {
if (printed) {
sb.append("|");
}
printed = true;
sb.append("active");
}
- if ((lastReportedChange & CHANGE_CACHED) != 0) {
+ if ((mLastReportedChange & CHANGE_CACHED) != 0) {
if (printed) {
sb.append("|");
}
printed = true;
sb.append("cached");
}
- if ((lastReportedChange & CHANGE_UNCACHED) != 0) {
+ if ((mLastReportedChange & CHANGE_UNCACHED) != 0) {
if (printed) {
sb.append("|");
}
@@ -237,7 +404,7 @@ public final class UidRecord {
}
}
sb.append(" procs:");
- sb.append(numProcs);
+ sb.append(mNumProcs);
sb.append(" seq(");
sb.append(curProcStateSeq);
sb.append(",");
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
index a18632b8d1b2d..961fc1884cfd9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
@@ -232,8 +232,8 @@ public class AppChildProcessTest {
ai.packageName = packageName;
ai.uid = uid;
ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
- app.pid = pid;
- mAms.mPidsSelfLocked.doAddInternal(app);
+ app.setPid(pid);
+ mAms.mPidsSelfLocked.doAddInternal(app.getPid(), app);
mPhantomInjector.addToProcess(uid, pid, pid);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 9441ecf74e830..22b2f7e04069c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -798,7 +798,7 @@ public class ApplicationExitInfoTest {
final int traceEnd = 8192;
createRandomFile(traceFile, traceSize);
assertEquals(traceSize, traceFile.length());
- mAppExitInfoTracker.handleLogAnrTrace(app.pid, app.uid, app.getPackageList(),
+ mAppExitInfoTracker.handleLogAnrTrace(app.getPid(), app.uid, app.getPackageList(),
traceFile, traceStart, traceEnd);
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
@@ -991,16 +991,16 @@ public class ApplicationExitInfoTest {
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName;
ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
- app.pid = pid;
+ app.setPid(pid);
app.info.uid = packageUid;
if (definingUid != null) {
final String dummyPackageName = "com.android.test";
final String dummyClassName = ".Foo";
- app.hostingRecord = HostingRecord.byAppZygote(new ComponentName(
- dummyPackageName, dummyClassName), "", definingUid);
+ app.setHostingRecord(HostingRecord.byAppZygote(new ComponentName(
+ dummyPackageName, dummyClassName), "", definingUid));
}
- app.connectionGroup = connectionGroup;
- app.setProcState = procState;
+ app.mServices.setConnectionGroup(connectionGroup);
+ app.mState.setSetProcState(procState);
app.mProfile.setLastMemInfo(spy(new Debug.MemoryInfo()));
app.mProfile.setLastPss(pss);
app.mProfile.setLastRss(rss);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
index c82db7305bd8d..022fadcc6dd0f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
@@ -170,7 +170,7 @@ public class CacheOomRankerTest {
/* lruWeight= */1.0f);
ProcessList list = new ProcessList();
- ArrayList processList = list.mLruProcesses;
+ ArrayList processList = list.getLruProcessesLSP();
ProcessRecord lastUsed40MinutesAgo = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000);
processList.add(lastUsed40MinutesAgo);
@@ -191,7 +191,7 @@ public class CacheOomRankerTest {
Duration.ofMinutes(30).toMillis(), 1024L, 20);
processList.add(lastUsed30MinutesAgo);
- mCacheOomRanker.reRankLruCachedApps(list);
+ mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
// First 5 ordered by least recently used first, then last processes position unchanged.
assertThat(processList).containsExactly(lastUsed60MinutesAgo, lastUsed42MinutesAgo,
@@ -207,7 +207,7 @@ public class CacheOomRankerTest {
/* lruWeight= */ 0.0f);
ProcessList list = new ProcessList();
- ArrayList processList = list.mLruProcesses;
+ ArrayList processList = list.getLruProcessesLSP();
ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000);
processList.add(rss10k);
@@ -231,7 +231,7 @@ public class CacheOomRankerTest {
Duration.ofMinutes(30).toMillis(), 16 * 1024L, 20);
processList.add(rss16k);
- mCacheOomRanker.reRankLruCachedApps(list);
+ mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
// First 6 ordered by largest pss, then last processes position unchanged.
assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
@@ -246,8 +246,8 @@ public class CacheOomRankerTest {
/* lruWeight= */ 0.0f);
ProcessList list = new ProcessList();
- list.mLruProcessServiceStart = 1;
- ArrayList processList = list.mLruProcesses;
+ list.setLruProcessServiceStartLSP(1);
+ ArrayList processList = list.getLruProcessesLSP();
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000);
processList.add(used1000);
@@ -268,7 +268,7 @@ public class CacheOomRankerTest {
Duration.ofMinutes(30).toMillis(), 16 * 1024L, 200);
processList.add(used200);
- mCacheOomRanker.reRankLruCachedApps(list);
+ mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
// First 4 ordered by uses, then last processes position unchanged.
assertThat(processList).containsExactly(used10, used20, used1000, used2000, used500,
@@ -283,7 +283,7 @@ public class CacheOomRankerTest {
/* lruWeight= */ 0.3f);
ProcessList list = new ProcessList();
- ArrayList processList = list.mLruProcesses;
+ ArrayList processList = list.getLruProcessesLSP();
ProcessRecord unknownAdj1 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000);
processList.add(unknownAdj1);
@@ -304,7 +304,7 @@ public class CacheOomRankerTest {
processList.add(systemAdj);
// 6 Processes but only 3 in eligible for cache so no re-ranking.
- mCacheOomRanker.reRankLruCachedApps(list);
+ mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
// All positions unchanged.
assertThat(processList).containsExactly(unknownAdj1, unknownAdj2, unknownAdj3,
@@ -319,8 +319,8 @@ public class CacheOomRankerTest {
/* lruWeight= */ 0.0f);
ProcessList list = new ProcessList();
- list.mLruProcessServiceStart = 4;
- ArrayList processList = list.mLruProcesses;
+ list.setLruProcessServiceStartLSP(4);
+ ArrayList processList = list.getLruProcessesLSP();
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
Duration.ofMinutes(40).toMillis(), 10 * 1024L, 1000);
processList.add(used1000);
@@ -340,7 +340,7 @@ public class CacheOomRankerTest {
Duration.ofMinutes(30).toMillis(), 16 * 1024L, 200);
processList.add(used200);
- mCacheOomRanker.reRankLruCachedApps(list);
+ mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
// All positions unchanged.
assertThat(processList).containsExactly(used1000, used2000, used10, used20, used500,
@@ -378,17 +378,17 @@ public class CacheOomRankerTest {
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = "a.package.name" + mNextPackageName++;
ProcessRecord app = new ProcessRecord(mAms, ai, ai.packageName + ":process", mNextUid++);
- app.pid = mNextPid++;
+ app.setPid(mNextPid++);
app.info.uid = mNextPackageUid++;
// Exact value does not mater, it can be any state for which compaction is allowed.
- app.setProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- app.setAdj = setAdj;
- app.lastActivityTime = lastActivityTime;
+ app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ app.mState.setSetAdj(setAdj);
+ app.setLastActivityTime(lastActivityTime);
app.mProfile.setLastRss(lastRss);
- app.setCached(false);
+ app.mState.setCached(false);
for (int i = 0; i < returnedToCacheCount; ++i) {
- app.setCached(false);
- app.setCached(true);
+ app.mState.setCached(false);
+ app.mState.setCached(true);
}
return app;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 96a44a46bbafb..d86032622e43d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -134,11 +134,11 @@ public final class CachedAppOptimizerTest {
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName;
ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
- app.pid = pid;
+ app.setPid(pid);
app.info.uid = packageUid;
// Exact value does not mater, it can be any state for which compaction is allowed.
- app.setProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- app.setAdj = 905;
+ app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ app.mState.setSetAdj(905);
return app;
}
@@ -875,7 +875,8 @@ public final class CachedAppOptimizerTest {
mProcessDependencies.setRss(rssBefore2);
mProcessDependencies.setRssAfterCompaction(rssAfter2);
// This is to avoid throttle of compacting too soon.
- processRecord.lastCompactTime = processRecord.lastCompactTime - 10_000;
+ processRecord.mOptRecord.setLastCompactTime(
+ processRecord.mOptRecord.getLastCompactTime() - 10_000);
// WHEN we try to run compaction.
mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
waitForHandler();
@@ -890,7 +891,8 @@ public final class CachedAppOptimizerTest {
mProcessDependencies.setRss(rssBefore3);
mProcessDependencies.setRssAfterCompaction(rssAfter3);
// This is to avoid throttle of compacting too soon.
- processRecord.lastCompactTime = processRecord.lastCompactTime - 10_000;
+ processRecord.mOptRecord.setLastCompactTime(
+ processRecord.mOptRecord.getLastCompactTime() - 10_000);
// WHEN we try to run compaction
mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
waitForHandler();
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 7daf357705bc2..27825a461b40b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -176,6 +176,8 @@ public class MockingOomAdjusterTests {
setFieldValue(ActivityManagerService.class, sService, "mUserController",
mock(UserController.class));
setFieldValue(ActivityManagerService.class, sService, "mAppProfiler", profiler);
+ setFieldValue(ActivityManagerService.class, sService, "mProcLock",
+ new ActivityManagerProcLock());
setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
@@ -207,8 +209,8 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Persistent_TopUi_Sleeping() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.maxAdj = PERSISTENT_PROC_ADJ;
- app.setHasTopUi(true);
+ app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ app.mState.setHasTopUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_ASLEEP);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -222,8 +224,8 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Persistent_TopUi_Awake() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.maxAdj = PERSISTENT_PROC_ADJ;
- app.setHasTopUi(true);
+ app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ app.mState.setHasTopUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -236,7 +238,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Persistent_TopApp() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.maxAdj = PERSISTENT_PROC_ADJ;
+ app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
doReturn(app).when(sService).getTopApp();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -266,7 +268,7 @@ public class MockingOomAdjusterTests {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
doReturn(PROCESS_STATE_TOP_SLEEPING).when(sService.mAtmInternal).getTopProcessState();
- app.runningRemoteAnimation = true;
+ app.mState.setRunningRemoteAnimation(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
@@ -308,7 +310,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_ExecutingService() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.executingServices.add(mock(ServiceRecord.class));
+ app.mServices.startExecutingService(mock(ServiceRecord.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -337,7 +339,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_CachedEmpty() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.setCurRawAdj(CACHED_APP_MIN_ADJ);
+ app.mState.setCurRawAdj(CACHED_APP_MIN_ADJ);
doReturn(null).when(sService).getTopApp();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -351,7 +353,6 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_VisibleActivities() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(true).when(wpc).hasActivities();
doAnswer(answer(callback -> {
@@ -368,7 +369,6 @@ public class MockingOomAdjusterTests {
any(WindowProcessController.ComputeOomAdjCallback.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- doCallRealMethod().when(app).getWindowProcessController();
assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP);
}
@@ -378,15 +378,14 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_RecentTasks() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(true).when(wpc).hasRecentTasks();
- app.lastTopTime = SystemClock.uptimeMillis();
+ app.mState.setLastTopTime(SystemClock.uptimeMillis());
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
doCallRealMethod().when(wpc).hasRecentTasks();
- assertEquals(PROCESS_STATE_CACHED_RECENT, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_RECENT, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -394,7 +393,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_FgServiceLocation() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.setHasForegroundServices(true, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
+ app.mServices.setHasForegroundServices(true, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -407,7 +406,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_FgService() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.setHasForegroundServices(true, 0);
+ app.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -420,7 +419,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_OverlayUi() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.setHasOverlayUi(true);
+ app.mState.setHasOverlayUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -433,8 +432,8 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_PerceptibleRecent() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.setHasForegroundServices(true, 0);
- app.lastTopTime = SystemClock.uptimeMillis();
+ app.mServices.setHasForegroundServices(true, 0);
+ app.mState.setLastTopTime(SystemClock.uptimeMillis());
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -447,7 +446,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Toast() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.forcingToImportant = new Object();
+ app.mState.setForcingToImportant(new Object());
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -460,7 +459,6 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_HeavyWeight() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(true).when(wpc).isHeavyWeightProcess();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -476,7 +474,6 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_HomeApp() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -490,7 +487,6 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_PreviousApp() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(true).when(wpc).isPreviousProcess();
doReturn(true).when(wpc).hasActivities();
@@ -522,11 +518,11 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_ClientActivities() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(true).when(app).hasClientActivities();
+ app.mServices.setHasClientActivities(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_CACHED_ACTIVITY_CLIENT, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY_CLIENT, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -534,11 +530,11 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_TreatLikeActivity() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- app.treatLikeActivity = true;
+ app.mServices.setTreatLikeActivity(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -546,12 +542,12 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_ServiceB() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.serviceb = true;
+ app.mState.setServiceB(true);
ServiceRecord s = mock(ServiceRecord.class);
doReturn(new ArrayMap>()).when(s).getConnections();
s.startRequested = true;
s.lastActivity = SystemClock.uptimeMillis();
- app.startService(s);
+ app.mServices.startService(s);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -563,7 +559,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_MaxAdj() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.maxAdj = PERCEPTIBLE_LOW_APP_ADJ;
+ app.mState.setMaxAdj(PERCEPTIBLE_LOW_APP_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -576,14 +572,14 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_NonCachedToCached() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.setCached(false);
- app.setCurRawAdj(SERVICE_ADJ);
+ app.mState.setCached(false);
+ app.mState.setCurRawAdj(SERVICE_ADJ);
doReturn(null).when(sService).getTopApp();
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertTrue(ProcessList.CACHED_APP_MIN_ADJ <= app.setAdj);
- assertTrue(ProcessList.CACHED_APP_MAX_ADJ >= app.setAdj);
+ assertTrue(ProcessList.CACHED_APP_MIN_ADJ <= app.mState.getSetAdj());
+ assertTrue(ProcessList.CACHED_APP_MAX_ADJ >= app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -595,7 +591,7 @@ public class MockingOomAdjusterTests {
doReturn(new ArrayMap>()).when(s).getConnections();
s.startRequested = true;
s.lastActivity = SystemClock.uptimeMillis();
- app.startService(s);
+ app.mServices.startService(s);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -633,7 +629,7 @@ public class MockingOomAdjusterTests {
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -653,8 +649,8 @@ public class MockingOomAdjusterTests {
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(FOREGROUND_APP_ADJ, app.setAdj);
- assertEquals(SCHED_GROUP_TOP_APP_BOUND, app.setSchedGroup);
+ assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+ assertEquals(SCHED_GROUP_TOP_APP_BOUND, app.mState.getSetSchedGroup());
}
@SuppressWarnings("GuardedBy")
@@ -676,12 +672,12 @@ public class MockingOomAdjusterTests {
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- client.treatLikeActivity = true;
+ client.mServices.setTreatLikeActivity(true);
bindService(app, client, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -689,7 +685,6 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Service_AllowOomManagement() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
WindowProcessController wpc = app.getWindowProcessController();
doReturn(false).when(wpc).isHomeProcess();
doReturn(true).when(wpc).isPreviousProcess();
@@ -703,7 +698,7 @@ public class MockingOomAdjusterTests {
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
doReturn(null).when(sService).getTopApp();
- assertEquals(PREVIOUS_APP_ADJ, app.setAdj);
+ assertEquals(PREVIOUS_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -714,8 +709,8 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
- client.maxAdj = PERSISTENT_PROC_ADJ;
- client.setHasTopUi(true);
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ client.mState.setHasTopUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -731,11 +726,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_IMPORTANT, mock(IBinder.class));
- client.executingServices.add(mock(ServiceRecord.class));
+ client.mServices.startExecutingService(mock(ServiceRecord.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(FOREGROUND_APP_ADJ, app.setAdj);
+ assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -763,11 +758,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
- client.maxAdj = PERSISTENT_PROC_ADJ;
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_BOUND_FOREGROUND_SERVICE, app.setProcState);
+ assertEquals(PROCESS_STATE_BOUND_FOREGROUND_SERVICE, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -778,11 +773,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
- client.maxAdj = PERSISTENT_PROC_ADJ;
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app.setProcState);
+ assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -793,11 +788,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, 0, mock(IBinder.class));
- client.setHasForegroundServices(true, 0);
+ client.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app.setProcState);
+ assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -815,12 +810,12 @@ public class MockingOomAdjusterTests {
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
doReturn(null).when(sService.mBackupTargets).get(anyInt());
- assertEquals(BACKUP_APP_ADJ, app.setAdj);
+ assertEquals(BACKUP_APP_ADJ, app.mState.getSetAdj());
- client.maxAdj = PERSISTENT_PROC_ADJ;
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PERSISTENT_SERVICE_ADJ, app.setAdj);
+ assertEquals(PERSISTENT_SERVICE_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -831,11 +826,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
- client.runningRemoteAnimation = true;
+ client.mState.setRunningRemoteAnimation(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PERCEPTIBLE_LOW_APP_ADJ, app.setAdj);
+ assertEquals(PERCEPTIBLE_LOW_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -846,11 +841,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_NOT_VISIBLE, mock(IBinder.class));
- client.runningRemoteAnimation = true;
+ client.mState.setRunningRemoteAnimation(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PERCEPTIBLE_APP_ADJ, app.setAdj);
+ assertEquals(PERCEPTIBLE_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -861,11 +856,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, 0, mock(IBinder.class));
- client.setHasOverlayUi(true);
+ client.mState.setHasOverlayUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PERCEPTIBLE_APP_ADJ, app.setAdj);
+ assertEquals(PERCEPTIBLE_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -876,11 +871,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, 0, mock(IBinder.class));
- client.runningRemoteAnimation = true;
+ client.mState.setRunningRemoteAnimation(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(VISIBLE_APP_ADJ, app.setAdj);
+ assertEquals(VISIBLE_APP_ADJ, app.mState.getSetAdj());
}
@SuppressWarnings("GuardedBy")
@@ -891,11 +886,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_IMPORTANT_BACKGROUND, mock(IBinder.class));
- client.setHasOverlayUi(true);
+ client.mState.setHasOverlayUi(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_IMPORTANT_BACKGROUND, app.setProcState);
+ assertEquals(PROCESS_STATE_IMPORTANT_BACKGROUND, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -917,7 +912,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindProvider(app, client, null, null, false);
- client.treatLikeActivity = true;
+ client.mServices.setTreatLikeActivity(true);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -948,7 +943,7 @@ public class MockingOomAdjusterTests {
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- client.setHasForegroundServices(true, 0);
+ client.mServices.setHasForegroundServices(true, 0);
bindProvider(app, client, null, null, false);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -977,7 +972,7 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoOne_Provider_Retention() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.lastProviderTime = SystemClock.uptimeMillis();
+ app.mProviders.setLastProviderTime(SystemClock.uptimeMillis());
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1017,7 +1012,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(app, client2, null, 0, mock(IBinder.class));
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1036,7 +1031,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1055,9 +1050,9 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
bindService(client2, app, null, 0, mock(IBinder.class));
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ ArrayList lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
lru.add(app);
lru.add(client);
@@ -1072,13 +1067,13 @@ public class MockingOomAdjusterTests {
assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
- client2.setHasForegroundServices(false, 0);
+ client2.mServices.setHasForegroundServices(false, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(client2, true, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertEquals(PROCESS_STATE_CACHED_EMPTY, client2.setProcState);
- assertEquals(PROCESS_STATE_CACHED_EMPTY, client.setProcState);
- assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState);
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, client2.mState.getSetProcState());
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, client.mState.getSetProcState());
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, app.mState.getSetProcState());
}
@SuppressWarnings("GuardedBy")
@@ -1093,8 +1088,8 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client2, client, null, 0, mock(IBinder.class));
- client.setHasForegroundServices(true, 0);
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ client.mServices.setHasForegroundServices(true, 0);
+ ArrayList lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
lru.add(app);
lru.add(client);
@@ -1121,11 +1116,11 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
bindService(client2, app, null, 0, mock(IBinder.class));
ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
- client3.forcingToImportant = new Object();
+ client3.mState.setForcingToImportant(new Object());
bindService(app, client3, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1146,12 +1141,11 @@ public class MockingOomAdjusterTests {
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
bindService(client2, app, null, 0, mock(IBinder.class));
- doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
WindowProcessController wpc = client2.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
- client3.forcingToImportant = new Object();
+ client3.mState.setForcingToImportant(new Object());
bindService(app, client3, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1172,14 +1166,13 @@ public class MockingOomAdjusterTests {
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
bindService(client2, app, null, 0, mock(IBinder.class));
- doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
WindowProcessController wpc = client2.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
- client4.forcingToImportant = new Object();
+ client4.mState.setForcingToImportant(new Object());
bindService(app, client4, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1200,16 +1193,15 @@ public class MockingOomAdjusterTests {
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(client, client2, null, 0, mock(IBinder.class));
bindService(client2, app, null, 0, mock(IBinder.class));
- doReturn(mock(WindowProcessController.class)).when(client2).getWindowProcessController();
WindowProcessController wpc = client2.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
- client3.forcingToImportant = new Object();
+ client3.mState.setForcingToImportant(new Object());
bindService(app, client3, null, 0, mock(IBinder.class));
ProcessRecord client4 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
- client4.setHasForegroundServices(true, 0);
+ client4.mServices.setHasForegroundServices(true, 0);
bindService(app, client4, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1225,17 +1217,16 @@ public class MockingOomAdjusterTests {
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- doReturn(mock(WindowProcessController.class)).when(client).getWindowProcessController();
WindowProcessController wpc = client.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
bindService(app, client, null, 0, mock(IBinder.class));
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(app, client2, null, 0, mock(IBinder.class));
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
- client3.forcingToImportant = new Object();
+ client3.mState.setForcingToImportant(new Object());
bindService(app, client3, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1255,7 +1246,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindProvider(client, client2, null, null, false);
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1274,7 +1265,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindProvider(client, client2, null, null, false);
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
bindService(client2, app, null, 0, mock(IBinder.class));
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1294,7 +1285,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindProvider(client, client2, null, null, false);
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1313,7 +1304,7 @@ public class MockingOomAdjusterTests {
ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindProvider(client, client2, null, null, false);
- client2.setHasForegroundServices(true, 0);
+ client2.mServices.setHasForegroundServices(true, 0);
bindProvider(client2, app, null, null, false);
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1327,11 +1318,11 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoAll_Unbound() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.forcingToImportant = new Object();
+ app.mState.setForcingToImportant(new Object());
ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- app2.setHasForegroundServices(true, 0);
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ app2.mServices.setHasForegroundServices(true, 0);
+ ArrayList lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
lru.add(app);
lru.add(app2);
@@ -1350,12 +1341,12 @@ public class MockingOomAdjusterTests {
public void testUpdateOomAdj_DoAll_BoundFgService() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
- app.forcingToImportant = new Object();
+ app.mState.setForcingToImportant(new Object());
ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
- app2.setHasForegroundServices(true, 0);
+ app2.mServices.setHasForegroundServices(true, 0);
bindService(app, app2, null, 0, mock(IBinder.class));
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ ArrayList lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
lru.add(app);
lru.add(app2);
@@ -1380,9 +1371,9 @@ public class MockingOomAdjusterTests {
ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(app2, app3, null, 0, mock(IBinder.class));
- app3.setHasForegroundServices(true, 0);
+ app3.mServices.setHasForegroundServices(true, 0);
bindService(app3, app, null, 0, mock(IBinder.class));
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ ArrayList lru = sService.mProcessList.getLruProcessesLOSP();
lru.clear();
lru.add(app);
lru.add(app2);
@@ -1397,15 +1388,15 @@ public class MockingOomAdjusterTests {
SCHED_GROUP_DEFAULT);
assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
- assertEquals("service", app.adjType);
- assertEquals("service", app2.adjType);
- assertEquals("fg-service", app3.adjType);
+ assertEquals("service", app.mState.getAdjType());
+ assertEquals("service", app2.mState.getAdjType());
+ assertEquals("fg-service", app3.mState.getAdjType());
assertEquals(false, app.isCached());
assertEquals(false, app2.isCached());
assertEquals(false, app3.isCached());
- assertEquals(false, app.empty);
- assertEquals(false, app2.empty);
- assertEquals(false, app3.empty);
+ assertEquals(false, app.mState.isEmpty());
+ assertEquals(false, app2.mState.isEmpty());
+ assertEquals(false, app3.mState.isEmpty());
}
@SuppressWarnings("GuardedBy")
@@ -1420,18 +1411,17 @@ public class MockingOomAdjusterTests {
MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
bindService(app2, app3, null, 0, mock(IBinder.class));
bindService(app3, app, null, 0, mock(IBinder.class));
- doReturn(mock(WindowProcessController.class)).when(app3).getWindowProcessController();
WindowProcessController wpc = app3.getWindowProcessController();
doReturn(true).when(wpc).isHomeProcess();
ProcessRecord app4 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
- app4.setHasOverlayUi(true);
+ app4.mState.setHasOverlayUi(true);
bindService(app, app4, s, 0, mock(IBinder.class));
ProcessRecord app5 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
- app5.setHasForegroundServices(true, 0);
+ app5.mServices.setHasForegroundServices(true, 0);
bindService(app, app5, s, 0, mock(IBinder.class));
- ArrayList lru = sService.mProcessList.mLruProcesses;
+ ArrayList