am fbf4888d: am 9882d388: Merge "Fix issue #11223338: Not retaining service started state while restarting" into klp-dev

* commit 'fbf4888d19b0c68d8004f9ad2423a583dc01178e':
  Fix issue #11223338: Not retaining service started state while restarting
This commit is contained in:
Dianne Hackborn
2013-11-07 10:21:34 -08:00
committed by Android Git Automerger
7 changed files with 237 additions and 126 deletions

View File

@ -2272,9 +2272,12 @@ public class ActivityManager {
public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) { public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
FileOutputStream fout = new FileOutputStream(fd); FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout); PrintWriter pw = new FastPrintWriter(fout);
dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName }); dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] {
"-a", "package", packageName });
pw.println(); pw.println();
dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { packageName }); dumpService(pw, fd, "meminfo", new String[] { "--local", packageName });
pw.println();
dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { "-a", packageName });
pw.println(); pw.println();
dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName }); dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName });
pw.println(); pw.println();
@ -2296,7 +2299,7 @@ public class ActivityManager {
pw.flush(); pw.flush();
tp = new TransferPipe(); tp = new TransferPipe();
tp.setBufferPrefix(" "); tp.setBufferPrefix(" ");
service.dump(tp.getWriteFd().getFileDescriptor(), args); service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args);
tp.go(fd); tp.go(fd);
} catch (Throwable e) { } catch (Throwable e) {
if (tp != null) { if (tp != null) {

View File

@ -1758,21 +1758,34 @@ public final class ProcessStats implements Parcelable {
mStartTime, now); mStartTime, now);
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap(); ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
boolean printedHeader = false; boolean printedHeader = false;
boolean sepNeeded = false;
for (int ip=0; ip<pkgMap.size(); ip++) { for (int ip=0; ip<pkgMap.size(); ip++) {
String pkgName = pkgMap.keyAt(ip); final String pkgName = pkgMap.keyAt(ip);
if (reqPackage != null && !reqPackage.equals(pkgName)) { final SparseArray<PackageState> uids = pkgMap.valueAt(ip);
continue;
}
SparseArray<PackageState> uids = pkgMap.valueAt(ip);
for (int iu=0; iu<uids.size(); iu++) { for (int iu=0; iu<uids.size(); iu++) {
int uid = uids.keyAt(iu); final int uid = uids.keyAt(iu);
PackageState pkgState = uids.valueAt(iu); final PackageState pkgState = uids.valueAt(iu);
final int NPROCS = pkgState.mProcesses.size(); final int NPROCS = pkgState.mProcesses.size();
final int NSRVS = pkgState.mServices.size(); final int NSRVS = pkgState.mServices.size();
final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
if (!pkgMatch) {
boolean procMatch = false;
for (int iproc=0; iproc<NPROCS; iproc++) {
ProcessState proc = pkgState.mProcesses.valueAt(iproc);
if (reqPackage.equals(proc.mName)) {
procMatch = true;
break;
}
}
if (!procMatch) {
continue;
}
}
if (NPROCS > 0 || NSRVS > 0) { if (NPROCS > 0 || NSRVS > 0) {
if (!printedHeader) { if (!printedHeader) {
pw.println("Per-Package Stats:"); pw.println("Per-Package Stats:");
printedHeader = true; printedHeader = true;
sepNeeded = true;
} }
pw.print(" * "); pw.print(pkgName); pw.print(" / "); pw.print(" * "); pw.print(pkgName); pw.print(" / ");
UserHandle.formatUid(pw, uid); pw.println(":"); UserHandle.formatUid(pw, uid); pw.println(":");
@ -1780,6 +1793,9 @@ public final class ProcessStats implements Parcelable {
if (!dumpSummary || dumpAll) { if (!dumpSummary || dumpAll) {
for (int iproc=0; iproc<NPROCS; iproc++) { for (int iproc=0; iproc<NPROCS; iproc++) {
ProcessState proc = pkgState.mProcesses.valueAt(iproc); ProcessState proc = pkgState.mProcesses.valueAt(iproc);
if (!pkgMatch && !reqPackage.equals(proc.mName)) {
continue;
}
if (activeOnly && !proc.isInUse()) { if (activeOnly && !proc.isInUse()) {
pw.print(" (Not active: "); pw.print(" (Not active: ");
pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
@ -1787,7 +1803,11 @@ public final class ProcessStats implements Parcelable {
} }
pw.print(" Process "); pw.print(" Process ");
pw.print(pkgState.mProcesses.keyAt(iproc)); pw.print(pkgState.mProcesses.keyAt(iproc));
pw.print(" ("); if (proc.mCommonProcess.mMultiPackage) {
pw.print(" (multi, ");
} else {
pw.print(" (unique, ");
}
pw.print(proc.mDurationsTableSize); pw.print(proc.mDurationsTableSize);
pw.print(" entries)"); pw.print(" entries)");
pw.println(":"); pw.println(":");
@ -1801,6 +1821,9 @@ public final class ProcessStats implements Parcelable {
ArrayList<ProcessState> procs = new ArrayList<ProcessState>(); ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
for (int iproc=0; iproc<NPROCS; iproc++) { for (int iproc=0; iproc<NPROCS; iproc++) {
ProcessState proc = pkgState.mProcesses.valueAt(iproc); ProcessState proc = pkgState.mProcesses.valueAt(iproc);
if (!pkgMatch && !reqPackage.equals(proc.mName)) {
continue;
}
if (activeOnly && !proc.isInUse()) { if (activeOnly && !proc.isInUse()) {
continue; continue;
} }
@ -1811,6 +1834,9 @@ public final class ProcessStats implements Parcelable {
} }
for (int isvc=0; isvc<NSRVS; isvc++) { for (int isvc=0; isvc<NSRVS; isvc++) {
ServiceState svc = pkgState.mServices.valueAt(isvc); ServiceState svc = pkgState.mServices.valueAt(isvc);
if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
continue;
}
if (activeOnly && !svc.isInUse()) { if (activeOnly && !svc.isInUse()) {
pw.print(" (Not active: "); pw.print(" (Not active: ");
pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")"); pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
@ -1840,12 +1866,15 @@ public final class ProcessStats implements Parcelable {
if (svc.mOwner != null) { if (svc.mOwner != null) {
pw.print(" mOwner="); pw.println(svc.mOwner); pw.print(" mOwner="); pw.println(svc.mOwner);
} }
if (svc.mStarted || svc.mRestarting) {
pw.print(" mStarted="); pw.print(svc.mStarted);
pw.print(" mRestarting="); pw.println(svc.mRestarting);
}
} }
} }
} }
} }
if (reqPackage == null) {
ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
printedHeader = false; printedHeader = false;
int numShownProcs = 0, numTotalProcs = 0; int numShownProcs = 0, numTotalProcs = 0;
@ -1860,10 +1889,20 @@ public final class ProcessStats implements Parcelable {
&& proc.mPssTableSize == 0) { && proc.mPssTableSize == 0) {
continue; continue;
} }
if (!proc.mMultiPackage) {
continue;
}
if (reqPackage != null && !reqPackage.equals(procName)
&& !reqPackage.equals(proc.mPackage)) {
continue;
}
numShownProcs++; numShownProcs++;
if (!printedHeader) { if (sepNeeded) {
pw.println(); pw.println();
pw.println("Per-Process Stats:"); }
sepNeeded = true;
if (!printedHeader) {
pw.println("Multi-Package Common Processes:");
printedHeader = true; printedHeader = true;
} }
if (activeOnly && !proc.isInUse()) { if (activeOnly && !proc.isInUse()) {
@ -1878,28 +1917,24 @@ public final class ProcessStats implements Parcelable {
ALL_PROC_STATES, now); ALL_PROC_STATES, now);
dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
ALL_PROC_STATES); ALL_PROC_STATES);
if (dumpAll) {
dumpProcessInternalLocked(pw, " ", proc, dumpAll); dumpProcessInternalLocked(pw, " ", proc, dumpAll);
} }
} }
}
if (dumpAll) { if (dumpAll) {
pw.println(); pw.println();
pw.print(" Total procs: "); pw.print(numShownProcs); pw.print(" Total procs: "); pw.print(numShownProcs);
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
} }
if (sepNeeded) {
pw.println(); pw.println();
}
if (dumpSummary) { if (dumpSummary) {
pw.println("Summary:"); pw.println("Summary:");
dumpSummaryLocked(pw, reqPackage, now, activeOnly); dumpSummaryLocked(pw, reqPackage, now, activeOnly);
} else { } else {
dumpTotalsLocked(pw, now); dumpTotalsLocked(pw, now);
} }
} else {
pw.println();
dumpTotalsLocked(pw, now);
}
if (dumpAll) { if (dumpAll) {
pw.println(); pw.println();
@ -2031,17 +2066,20 @@ public final class ProcessStats implements Parcelable {
public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates, public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
int[] procStates, int sortProcStates[], long now, String reqPackage, int[] procStates, int sortProcStates[], long now, String reqPackage,
boolean activeOnly) { boolean activeOnly) {
ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap(); final ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
for (int ip=0; ip<pkgMap.size(); ip++) { for (int ip=0; ip<pkgMap.size(); ip++) {
if (reqPackage != null && !reqPackage.equals(pkgMap.keyAt(ip))) { final String pkgName = pkgMap.keyAt(ip);
final SparseArray<PackageState> procs = pkgMap.valueAt(ip);
for (int iu=0; iu<procs.size(); iu++) {
final PackageState state = procs.valueAt(iu);
final int NPROCS = state.mProcesses.size();
final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
for (int iproc=0; iproc<NPROCS; iproc++) {
final ProcessState proc = state.mProcesses.valueAt(iproc);
if (!pkgMatch && !reqPackage.equals(proc.mName)) {
continue; continue;
} }
SparseArray<PackageState> procs = pkgMap.valueAt(ip);
for (int iu=0; iu<procs.size(); iu++) {
PackageState state = procs.valueAt(iu);
for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
ProcessState proc = state.mProcesses.valueAt(iproc);
if (activeOnly && !proc.isInUse()) { if (activeOnly && !proc.isInUse()) {
continue; continue;
} }
@ -2601,23 +2639,35 @@ public final class ProcessStats implements Parcelable {
} }
} }
void incStartedServices(int memFactor, long now) { void incStartedServices(int memFactor, long now, String serviceName) {
if (false) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
+ " to " + (mNumStartedServices+1), here);
}
if (mCommonProcess != this) { if (mCommonProcess != this) {
mCommonProcess.incStartedServices(memFactor, now); mCommonProcess.incStartedServices(memFactor, now, serviceName);
} }
mNumStartedServices++; mNumStartedServices++;
if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) { if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
setState(STATE_NOTHING, memFactor, now, null); setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
} }
} }
void decStartedServices(int memFactor, long now) { void decStartedServices(int memFactor, long now, String serviceName) {
if (false) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+ " to " + (mNumStartedServices-1), here);
}
if (mCommonProcess != this) { if (mCommonProcess != this) {
mCommonProcess.decStartedServices(memFactor, now); mCommonProcess.decStartedServices(memFactor, now, serviceName);
} }
mNumStartedServices--; mNumStartedServices--;
if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) { if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
setState(STATE_NOTHING, memFactor, now, null); setState(STATE_NOTHING, now);
} else if (mNumStartedServices < 0) { } else if (mNumStartedServices < 0) {
Slog.wtfStack(TAG, "Proc started services underrun: pkg=" Slog.wtfStack(TAG, "Proc started services underrun: pkg="
+ mPackage + " uid=" + mUid + " name=" + mName); + mPackage + " uid=" + mUid + " name=" + mName);
@ -2873,6 +2923,8 @@ public final class ProcessStats implements Parcelable {
public int mRunState = STATE_NOTHING; public int mRunState = STATE_NOTHING;
long mRunStartTime; long mRunStartTime;
boolean mStarted;
boolean mRestarting;
int mStartedCount; int mStartedCount;
public int mStartedState = STATE_NOTHING; public int mStartedState = STATE_NOTHING;
long mStartedStartTime; long mStartedStartTime;
@ -2902,10 +2954,9 @@ public final class ProcessStats implements Parcelable {
// There was already an old owner, reset this object for its // There was already an old owner, reset this object for its
// new owner. // new owner.
mOwner = newOwner; mOwner = newOwner;
if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
|| mExecState != STATE_NOTHING) {
long now = SystemClock.uptimeMillis(); long now = SystemClock.uptimeMillis();
if (mStartedState != STATE_NOTHING) { if (mStarted) {
if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+ " from " + mOwner + " while started: pkg=" + " from " + mOwner + " while started: pkg="
+ mPackage + " service=" + mName + " proc=" + mProc); + mPackage + " service=" + mName + " proc=" + mProc);
@ -2931,10 +2982,9 @@ public final class ProcessStats implements Parcelable {
public void clearCurrentOwner(Object owner, boolean silently) { public void clearCurrentOwner(Object owner, boolean silently) {
if (mOwner == owner) { if (mOwner == owner) {
mProc.decActiveServices(mName); mProc.decActiveServices(mName);
if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
|| mExecState != STATE_NOTHING) {
long now = SystemClock.uptimeMillis(); long now = SystemClock.uptimeMillis();
if (mStartedState != STATE_NOTHING) { if (mStarted) {
if (!silently) { if (!silently) {
Slog.wtfStack(TAG, "Service owner " + owner Slog.wtfStack(TAG, "Service owner " + owner
+ " cleared while started: pkg=" + mPackage + " service=" + " cleared while started: pkg=" + mPackage + " service="
@ -3042,7 +3092,18 @@ public final class ProcessStats implements Parcelable {
if (mOwner == null) { if (mOwner == null) {
Slog.wtf(TAG, "Starting service " + this + " without owner"); Slog.wtf(TAG, "Starting service " + this + " without owner");
} }
mStarted = started;
updateStartedState(memFactor, now);
}
public void setRestarting(boolean restarting, int memFactor, long now) {
mRestarting = restarting;
updateStartedState(memFactor, now);
}
void updateStartedState(int memFactor, long now) {
final boolean wasStarted = mStartedState != STATE_NOTHING; final boolean wasStarted = mStartedState != STATE_NOTHING;
final boolean started = mStarted || mRestarting;
final int state = started ? memFactor : STATE_NOTHING; final int state = started ? memFactor : STATE_NOTHING;
if (mStartedState != state) { if (mStartedState != state) {
if (mStartedState != STATE_NOTHING) { if (mStartedState != STATE_NOTHING) {
@ -3056,9 +3117,9 @@ public final class ProcessStats implements Parcelable {
mProc = mProc.pullFixedProc(mPackage); mProc = mProc.pullFixedProc(mPackage);
if (wasStarted != started) { if (wasStarted != started) {
if (started) { if (started) {
mProc.incStartedServices(memFactor, now); mProc.incStartedServices(memFactor, now, mName);
} else { } else {
mProc.decStartedServices(memFactor, now); mProc.decStartedServices(memFactor, now, mName);
} }
} }
updateRunning(memFactor, now); updateRunning(memFactor, now);

View File

@ -1187,6 +1187,7 @@ public final class ActiveServices {
if (!mRestartingServices.contains(r)) { if (!mRestartingServices.contains(r)) {
r.createdFromFg = false; r.createdFromFg = false;
mRestartingServices.add(r); mRestartingServices.add(r);
r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
} }
r.cancelNotification(); r.cancelNotification();
@ -1220,6 +1221,9 @@ public final class ActiveServices {
if (removed || callingUid != r.appInfo.uid) { if (removed || callingUid != r.appInfo.uid) {
r.resetRestartCounter(); r.resetRestartCounter();
} }
if (removed) {
r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
}
mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.removeCallbacks(r.restarter);
return true; return true;
} }
@ -1243,7 +1247,9 @@ public final class ActiveServices {
// We are now bringing the service up, so no longer in the // We are now bringing the service up, so no longer in the
// restarting state. // restarting state.
mRestartingServices.remove(r); if (mRestartingServices.remove(r)) {
r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
}
// Make sure this service is no longer considered delayed, we are starting it now. // Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) { if (r.delayed) {
@ -1581,6 +1587,7 @@ public final class ActiveServices {
} }
r.app.services.remove(r); r.app.services.remove(r);
if (r.app.thread != null) { if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
try { try {
bumpServiceExecutingLocked(r, false, "destroy"); bumpServiceExecutingLocked(r, false, "destroy");
mDestroyingServices.add(r); mDestroyingServices.add(r);
@ -1591,7 +1598,6 @@ public final class ActiveServices {
+ r.shortName, e); + r.shortName, e);
serviceProcessGoneLocked(r); serviceProcessGoneLocked(r);
} }
updateServiceForegroundLocked(r.app, false);
} else { } else {
if (DEBUG_SERVICE) Slog.v( if (DEBUG_SERVICE) Slog.v(
TAG, "Removed service that has no process: " + r); TAG, "Removed service that has no process: " + r);
@ -1816,6 +1822,9 @@ public final class ActiveServices {
r.tracker = null; r.tracker = null;
} }
} }
if (finishing) {
r.app = null;
}
} }
} }
@ -1960,8 +1969,7 @@ public final class ActiveServices {
} }
} }
final void killServicesLocked(ProcessRecord app, final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
boolean allowRestart) {
// Report disconnected services. // Report disconnected services.
if (false) { if (false) {
// XXX we are letting the client link to the service for // XXX we are letting the client link to the service for
@ -1990,16 +1998,8 @@ public final class ActiveServices {
} }
} }
// Clean up any connections this application has to other services. // First clear app state from services.
for (int i=app.connections.size()-1; i>=0; i--) {
ConnectionRecord r = app.connections.valueAt(i);
removeConnectionLocked(r, app, null);
}
app.connections.clear();
for (int i=app.services.size()-1; i>=0; i--) { for (int i=app.services.size()-1; i>=0; i--) {
// Any services running in the application need to be placed
// back in the pending list.
ServiceRecord sr = app.services.valueAt(i); ServiceRecord sr = app.services.valueAt(i);
synchronized (sr.stats.getBatteryStats()) { synchronized (sr.stats.getBatteryStats()) {
sr.stats.stopLaunchedLocked(); sr.stats.stopLaunchedLocked();
@ -2020,8 +2020,21 @@ public final class ActiveServices {
b.binder = null; b.binder = null;
b.requested = b.received = b.hasBound = false; b.requested = b.received = b.hasBound = false;
} }
}
if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags // Clean up any connections this application has to other services.
for (int i=app.connections.size()-1; i>=0; i--) {
ConnectionRecord r = app.connections.valueAt(i);
removeConnectionLocked(r, app, null);
}
app.connections.clear();
// Now do remaining service cleanup.
for (int i=app.services.size()-1; i>=0; i--) {
// Any services running in the application may need to be placed
// back in the pending list.
ServiceRecord sr = app.services.valueAt(i);
if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
&ApplicationInfo.FLAG_PERSISTENT) == 0) { &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Slog.w(TAG, "Service crashed " + sr.crashCount Slog.w(TAG, "Service crashed " + sr.crashCount
+ " times, stopping: " + sr); + " times, stopping: " + sr);
@ -2054,6 +2067,17 @@ public final class ActiveServices {
if (!allowRestart) { if (!allowRestart) {
app.services.clear(); app.services.clear();
// Make sure there are no more restarting services for this process.
for (int i=mRestartingServices.size()-1; i>=0; i--) {
ServiceRecord r = mRestartingServices.get(i);
if (r.processName.equals(app.processName) &&
r.serviceInfo.applicationInfo.uid == app.info.uid) {
mRestartingServices.remove(i);
r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
} }
// Make sure we have no more records on the stopping list. // Make sure we have no more records on the stopping list.

View File

@ -11901,6 +11901,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean dumpDalvik = false; boolean dumpDalvik = false;
boolean oomOnly = false; boolean oomOnly = false;
boolean isCompact = false; boolean isCompact = false;
boolean localOnly = false;
int opti = 0; int opti = 0;
while (opti < args.length) { while (opti < args.length) {
@ -11919,12 +11920,15 @@ public final class ActivityManagerService extends ActivityManagerNative
isCompact = true; isCompact = true;
} else if ("--oom".equals(opt)) { } else if ("--oom".equals(opt)) {
oomOnly = true; oomOnly = true;
} else if ("--local".equals(opt)) {
localOnly = true;
} else if ("-h".equals(opt)) { } else if ("-h".equals(opt)) {
pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]"); pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]");
pw.println(" -a: include all available information for each process."); pw.println(" -a: include all available information for each process.");
pw.println(" -d: include dalvik details when dumping process details."); pw.println(" -d: include dalvik details when dumping process details.");
pw.println(" -c: dump in a compact machine-parseable representation."); pw.println(" -c: dump in a compact machine-parseable representation.");
pw.println(" --oom: only show processes organized by oom adj."); pw.println(" --oom: only show processes organized by oom adj.");
pw.println(" --local: only collect details locally, don't call process.");
pw.println("If [process] is specified it can be the name or "); pw.println("If [process] is specified it can be the name or ");
pw.println("pid of a specific process to dump."); pw.println("pid of a specific process to dump.");
return; return;
@ -12041,6 +12045,13 @@ public final class ActivityManagerService extends ActivityManagerNative
mi.dalvikPrivateDirty = (int)tmpLong[0]; mi.dalvikPrivateDirty = (int)tmpLong[0];
} }
if (dumpDetails) { if (dumpDetails) {
if (localOnly) {
ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0);
if (isCheckinRequest) {
pw.println();
}
} else {
try { try {
pw.flush(); pw.flush();
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails, thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
@ -12052,6 +12063,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} }
} }
} }
}
final long myTotalPss = mi.getTotalPss(); final long myTotalPss = mi.getTotalPss();
final long myTotalUss = mi.getTotalUss(); final long myTotalUss = mi.getTotalUss();

View File

@ -750,9 +750,6 @@ public final class ProcessStatsService extends IProcessStats.Stub {
return; return;
} else { } else {
// Not an option, last argument must be a package name. // Not an option, last argument must be a package name.
try {
IPackageManager pm = AppGlobals.getPackageManager();
if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) {
reqPackage = arg; reqPackage = arg;
// Include all details, since we know we are only going to // Include all details, since we know we are only going to
// be dumping a smaller set of data. In fact only the details // be dumping a smaller set of data. In fact only the details
@ -760,14 +757,6 @@ public final class ProcessStatsService extends IProcessStats.Stub {
// to dump anything at all when filtering by package. // to dump anything at all when filtering by package.
dumpDetails = true; dumpDetails = true;
} }
} catch (RemoteException e) {
}
if (reqPackage == null) {
pw.println("Unknown package: " + arg);
dumpHelp(pw);
return;
}
}
} }
} }
@ -816,13 +805,14 @@ public final class ProcessStatsService extends IProcessStats.Stub {
} }
return; return;
} else if (aggregateHours != 0) { } else if (aggregateHours != 0) {
pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact, dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
dumpDetails, dumpFullDetails, dumpAll, activeOnly); dumpDetails, dumpFullDetails, dumpAll, activeOnly);
return; return;
} }
boolean sepNeeded = false; boolean sepNeeded = false;
if (!currentOnly || isCheckin) { if (dumpAll || isCheckin) {
mWriteLock.lock(); mWriteLock.lock();
try { try {
ArrayList<String> files = getCommittedFiles(0, false, !isCheckin); ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
@ -882,11 +872,11 @@ public final class ProcessStatsService extends IProcessStats.Stub {
} }
} }
if (!isCheckin) { if (!isCheckin) {
if (dumpAll) { if (!currentOnly) {
if (sepNeeded) { if (sepNeeded) {
pw.println(); pw.println();
pw.println("AGGREGATED OVER LAST 24 HOURS:");
} }
pw.println("AGGREGATED OVER LAST 24 HOURS:");
dumpAggregatedStats(pw, 24, now, reqPackage, isCompact, dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
dumpDetails, dumpFullDetails, dumpAll, activeOnly); dumpDetails, dumpFullDetails, dumpAll, activeOnly);
pw.println(); pw.println();
@ -901,8 +891,8 @@ public final class ProcessStatsService extends IProcessStats.Stub {
} else { } else {
if (sepNeeded) { if (sepNeeded) {
pw.println(); pw.println();
pw.println("CURRENT STATS:");
} }
pw.println("CURRENT STATS:");
if (dumpDetails || dumpFullDetails) { if (dumpDetails || dumpFullDetails) {
mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
activeOnly); activeOnly);

View File

@ -85,6 +85,7 @@ final class ServiceRecord extends Binder {
ProcessRecord app; // where this service is running or null. ProcessRecord app; // where this service is running or null.
ProcessRecord isolatedProc; // keep track of isolated process, if requested ProcessRecord isolatedProc; // keep track of isolated process, if requested
ProcessStats.ServiceState tracker; // tracking service execution, may be null ProcessStats.ServiceState tracker; // tracking service execution, may be null
ProcessStats.ServiceState restartTracker; // tracking service restart
boolean delayed; // are we waiting to start this service in the background? boolean delayed; // are we waiting to start this service in the background?
boolean isForeground; // is service currently in foreground mode? boolean isForeground; // is service currently in foreground mode?
int foregroundId; // Notification ID of last foreground req. int foregroundId; // Notification ID of last foreground req.
@ -340,6 +341,26 @@ final class ServiceRecord extends Binder {
} }
} }
public void makeRestarting(int memFactor, long now) {
if (restartTracker == null) {
if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name);
}
if (restartTracker == null) {
return;
}
}
restartTracker.setRestarting(true, memFactor, now);
}
public void clearRestarting(int memFactor, long now) {
if (restartTracker != null) {
restartTracker.setRestarting(false, memFactor, now);
restartTracker = null;
}
}
public AppBindRecord retrieveAppBindingLocked(Intent intent, public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) { ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent); Intent.FilterComparison filter = new Intent.FilterComparison(intent);