diff options
12 files changed, 333 insertions, 143 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 28ecb27b53d2..45caf8336b71 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1729,8 +1729,11 @@ class ContextImpl extends Context { 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 3f1075448c84..e057b8634f5b 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -1639,6 +1639,19 @@ public final class LoadedApk { } } + @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 ff57b0311d60..9ff9044b2dfe 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3003,6 +3003,11 @@ public abstract class Context { * 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 7c3b5e48cb5b..546347a035b4 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1303,7 +1303,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** {@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 cdb781438909..ff7b34773268 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -433,18 +433,18 @@ public class PackageItemInfo { /** * @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 ab50ad147107..60561bd9dbc5 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -185,6 +185,7 @@ message ProcessRecordProto { 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 8cd9d1881639..15de3def913a 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 @@ class ActiveInstrumentation { 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 a19e9287aa6c..23287cf399ca 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { 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 0e354d515eef..4cc008bbc184 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9183,6 +9183,19 @@ public class ActivityManagerService extends IActivityManager.Stub } 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) { @@ -9248,19 +9261,6 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 */); - } } /** @@ -10240,7 +10240,8 @@ public class ActivityManagerService extends IActivityManager.Stub 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++; } @@ -10252,7 +10253,9 @@ public class ActivityManagerService extends IActivityManager.Stub 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 7991783e08c8..7c9fc561e9a3 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 @@ public final class ProcessList { } 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 { @@ -2241,6 +2245,191 @@ public final class ProcessList { 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() @@ -2353,91 +2542,31 @@ public final class ProcessList { 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); - // 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; - } - } - } + "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--; } - // 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; - } - } + 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. + int endIndex = pos - 1; + if (endIndex < mLruProcessActivityStart) { + endIndex = mLruProcessActivityStart; } + 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); @@ -2473,6 +2602,9 @@ public final class ProcessList { 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 013de93c7f24..4826f486da89 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 @@ final class ProcessRecord implements WindowProcessListener { } 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 @@ final class ProcessRecord implements WindowProcessListener { 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 @@ final class ProcessRecord implements WindowProcessListener { @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 @@ final class ProcessRecord implements WindowProcessListener { 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 @@ final class ProcessRecord implements WindowProcessListener { 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 09f8c3eee3b6..da5ce1c45610 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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN 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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN 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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN 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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN 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); |