Skip to content

Commit a93c2c1

Browse files
author
Dianne Hackborn
committed
Extend process observer to be usable for media routing.
It now has a new callback to report changes in the "importance" of processes. Rewrote the dispatching code to be a bit more efficient now that we are sending more reports. Change-Id: Ie865cfd286455819f04e8c14e9b6fd54d028f8f2
1 parent f0e96de commit a93c2c1

File tree

5 files changed

+158
-23
lines changed

5 files changed

+158
-23
lines changed

core/java/android/app/ActivityManager.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,13 @@ public static class RunningAppProcessInfo implements Parcelable {
13591359
*/
13601360
public int lastTrimLevel;
13611361

1362+
/**
1363+
* Constant for {@link #importance}: this is a persistent process.
1364+
* Only used when reporting to process observers.
1365+
* @hide
1366+
*/
1367+
public static final int IMPORTANCE_PERSISTENT = 50;
1368+
13621369
/**
13631370
* Constant for {@link #importance}: this process is running the
13641371
* foreground UI.

core/java/android/app/IProcessObserver.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package android.app;
2020
oneway interface IProcessObserver {
2121

2222
void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
23+
void onImportanceChanged(int pid, int uid, int importance);
2324
void onProcessDied(int pid, int uid);
2425

2526
}

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 145 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ public final class ActivityManagerService extends ActivityManagerNative
176176
static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
177177
static final boolean DEBUG_VISBILITY = localLOGV || false;
178178
static final boolean DEBUG_PROCESSES = localLOGV || false;
179+
static final boolean DEBUG_PROCESS_OBSERVERS = localLOGV || false;
179180
static final boolean DEBUG_PROVIDER = localLOGV || false;
180181
static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
181182
static final boolean DEBUG_USER_LEAVING = localLOGV || false;
@@ -764,8 +765,24 @@ private class Identity {
764765
boolean mAutoStopProfiler = false;
765766
String mOpenGlTraceApp = null;
766767

768+
static class ProcessChangeItem {
769+
static final int CHANGE_ACTIVITIES = 1<<0;
770+
static final int CHANGE_IMPORTANCE= 1<<1;
771+
int changes;
772+
int uid;
773+
int pid;
774+
int importance;
775+
boolean foregroundActivities;
776+
}
777+
767778
final RemoteCallbackList<IProcessObserver> mProcessObservers
768779
= new RemoteCallbackList<IProcessObserver>();
780+
ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
781+
782+
final ArrayList<ProcessChangeItem> mPendingProcessChanges
783+
= new ArrayList<ProcessChangeItem>();
784+
final ArrayList<ProcessChangeItem> mAvailProcessChanges
785+
= new ArrayList<ProcessChangeItem>();
769786

770787
/**
771788
* Callback of last caller to {@link #requestPss}.
@@ -855,7 +872,7 @@ public void binderDied() {
855872
static final int CLEAR_DNS_CACHE = 28;
856873
static final int UPDATE_HTTP_PROXY = 29;
857874
static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
858-
static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
875+
static final int DISPATCH_PROCESSES_CHANGED = 31;
859876
static final int DISPATCH_PROCESS_DIED = 32;
860877
static final int REPORT_MEM_USAGE = 33;
861878

@@ -1195,11 +1212,8 @@ public void handleMessage(Message msg) {
11951212
}
11961213
break;
11971214
}
1198-
case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
1199-
final int pid = msg.arg1;
1200-
final int uid = msg.arg2;
1201-
final boolean foregroundActivities = (Boolean) msg.obj;
1202-
dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
1215+
case DISPATCH_PROCESSES_CHANGED: {
1216+
dispatchProcessesChanged();
12031217
break;
12041218
}
12051219
case DISPATCH_PROCESS_DIED: {
@@ -2260,19 +2274,43 @@ public void setPackageAskScreenCompat(String packageName, boolean ask) {
22602274

22612275
void reportResumedActivityLocked(ActivityRecord r) {
22622276
//Slog.i(TAG, "**** REPORT RESUME: " + r);
2263-
2264-
final int identHash = System.identityHashCode(r);
22652277
updateUsageStats(r, true);
22662278
}
22672279

2268-
private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2280+
private void dispatchProcessesChanged() {
2281+
int N;
2282+
synchronized (this) {
2283+
N = mPendingProcessChanges.size();
2284+
if (mActiveProcessChanges.length < N) {
2285+
mActiveProcessChanges = new ProcessChangeItem[N];
2286+
}
2287+
mPendingProcessChanges.toArray(mActiveProcessChanges);
2288+
mAvailProcessChanges.addAll(mPendingProcessChanges);
2289+
mPendingProcessChanges.clear();
2290+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "*** Delivering " + N + " process changes");
2291+
}
22692292
int i = mProcessObservers.beginBroadcast();
22702293
while (i > 0) {
22712294
i--;
22722295
final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
22732296
if (observer != null) {
22742297
try {
2275-
observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2298+
for (int j=0; j<N; j++) {
2299+
ProcessChangeItem item = mActiveProcessChanges[j];
2300+
if ((item.changes&ProcessChangeItem.CHANGE_ACTIVITIES) != 0) {
2301+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "ACTIVITIES CHANGED pid="
2302+
+ item.pid + " uid=" + item.uid + ": "
2303+
+ item.foregroundActivities);
2304+
observer.onForegroundActivitiesChanged(item.pid, item.uid,
2305+
item.foregroundActivities);
2306+
}
2307+
if ((item.changes&ProcessChangeItem.CHANGE_IMPORTANCE) != 0) {
2308+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "IMPORTANCE CHANGED pid="
2309+
+ item.pid + " uid=" + item.uid + ": " + item.importance);
2310+
observer.onImportanceChanged(item.pid, item.uid,
2311+
item.importance);
2312+
}
2313+
}
22762314
} catch (RemoteException e) {
22772315
}
22782316
}
@@ -10802,6 +10840,13 @@ private final void cleanUpApplicationRecordLocked(ProcessRecord app,
1080210840
}
1080310841
}
1080410842

10843+
for (int i = mPendingProcessChanges.size()-1; i>=0; i--) {
10844+
ProcessChangeItem item = mPendingProcessChanges.get(i);
10845+
if (item.pid == app.pid) {
10846+
mPendingProcessChanges.remove(i);
10847+
mAvailProcessChanges.add(item);
10848+
}
10849+
}
1080510850
mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
1080610851

1080710852
// If the caller is restarting this app, then leave it in its
@@ -13734,28 +13779,29 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1373413779
return (app.curAdj=app.maxAdj);
1373513780
}
1373613781

13737-
final boolean hadForegroundActivities = app.foregroundActivities;
13738-
13739-
app.foregroundActivities = false;
1374013782
app.keeping = false;
1374113783
app.systemNoUi = false;
1374213784

1374313785
// Determine the importance of the process, starting with most
1374413786
// important to least, and assign an appropriate OOM adjustment.
1374513787
int adj;
1374613788
int schedGroup;
13789+
boolean foregroundActivities = false;
13790+
boolean interesting = false;
1374713791
BroadcastQueue queue;
1374813792
if (app == TOP_APP) {
1374913793
// The last app on the list is the foreground app.
1375013794
adj = ProcessList.FOREGROUND_APP_ADJ;
1375113795
schedGroup = Process.THREAD_GROUP_DEFAULT;
1375213796
app.adjType = "top-activity";
13753-
app.foregroundActivities = true;
13797+
foregroundActivities = true;
13798+
interesting = true;
1375413799
} else if (app.instrumentationClass != null) {
1375513800
// Don't want to kill running instrumentation.
1375613801
adj = ProcessList.FOREGROUND_APP_ADJ;
1375713802
schedGroup = Process.THREAD_GROUP_DEFAULT;
1375813803
app.adjType = "instrumentation";
13804+
interesting = true;
1375913805
} else if ((queue = isReceivingBroadcast(app)) != null) {
1376013806
// An app that is currently receiving a broadcast also
1376113807
// counts as being in the foreground for OOM killer purposes.
@@ -13791,7 +13837,7 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1379113837
boolean hasStoppingActivities = false;
1379213838

1379313839
// Examine all activities if not already foreground.
13794-
if (!app.foregroundActivities && activitiesSize > 0) {
13840+
if (!foregroundActivities && activitiesSize > 0) {
1379513841
for (int j = 0; j < activitiesSize; j++) {
1379613842
final ActivityRecord r = app.activities.get(j);
1379713843
if (r.visible) {
@@ -13802,21 +13848,21 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1380213848
}
1380313849
schedGroup = Process.THREAD_GROUP_DEFAULT;
1380413850
app.hidden = false;
13805-
app.foregroundActivities = true;
13851+
foregroundActivities = true;
1380613852
break;
1380713853
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
1380813854
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
1380913855
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
1381013856
app.adjType = "pausing";
1381113857
}
1381213858
app.hidden = false;
13813-
app.foregroundActivities = true;
13859+
foregroundActivities = true;
1381413860
} else if (r.state == ActivityState.STOPPING) {
1381513861
// We will apply the actual adjustment later, because
1381613862
// we want to allow this process to immediately go through
1381713863
// any memory trimming that is in effect.
1381813864
app.hidden = false;
13819-
app.foregroundActivities = true;
13865+
foregroundActivities = true;
1382013866
hasStoppingActivities = true;
1382113867
}
1382213868
}
@@ -13839,6 +13885,10 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1383913885
}
1384013886
}
1384113887

13888+
if (app.foregroundServices) {
13889+
interesting = true;
13890+
}
13891+
1384213892
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
1384313893
// We don't want to kill the current heavy-weight process.
1384413894
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
@@ -14188,12 +14238,84 @@ private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
1418814238
}
1418914239
}
1419014240

14191-
app.curAdj = adj;
14192-
app.curSchedGroup = schedGroup;
14241+
int importance = app.memImportance;
14242+
if (importance == 0 || adj != app.curAdj || schedGroup != app.curSchedGroup) {
14243+
app.curAdj = adj;
14244+
app.curSchedGroup = schedGroup;
14245+
if (!interesting) {
14246+
// For this reporting, if there is not something explicitly
14247+
// interesting in this process then we will push it to the
14248+
// background importance.
14249+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
14250+
} else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
14251+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
14252+
} else if (adj >= ProcessList.SERVICE_B_ADJ) {
14253+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
14254+
} else if (adj >= ProcessList.HOME_APP_ADJ) {
14255+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
14256+
} else if (adj >= ProcessList.SERVICE_ADJ) {
14257+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
14258+
} else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
14259+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
14260+
} else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
14261+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
14262+
} else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
14263+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
14264+
} else if (adj >= ProcessList.FOREGROUND_APP_ADJ) {
14265+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
14266+
} else {
14267+
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERSISTENT;
14268+
}
14269+
}
1419314270

14194-
if (hadForegroundActivities != app.foregroundActivities) {
14195-
mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
14196-
app.foregroundActivities).sendToTarget();
14271+
int changes = importance != app.memImportance ? ProcessChangeItem.CHANGE_IMPORTANCE : 0;
14272+
if (foregroundActivities != app.foregroundActivities) {
14273+
changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
14274+
}
14275+
if (changes != 0) {
14276+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
14277+
app.memImportance = importance;
14278+
app.foregroundActivities = foregroundActivities;
14279+
int i = mPendingProcessChanges.size()-1;
14280+
ProcessChangeItem item = null;
14281+
while (i >= 0) {
14282+
item = mPendingProcessChanges.get(i);
14283+
if (item.pid == app.pid) {
14284+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
14285+
break;
14286+
}
14287+
i--;
14288+
}
14289+
if (i < 0) {
14290+
// No existing item in pending changes; need a new one.
14291+
final int NA = mAvailProcessChanges.size();
14292+
if (NA > 0) {
14293+
item = mAvailProcessChanges.remove(NA-1);
14294+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
14295+
} else {
14296+
item = new ProcessChangeItem();
14297+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
14298+
}
14299+
item.changes = 0;
14300+
item.pid = app.pid;
14301+
item.uid = app.info.uid;
14302+
if (mPendingProcessChanges.size() == 0) {
14303+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
14304+
"*** Enqueueing dispatch processes changed!");
14305+
mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
14306+
}
14307+
mPendingProcessChanges.add(item);
14308+
}
14309+
item.changes |= changes;
14310+
item.importance = importance;
14311+
item.foregroundActivities = foregroundActivities;
14312+
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
14313+
+ Integer.toHexString(System.identityHashCode(item))
14314+
+ " " + app.toShortString() + ": changes=" + item.changes
14315+
+ " importance=" + item.importance
14316+
+ " foreground=" + item.foregroundActivities
14317+
+ " type=" + app.adjType + " source=" + app.adjSource
14318+
+ " target=" + app.adjTarget);
1419714319
}
1419814320

1419914321
return app.curRawAdj;

services/java/com/android/server/am/ProcessRecord.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ProcessRecord {
6969
int curSchedGroup; // Currently desired scheduling class
7070
int setSchedGroup; // Last set to background scheduling class
7171
int trimMemoryLevel; // Last selected memory trimming level
72+
int memImportance; // Importance constant computed from curAdj
7273
boolean serviceb; // Process currently is on the service B list
7374
boolean keeping; // Actively running code so don't kill due to that?
7475
boolean setIsForeground; // Running foreground UI when last set?

services/java/com/android/server/net/NetworkPolicyManagerService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundAc
395395
pid, uid, foregroundActivities).sendToTarget();
396396
}
397397

398+
@Override
399+
public void onImportanceChanged(int pid, int uid, int importance) {
400+
}
401+
398402
@Override
399403
public void onProcessDied(int pid, int uid) {
400404
mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget();

0 commit comments

Comments
 (0)