Merge "Fix various issues in ordering of grouped bindings."
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6f0b6c8..c7a9d99 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1731,8 +1731,11 @@
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
- IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
- getOuterContext(), conn);
+ IServiceConnection sd = mPackageInfo.lookupServiceDispatcher(conn, getOuterContext());
+ if (sd == null) {
+ throw new IllegalArgumentException("ServiceConnection not currently bound: "
+ + conn);
+ }
try {
ActivityManager.getService().updateServiceGroup(sd, group, importance);
} catch (RemoteException e) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 719bba0..759763b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1659,6 +1659,19 @@
}
}
+ @UnsupportedAppUsage
+ public IServiceConnection lookupServiceDispatcher(ServiceConnection c,
+ Context context) {
+ synchronized (mServices) {
+ LoadedApk.ServiceDispatcher sd = null;
+ ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
+ if (map != null) {
+ sd = map.get(c);
+ }
+ return sd != null ? sd.getIServiceConnection() : null;
+ }
+ }
+
public final IServiceConnection forgetServiceDispatcher(Context context,
ServiceConnection c) {
synchronized (mServices) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fe11acb..e2c7b85 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3003,6 +3003,11 @@
* how the process will be managed in some cases based on those flags. Currently only
* works on isolated processes (will be ignored for non-isolated processes).
*
+ * <p>Note that this call does not take immediate effect, but will be applied the next
+ * time the impacted process is adjusted for some other reason. Typically you would
+ * call this before then calling a new {@link #bindIsolatedService} on the service
+ * of interest, with that binding causing the process to be shuffled accordingly.</p>
+ *
* @param conn The connection interface previously supplied to bindService(). This
* parameter must not be null.
* @param group A group to put this connection's process in. Upon calling here, this
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 98a135f..07d6e47 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1303,7 +1303,7 @@
/** {@hide} */
public void writeToProto(ProtoOutputStream proto, long fieldId, int dumpFlags) {
long token = proto.start(fieldId);
- super.writeToProto(proto, ApplicationInfoProto.PACKAGE);
+ super.writeToProto(proto, ApplicationInfoProto.PACKAGE, dumpFlags);
proto.write(ApplicationInfoProto.PERMISSION, permission);
proto.write(ApplicationInfoProto.PROCESS_NAME, processName);
proto.write(ApplicationInfoProto.UID, uid);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index cdb7814..ff7b347 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -433,18 +433,18 @@
/**
* @hide
*/
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, int dumpFlags) {
long token = proto.start(fieldId);
if (name != null) {
proto.write(PackageItemInfoProto.NAME, name);
}
proto.write(PackageItemInfoProto.PACKAGE_NAME, packageName);
- if (labelRes != 0 || nonLocalizedLabel != null || icon != 0 || banner != 0) {
- proto.write(PackageItemInfoProto.LABEL_RES, labelRes);
+ proto.write(PackageItemInfoProto.LABEL_RES, labelRes);
+ if (nonLocalizedLabel != null) {
proto.write(PackageItemInfoProto.NON_LOCALIZED_LABEL, nonLocalizedLabel.toString());
- proto.write(PackageItemInfoProto.ICON, icon);
- proto.write(PackageItemInfoProto.BANNER, banner);
}
+ proto.write(PackageItemInfoProto.ICON, icon);
+ proto.write(PackageItemInfoProto.BANNER, banner);
proto.end(token);
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index ab50ad1..60561bd 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -185,6 +185,7 @@
optional int32 app_id = 5;
optional int32 isolated_app_id = 6;
optional bool persistent = 7;
+ optional int32 lru_index = 8;
}
message BroadcastRecordProto {
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 8cd9d188..15de3de 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -133,7 +133,7 @@
proto.write(ActiveInstrumentationProto.TARGET_PROCESSES, p);
}
if (mTargetInfo != null) {
- mTargetInfo.writeToProto(proto, ActiveInstrumentationProto.TARGET_INFO);
+ mTargetInfo.writeToProto(proto, ActiveInstrumentationProto.TARGET_INFO, 0);
}
proto.write(ActiveInstrumentationProto.PROFILE_FILE, mProfileFile);
proto.write(ActiveInstrumentationProto.WATCHER, mWatcher.toString());
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a19e928..23287cf 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1801,16 +1801,25 @@
for (int i = clist.size() - 1; i >= 0; i--) {
final ConnectionRecord crec = clist.get(i);
final ServiceRecord srec = crec.binding.service;
- if (srec != null && srec.app != null
- && (srec.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) {
- if (group > 0) {
- srec.app.connectionService = srec;
- srec.app.connectionGroup = group;
- srec.app.connectionImportance = importance;
+ if (srec != null && (srec.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) {
+ if (srec.app != null) {
+ if (group > 0) {
+ srec.app.connectionService = srec;
+ srec.app.connectionGroup = group;
+ srec.app.connectionImportance = importance;
+ } else {
+ srec.app.connectionService = null;
+ srec.app.connectionGroup = 0;
+ srec.app.connectionImportance = 0;
+ }
} else {
- srec.app.connectionService = null;
- srec.app.connectionGroup = 0;
- srec.app.connectionImportance = 0;
+ if (group > 0) {
+ srec.pendingConnectionGroup = group;
+ srec.pendingConnectionImportance = importance;
+ } else {
+ srec.pendingConnectionGroup = 0;
+ srec.pendingConnectionImportance = 0;
+ }
}
}
}
@@ -2058,8 +2067,8 @@
sInfo.applicationInfo.uid, name.getPackageName(),
name.getClassName());
}
- r = new ServiceRecord(mAm, ss, className, name, filter, sInfo, callingFromFg,
- res);
+ r = new ServiceRecord(mAm, ss, className, name, filter, sInfo,
+ callingFromFg, res);
res.setService(r);
smap.mServicesByInstanceName.put(name, r);
smap.mServicesByIntent.put(filter, r);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8842f41..dc4eeaf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9209,6 +9209,19 @@
}
sdumper.dumpWithClient();
}
+ if (dumpPackage == null) {
+ // Intentionally dropping the lock for this, because dumpBinderProxies() will make many
+ // outgoing binder calls to retrieve interface descriptors; while that is system code,
+ // there is nothing preventing an app from overriding this implementation by talking to
+ // the binder driver directly, and hang up system_server in the process. So, dump
+ // without locks held, and even then only when there is an unreasonably large number of
+ // proxies in the first place.
+ pw.println();
+ if (dumpAll) {
+ pw.println("-------------------------------------------------------------------------------");
+ }
+ dumpBinderProxies(pw, BINDER_PROXY_HIGH_WATERMARK /* minToDump */);
+ }
synchronized(this) {
pw.println();
if (dumpAll) {
@@ -9274,19 +9287,6 @@
}
dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
}
- if (dumpPackage == null) {
- // Intentionally dropping the lock for this, because dumpBinderProxies() will make many
- // outgoing binder calls to retrieve interface descriptors; while that is system code,
- // there is nothing preventing an app from overriding this implementation by talking to
- // the binder driver directly, and hang up system_server in the process. So, dump
- // without locks held, and even then only when there is an unreasonably large number of
- // proxies in the first place.
- pw.println();
- if (dumpAll) {
- pw.println("-------------------------------------------------------------------------------");
- }
- dumpBinderProxies(pw, BINDER_PROXY_HIGH_WATERMARK /* minToDump */);
- }
}
/**
@@ -10266,7 +10266,8 @@
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
continue;
}
- r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PROCS);
+ r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PROCS, mProcessList.mLruProcesses.indexOf(r)
+ );
if (r.isPersistent()) {
numPers++;
}
@@ -10278,7 +10279,9 @@
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
continue;
}
- r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ISOLATED_PROCS);
+ r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.ISOLATED_PROCS,
+ mProcessList.mLruProcesses.indexOf(r)
+ );
}
for (int i=0; i<mActiveInstrumentation.size(); i++) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 62f1009..8cf9f1e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -537,40 +537,44 @@
}
private static String buildOomTag(String prefix, String space, int val, int base) {
- if (val == base) {
+ final int diff = val - base;
+ if (diff == 0) {
if (space == null) return prefix;
- return prefix + " ";
+ return prefix + space;
}
- return prefix + "+" + Integer.toString(val - base);
+ if (diff < 10) {
+ return prefix + "+ " + Integer.toString(diff);
+ }
+ return prefix + "+" + Integer.toString(diff);
}
public static String makeOomAdjString(int setAdj) {
if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- return buildOomTag("cch", " ", setAdj, ProcessList.CACHED_APP_MIN_ADJ);
+ return buildOomTag("cch", " ", setAdj, ProcessList.CACHED_APP_MIN_ADJ);
} else if (setAdj >= ProcessList.SERVICE_B_ADJ) {
- return buildOomTag("svcb ", null, setAdj, ProcessList.SERVICE_B_ADJ);
+ return buildOomTag("svcb ", null, setAdj, ProcessList.SERVICE_B_ADJ);
} else if (setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
- return buildOomTag("prev ", null, setAdj, ProcessList.PREVIOUS_APP_ADJ);
+ return buildOomTag("prev ", null, setAdj, ProcessList.PREVIOUS_APP_ADJ);
} else if (setAdj >= ProcessList.HOME_APP_ADJ) {
- return buildOomTag("home ", null, setAdj, ProcessList.HOME_APP_ADJ);
+ return buildOomTag("home ", null, setAdj, ProcessList.HOME_APP_ADJ);
} else if (setAdj >= ProcessList.SERVICE_ADJ) {
- return buildOomTag("svc ", null, setAdj, ProcessList.SERVICE_ADJ);
+ return buildOomTag("svc ", null, setAdj, ProcessList.SERVICE_ADJ);
} else if (setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
- return buildOomTag("hvy ", null, setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
+ return buildOomTag("hvy ", null, setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
} else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
- return buildOomTag("bkup ", null, setAdj, ProcessList.BACKUP_APP_ADJ);
+ return buildOomTag("bkup ", null, setAdj, ProcessList.BACKUP_APP_ADJ);
} else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
- return buildOomTag("prcp ", null, setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
+ return buildOomTag("prcp ", null, setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
} else if (setAdj >= ProcessList.VISIBLE_APP_ADJ) {
- return buildOomTag("vis ", null, setAdj, ProcessList.VISIBLE_APP_ADJ);
+ return buildOomTag("vis", " ", setAdj, ProcessList.VISIBLE_APP_ADJ);
} else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- return buildOomTag("fore ", null, setAdj, ProcessList.FOREGROUND_APP_ADJ);
+ return buildOomTag("fore ", null, setAdj, ProcessList.FOREGROUND_APP_ADJ);
} else if (setAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
- return buildOomTag("psvc ", null, setAdj, ProcessList.PERSISTENT_SERVICE_ADJ);
+ return buildOomTag("psvc ", null, setAdj, ProcessList.PERSISTENT_SERVICE_ADJ);
} else if (setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
- return buildOomTag("pers ", null, setAdj, ProcessList.PERSISTENT_PROC_ADJ);
+ return buildOomTag("pers ", null, setAdj, ProcessList.PERSISTENT_PROC_ADJ);
} else if (setAdj >= ProcessList.SYSTEM_ADJ) {
- return buildOomTag("sys ", null, setAdj, ProcessList.SYSTEM_ADJ);
+ return buildOomTag("sys ", null, setAdj, ProcessList.SYSTEM_ADJ);
} else if (setAdj >= ProcessList.NATIVE_ADJ) {
return buildOomTag("ntv ", null, setAdj, ProcessList.NATIVE_ADJ);
} else {
@@ -2237,6 +2241,191 @@
return index;
}
+ /**
+ * Handle the case where we are inserting a process hosting client activities:
+ * Make sure any groups have their order match their importance, and take care of
+ * distributing old clients across other activity processes so they can't spam
+ * the LRU list. Processing of the list will be restricted by the indices provided,
+ * and not extend out of them.
+ *
+ * @param topApp The app at the top that has just been inserted in to the list.
+ * @param topI The position in the list where topApp was inserted; this is the start (at the
+ * top) where we are going to do our processing.
+ * @param bottomI The last position at which we will be processing; this is the end position
+ * of whichever section of the LRU list we are in. Nothing past it will be
+ * touched.
+ * @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,
+ final int bottomI, int endIndex) {
+ if (topApp.hasActivitiesOrRecentTasks() || topApp.treatLikeActivity
+ || !topApp.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;
+ for (int i = endIndex; i >= bottomI; i--) {
+ final ProcessRecord subProc = mLruProcesses.get(i);
+ if (subProc.info.uid == uid
+ && subProc.connectionGroup == topApp.connectionGroup) {
+ if (i == endIndex && subProc.connectionImportance >= 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);
+ endIndex--;
+ endImportance = subProc.connectionImportance;
+ } 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);
+ boolean moved = false;
+ for (int pos = topI; pos > endIndex; pos--) {
+ final ProcessRecord posProc = mLruProcesses.get(pos);
+ if (subProc.connectionImportance
+ <= posProc.connectionImportance) {
+ mLruProcesses.remove(i);
+ mLruProcesses.add(pos, subProc);
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Moving " + subProc
+ + " from position " + i + " to above " + posProc
+ + " @ " + pos);
+ moved = true;
+ endIndex--;
+ break;
+ }
+ }
+ if (!moved) {
+ // Goes to the end of the group.
+ mLruProcesses.remove(i);
+ mLruProcesses.add(endIndex - 1, subProc);
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Moving " + subProc
+ + " from position " + i + " to end of group @ "
+ + endIndex);
+ endIndex--;
+ endImportance = subProc.connectionImportance;
+ }
+ }
+ }
+ }
+
+ }
+ // To keep it from spamming the LRU list (by making a bunch of clients),
+ // we will distribute other entries owned by it to be in-between other apps.
+ int i = endIndex;
+ while (i >= bottomI) {
+ ProcessRecord subProc = mLruProcesses.get(i);
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Looking to spread old procs, at " + subProc + " @ " + i);
+ if (subProc.info.uid != uid) {
+ // This is a different app... if we have gone through some of the
+ // target app, pull this up to be before them. We want to pull up
+ // one activity process, but any number of non-activity processes.
+ if (i < endIndex) {
+ boolean hasActivity = false;
+ int connUid = 0;
+ int connGroup = 0;
+ while (i >= bottomI) {
+ mLruProcesses.remove(i);
+ mLruProcesses.add(endIndex, subProc);
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Different app, moving to " + endIndex);
+ i--;
+ if (i < bottomI) {
+ break;
+ }
+ subProc = mLruProcesses.get(i);
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Looking at next app at " + i + ": " + subProc);
+ if (subProc.hasActivitiesOrRecentTasks() || subProc.treatLikeActivity) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "This is hosting an activity!");
+ if (hasActivity) {
+ // Already found an activity, done.
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Already found an activity, done");
+ break;
+ }
+ hasActivity = true;
+ } else if (subProc.hasClientActivities()) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "This is a client of an activity");
+ if (hasActivity) {
+ if (connUid == 0 || connUid != subProc.info.uid) {
+ // Already have an activity that is not from from a client
+ // connection or is a different client connection, done.
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Already found a different activity: connUid="
+ + connUid + " uid=" + subProc.info.uid);
+ break;
+ } else if (connGroup == 0 || connGroup != subProc.connectionGroup) {
+ // 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);
+ break;
+ }
+ } else {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "This is an activity client! uid="
+ + subProc.info.uid + " group=" + subProc.connectionGroup);
+ hasActivity = true;
+ connUid = subProc.info.uid;
+ connGroup = subProc.connectionGroup;
+ }
+ }
+ endIndex--;
+ }
+ }
+ // Find the end of the next group of processes for target app. This
+ // is after any entries of different apps (so we don't change the existing
+ // relative order of apps) and then after the next last group of processes
+ // of the target app.
+ for (endIndex--; endIndex >= bottomI; endIndex--) {
+ final ProcessRecord endProc = mLruProcesses.get(endIndex);
+ if (endProc.info.uid == uid) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Found next group of app: " + endProc + " @ "
+ + endIndex);
+ break;
+ }
+ }
+ if (endIndex >= bottomI) {
+ final ProcessRecord endProc = mLruProcesses.get(endIndex);
+ for (endIndex--; endIndex >= bottomI; endIndex--) {
+ final ProcessRecord nextEndProc = mLruProcesses.get(endIndex);
+ if (nextEndProc.info.uid != uid
+ || nextEndProc.connectionGroup != endProc.connectionGroup) {
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Found next group or app: " + nextEndProc + " @ "
+ + endIndex + " group=" + nextEndProc.connectionGroup);
+ break;
+ }
+ }
+ }
+ if (DEBUG_LRU) Slog.d(TAG_LRU,
+ "Bumping scan position to " + endIndex);
+ i = endIndex;
+ } else {
+ i--;
+ }
+ }
+ }
+
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
ProcessRecord client) {
final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities()
@@ -2349,91 +2538,31 @@
if (!app.hasActivitiesOrRecentTasks() && !app.treatLikeActivity
&& mLruProcessActivityStart < (N - 1)) {
// Process doesn't have activities, but has clients with
- // activities... move it up, but one below the top (the top
- // should always have a real activity).
+ // 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);
- mLruProcesses.add(N - 1, app);
+ "Adding to second-top of LRU activity list: " + app
+ + " group=" + app.connectionGroup
+ + " importance=" + app.connectionImportance);
+ int pos = N - 1;
+ while (pos > mLruProcessActivityStart) {
+ final ProcessRecord posproc = mLruProcesses.get(pos);
+ if (posproc.info.uid == app.info.uid) {
+ // Technically this app could have multiple processes with different
+ // activities and so we should be looking for the actual process that
+ // is bound to the target proc... but I don't really care, do you?
+ break;
+ }
+ pos--;
+ }
+ mLruProcesses.add(pos, app);
// If this process is part of a group, need to pull up any other processes
// in that group to be with it.
- final int uid = app.info.uid;
- int endIndex = N - 2;
- nextActivityIndex = N - 2;
- if (app.connectionGroup > 0) {
- int endImportance = app.connectionImportance;
- for (int i = endIndex; i >= mLruProcessActivityStart; i--) {
- final ProcessRecord subProc = mLruProcesses.get(i);
- if (subProc.info.uid == uid
- && subProc.connectionGroup == subProc.connectionGroup) {
- if (i == endIndex && subProc.connectionImportance >= endImportance) {
- // This process is already in the group, and its importance
- // is not as strong as the process before it, so it keep it
- // correctly positioned in the group.
- endIndex--;
- endImportance = subProc.connectionImportance;
- } else {
- // We want to pull this up to be with the rest of the group,
- // and order within the group by importance.
- boolean moved = false;
- for (int pos = N - 1; pos > endIndex; pos--) {
- final ProcessRecord posProc = mLruProcesses.get(pos);
- if (subProc.connectionImportance
- <= posProc.connectionImportance) {
- mLruProcesses.remove(i);
- mLruProcesses.add(pos, subProc);
- moved = true;
- endIndex--;
- break;
- }
- }
- if (!moved) {
- // Goes to the end of the group.
- mLruProcesses.remove(i);
- mLruProcesses.add(endIndex - 1, subProc);
- endIndex--;
- endImportance = subProc.connectionImportance;
- }
- }
- }
- }
-
+ int endIndex = pos - 1;
+ if (endIndex < mLruProcessActivityStart) {
+ endIndex = mLruProcessActivityStart;
}
- // To keep it from spamming the LRU list (by making a bunch of clients),
- // we will distribute other entries owned by it to be in-between other apps.
- for (int i = endIndex; i >= mLruProcessActivityStart; i--) {
- final ProcessRecord subProc = mLruProcesses.get(i);
- if (subProc.info.uid != uid) {
- // This is a different app... if we have gone through some of the
- // target app, pull this up to be before them.
- if (i < endIndex) {
- mLruProcesses.remove(i);
- mLruProcesses.add(endIndex, subProc);
- }
- // Find the end of the next group of processes for target app. This
- // is after any entries of different apps (so we don't change the existing
- // relative order of apps) and then after the next last group of processes
- // of the target app.
- for (endIndex--; endIndex >= mLruProcessActivityStart; endIndex--) {
- final ProcessRecord endProc = mLruProcesses.get(endIndex);
- if (endProc.info.uid == uid) {
- break;
- }
- }
- if (endIndex >= mLruProcessActivityStart) {
- final ProcessRecord endProc = mLruProcesses.get(endIndex);
- for (endIndex--; endIndex >= mLruProcessActivityStart; endIndex--) {
- final ProcessRecord nextEndProc = mLruProcesses.get(endIndex);
- if (nextEndProc.info.uid != uid
- || nextEndProc.connectionGroup != endProc.connectionGroup) {
- break;
- }
- }
- }
- if (i > endIndex) {
- i = endIndex;
- }
- }
- }
+ nextActivityIndex = endIndex;
+ updateClientActivitiesOrdering(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);
@@ -2469,6 +2598,9 @@
nextIndex = index - 1;
mLruProcessActivityStart++;
mLruProcessServiceStart++;
+ if (index > 1) {
+ updateClientActivitiesOrdering(app, mLruProcessServiceStart - 1, 0, index - 1);
+ }
}
app.lruSeq = mLruSeq;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 013de93..4826f48 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -586,7 +586,7 @@
}
origBase.makeInactive();
}
- baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
+ baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid,
info.longVersionCode, processName);
baseProcessTracker.makeActive();
for (int i=0; i<pkgList.size(); i++) {
@@ -594,7 +594,7 @@
if (holder.state != null && holder.state != origBase) {
holder.state.makeInactive();
}
- tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), uid,
+ tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), info.uid,
info.longVersionCode, processName);
if (holder.state != baseProcessTracker) {
holder.state.makeActive();
@@ -760,19 +760,25 @@
@Override
public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ writeToProto(proto, fieldId, -1);
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId, int lruIndex) {
long token = proto.start(fieldId);
proto.write(ProcessRecordProto.PID, pid);
proto.write(ProcessRecordProto.PROCESS_NAME, processName);
- if (info.uid < Process.FIRST_APPLICATION_UID) {
- proto.write(ProcessRecordProto.UID, uid);
- } else {
+ proto.write(ProcessRecordProto.UID, info.uid);
+ if (UserHandle.getAppId(info.uid) >= Process.FIRST_APPLICATION_UID) {
proto.write(ProcessRecordProto.USER_ID, userId);
proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid));
- if (uid != info.uid) {
- proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
- }
+ }
+ if (uid != info.uid) {
+ proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
}
proto.write(ProcessRecordProto.PERSISTENT, mPersistent);
+ if (lruIndex >= 0) {
+ proto.write(ProcessRecordProto.LRU_INDEX, lruIndex);
+ }
proto.end(token);
}
@@ -864,7 +870,8 @@
ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
versionCode);
if (baseProcessTracker != null) {
- tracker.updateProcessStateHolderLocked(holder, pkg, uid, versionCode, processName);
+ tracker.updateProcessStateHolderLocked(holder, pkg, info.uid, versionCode,
+ processName);
pkgList.put(pkg, holder);
if (holder.state != baseProcessTracker) {
holder.state.makeActive();
@@ -925,7 +932,7 @@
pkgList.clear();
ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
info.longVersionCode);
- tracker.updateProcessStateHolderLocked(holder, info.packageName, uid,
+ tracker.updateProcessStateHolderLocked(holder, info.packageName, info.uid,
info.longVersionCode, processName);
pkgList.put(info.packageName, holder);
if (holder.state != baseProcessTracker) {
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 09f8c3e..da5ce1c 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -121,6 +121,8 @@
long nextRestartTime; // time when restartDelay will expire.
boolean destroying; // set when we have started destroying the service
long destroyTime; // time at which destory was initiated.
+ int pendingConnectionGroup; // To be filled in to ProcessRecord once it connects
+ int pendingConnectionImportance; // To be filled in to ProcessRecord once it connects
String stringName; // caching of toString
@@ -386,6 +388,11 @@
pw.print(" restartTime=");
TimeUtils.formatDuration(restartTime, now, pw);
pw.print(" createdFromFg="); pw.println(createdFromFg);
+ if (pendingConnectionGroup != 0) {
+ pw.print(prefix); pw.print(" pendingConnectionGroup=");
+ pw.print(pendingConnectionGroup);
+ pw.print(" Importance="); pw.println(pendingConnectionImportance);
+ }
if (startRequested || delayedStop || lastStartId != 0) {
pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
pw.print(" delayedStop="); pw.print(delayedStop);
@@ -461,7 +468,11 @@
serviceInfo = sInfo;
appInfo = sInfo.applicationInfo;
packageName = sInfo.applicationInfo.packageName;
- processName = sInfo.processName;
+ if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) {
+ processName = sInfo.processName + ":" + instanceName.getClassName();
+ } else {
+ processName = sInfo.processName;
+ }
permission = sInfo.permission;
exported = sInfo.exported;
this.restarter = restarter;
@@ -507,6 +518,12 @@
public void setProcess(ProcessRecord _proc) {
app = _proc;
+ if (pendingConnectionGroup > 0) {
+ app.connectionService = this;
+ app.connectionGroup = pendingConnectionGroup;
+ app.connectionImportance = pendingConnectionImportance;
+ pendingConnectionGroup = pendingConnectionImportance = 0;
+ }
if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS) {
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> cr = connections.valueAt(conni);