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:
@ -2272,9 +2272,12 @@ public class ActivityManager {
|
||||
public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
|
||||
FileOutputStream fout = new FileOutputStream(fd);
|
||||
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();
|
||||
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();
|
||||
dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName });
|
||||
pw.println();
|
||||
@ -2296,7 +2299,7 @@ public class ActivityManager {
|
||||
pw.flush();
|
||||
tp = new TransferPipe();
|
||||
tp.setBufferPrefix(" ");
|
||||
service.dump(tp.getWriteFd().getFileDescriptor(), args);
|
||||
service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args);
|
||||
tp.go(fd);
|
||||
} catch (Throwable e) {
|
||||
if (tp != null) {
|
||||
|
@ -1758,21 +1758,34 @@ public final class ProcessStats implements Parcelable {
|
||||
mStartTime, now);
|
||||
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
|
||||
boolean printedHeader = false;
|
||||
boolean sepNeeded = false;
|
||||
for (int ip=0; ip<pkgMap.size(); ip++) {
|
||||
String pkgName = pkgMap.keyAt(ip);
|
||||
if (reqPackage != null && !reqPackage.equals(pkgName)) {
|
||||
continue;
|
||||
}
|
||||
SparseArray<PackageState> uids = pkgMap.valueAt(ip);
|
||||
final String pkgName = pkgMap.keyAt(ip);
|
||||
final SparseArray<PackageState> uids = pkgMap.valueAt(ip);
|
||||
for (int iu=0; iu<uids.size(); iu++) {
|
||||
int uid = uids.keyAt(iu);
|
||||
PackageState pkgState = uids.valueAt(iu);
|
||||
final int uid = uids.keyAt(iu);
|
||||
final PackageState pkgState = uids.valueAt(iu);
|
||||
final int NPROCS = pkgState.mProcesses.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 (!printedHeader) {
|
||||
pw.println("Per-Package Stats:");
|
||||
printedHeader = true;
|
||||
sepNeeded = true;
|
||||
}
|
||||
pw.print(" * "); pw.print(pkgName); pw.print(" / ");
|
||||
UserHandle.formatUid(pw, uid); pw.println(":");
|
||||
@ -1780,6 +1793,9 @@ public final class ProcessStats implements Parcelable {
|
||||
if (!dumpSummary || dumpAll) {
|
||||
for (int iproc=0; iproc<NPROCS; iproc++) {
|
||||
ProcessState proc = pkgState.mProcesses.valueAt(iproc);
|
||||
if (!pkgMatch && !reqPackage.equals(proc.mName)) {
|
||||
continue;
|
||||
}
|
||||
if (activeOnly && !proc.isInUse()) {
|
||||
pw.print(" (Not active: ");
|
||||
pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
|
||||
@ -1787,7 +1803,11 @@ public final class ProcessStats implements Parcelable {
|
||||
}
|
||||
pw.print(" Process ");
|
||||
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(" entries)");
|
||||
pw.println(":");
|
||||
@ -1801,6 +1821,9 @@ public final class ProcessStats implements Parcelable {
|
||||
ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
|
||||
for (int iproc=0; iproc<NPROCS; iproc++) {
|
||||
ProcessState proc = pkgState.mProcesses.valueAt(iproc);
|
||||
if (!pkgMatch && !reqPackage.equals(proc.mName)) {
|
||||
continue;
|
||||
}
|
||||
if (activeOnly && !proc.isInUse()) {
|
||||
continue;
|
||||
}
|
||||
@ -1811,6 +1834,9 @@ public final class ProcessStats implements Parcelable {
|
||||
}
|
||||
for (int isvc=0; isvc<NSRVS; isvc++) {
|
||||
ServiceState svc = pkgState.mServices.valueAt(isvc);
|
||||
if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
|
||||
continue;
|
||||
}
|
||||
if (activeOnly && !svc.isInUse()) {
|
||||
pw.print(" (Not active: ");
|
||||
pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
|
||||
@ -1840,64 +1866,73 @@ public final class ProcessStats implements Parcelable {
|
||||
if (svc.mOwner != null) {
|
||||
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();
|
||||
printedHeader = false;
|
||||
int numShownProcs = 0, numTotalProcs = 0;
|
||||
for (int ip=0; ip<procMap.size(); ip++) {
|
||||
String procName = procMap.keyAt(ip);
|
||||
SparseArray<ProcessState> uids = procMap.valueAt(ip);
|
||||
for (int iu=0; iu<uids.size(); iu++) {
|
||||
int uid = uids.keyAt(iu);
|
||||
numTotalProcs++;
|
||||
ProcessState proc = uids.valueAt(iu);
|
||||
if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
|
||||
&& proc.mPssTableSize == 0) {
|
||||
continue;
|
||||
}
|
||||
numShownProcs++;
|
||||
if (!printedHeader) {
|
||||
pw.println();
|
||||
pw.println("Per-Process Stats:");
|
||||
printedHeader = true;
|
||||
}
|
||||
if (activeOnly && !proc.isInUse()) {
|
||||
pw.print(" (Not active: "); pw.print(procName); pw.println(")");
|
||||
continue;
|
||||
}
|
||||
pw.print(" * "); pw.print(procName); pw.print(" / ");
|
||||
UserHandle.formatUid(pw, uid);
|
||||
pw.print(" ("); pw.print(proc.mDurationsTableSize);
|
||||
pw.print(" entries)"); pw.println(":");
|
||||
dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
|
||||
ALL_PROC_STATES, now);
|
||||
dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
|
||||
ALL_PROC_STATES);
|
||||
if (dumpAll) {
|
||||
dumpProcessInternalLocked(pw, " ", proc, dumpAll);
|
||||
}
|
||||
ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
|
||||
printedHeader = false;
|
||||
int numShownProcs = 0, numTotalProcs = 0;
|
||||
for (int ip=0; ip<procMap.size(); ip++) {
|
||||
String procName = procMap.keyAt(ip);
|
||||
SparseArray<ProcessState> uids = procMap.valueAt(ip);
|
||||
for (int iu=0; iu<uids.size(); iu++) {
|
||||
int uid = uids.keyAt(iu);
|
||||
numTotalProcs++;
|
||||
ProcessState proc = uids.valueAt(iu);
|
||||
if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
|
||||
&& proc.mPssTableSize == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!proc.mMultiPackage) {
|
||||
continue;
|
||||
}
|
||||
if (reqPackage != null && !reqPackage.equals(procName)
|
||||
&& !reqPackage.equals(proc.mPackage)) {
|
||||
continue;
|
||||
}
|
||||
numShownProcs++;
|
||||
if (sepNeeded) {
|
||||
pw.println();
|
||||
}
|
||||
sepNeeded = true;
|
||||
if (!printedHeader) {
|
||||
pw.println("Multi-Package Common Processes:");
|
||||
printedHeader = true;
|
||||
}
|
||||
if (activeOnly && !proc.isInUse()) {
|
||||
pw.print(" (Not active: "); pw.print(procName); pw.println(")");
|
||||
continue;
|
||||
}
|
||||
pw.print(" * "); pw.print(procName); pw.print(" / ");
|
||||
UserHandle.formatUid(pw, uid);
|
||||
pw.print(" ("); pw.print(proc.mDurationsTableSize);
|
||||
pw.print(" entries)"); pw.println(":");
|
||||
dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
|
||||
ALL_PROC_STATES, now);
|
||||
dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
|
||||
ALL_PROC_STATES);
|
||||
dumpProcessInternalLocked(pw, " ", proc, dumpAll);
|
||||
}
|
||||
if (dumpAll) {
|
||||
pw.println();
|
||||
pw.print(" Total procs: "); pw.print(numShownProcs);
|
||||
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
|
||||
}
|
||||
}
|
||||
if (dumpAll) {
|
||||
pw.println();
|
||||
pw.print(" Total procs: "); pw.print(numShownProcs);
|
||||
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
|
||||
}
|
||||
|
||||
if (sepNeeded) {
|
||||
pw.println();
|
||||
if (dumpSummary) {
|
||||
pw.println("Summary:");
|
||||
dumpSummaryLocked(pw, reqPackage, now, activeOnly);
|
||||
} else {
|
||||
dumpTotalsLocked(pw, now);
|
||||
}
|
||||
}
|
||||
if (dumpSummary) {
|
||||
pw.println("Summary:");
|
||||
dumpSummaryLocked(pw, reqPackage, now, activeOnly);
|
||||
} else {
|
||||
pw.println();
|
||||
dumpTotalsLocked(pw, now);
|
||||
}
|
||||
|
||||
@ -2031,17 +2066,20 @@ public final class ProcessStats implements Parcelable {
|
||||
public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
|
||||
int[] procStates, int sortProcStates[], long now, String reqPackage,
|
||||
boolean activeOnly) {
|
||||
ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
|
||||
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
|
||||
final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
|
||||
final ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
|
||||
for (int ip=0; ip<pkgMap.size(); ip++) {
|
||||
if (reqPackage != null && !reqPackage.equals(pkgMap.keyAt(ip))) {
|
||||
continue;
|
||||
}
|
||||
SparseArray<PackageState> procs = pkgMap.valueAt(ip);
|
||||
final String pkgName = pkgMap.keyAt(ip);
|
||||
final 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);
|
||||
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;
|
||||
}
|
||||
if (activeOnly && !proc.isInUse()) {
|
||||
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) {
|
||||
mCommonProcess.incStartedServices(memFactor, now);
|
||||
mCommonProcess.incStartedServices(memFactor, now, serviceName);
|
||||
}
|
||||
mNumStartedServices++;
|
||||
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) {
|
||||
mCommonProcess.decStartedServices(memFactor, now);
|
||||
mCommonProcess.decStartedServices(memFactor, now, serviceName);
|
||||
}
|
||||
mNumStartedServices--;
|
||||
if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) {
|
||||
setState(STATE_NOTHING, memFactor, now, null);
|
||||
if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
|
||||
setState(STATE_NOTHING, now);
|
||||
} else if (mNumStartedServices < 0) {
|
||||
Slog.wtfStack(TAG, "Proc started services underrun: pkg="
|
||||
+ mPackage + " uid=" + mUid + " name=" + mName);
|
||||
@ -2873,6 +2923,8 @@ public final class ProcessStats implements Parcelable {
|
||||
public int mRunState = STATE_NOTHING;
|
||||
long mRunStartTime;
|
||||
|
||||
boolean mStarted;
|
||||
boolean mRestarting;
|
||||
int mStartedCount;
|
||||
public int mStartedState = STATE_NOTHING;
|
||||
long mStartedStartTime;
|
||||
@ -2902,10 +2954,9 @@ public final class ProcessStats implements Parcelable {
|
||||
// There was already an old owner, reset this object for its
|
||||
// new owner.
|
||||
mOwner = newOwner;
|
||||
if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
|
||||
|| mExecState != STATE_NOTHING) {
|
||||
if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
if (mStartedState != STATE_NOTHING) {
|
||||
if (mStarted) {
|
||||
if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
|
||||
+ " from " + mOwner + " while started: pkg="
|
||||
+ mPackage + " service=" + mName + " proc=" + mProc);
|
||||
@ -2931,10 +2982,9 @@ public final class ProcessStats implements Parcelable {
|
||||
public void clearCurrentOwner(Object owner, boolean silently) {
|
||||
if (mOwner == owner) {
|
||||
mProc.decActiveServices(mName);
|
||||
if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
|
||||
|| mExecState != STATE_NOTHING) {
|
||||
if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
if (mStartedState != STATE_NOTHING) {
|
||||
if (mStarted) {
|
||||
if (!silently) {
|
||||
Slog.wtfStack(TAG, "Service owner " + owner
|
||||
+ " cleared while started: pkg=" + mPackage + " service="
|
||||
@ -3042,7 +3092,18 @@ public final class ProcessStats implements Parcelable {
|
||||
if (mOwner == null) {
|
||||
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 started = mStarted || mRestarting;
|
||||
final int state = started ? memFactor : STATE_NOTHING;
|
||||
if (mStartedState != state) {
|
||||
if (mStartedState != STATE_NOTHING) {
|
||||
@ -3056,9 +3117,9 @@ public final class ProcessStats implements Parcelable {
|
||||
mProc = mProc.pullFixedProc(mPackage);
|
||||
if (wasStarted != started) {
|
||||
if (started) {
|
||||
mProc.incStartedServices(memFactor, now);
|
||||
mProc.incStartedServices(memFactor, now, mName);
|
||||
} else {
|
||||
mProc.decStartedServices(memFactor, now);
|
||||
mProc.decStartedServices(memFactor, now, mName);
|
||||
}
|
||||
}
|
||||
updateRunning(memFactor, now);
|
||||
|
@ -1187,6 +1187,7 @@ public final class ActiveServices {
|
||||
if (!mRestartingServices.contains(r)) {
|
||||
r.createdFromFg = false;
|
||||
mRestartingServices.add(r);
|
||||
r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
|
||||
}
|
||||
|
||||
r.cancelNotification();
|
||||
@ -1220,6 +1221,9 @@ public final class ActiveServices {
|
||||
if (removed || callingUid != r.appInfo.uid) {
|
||||
r.resetRestartCounter();
|
||||
}
|
||||
if (removed) {
|
||||
r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
|
||||
}
|
||||
mAm.mHandler.removeCallbacks(r.restarter);
|
||||
return true;
|
||||
}
|
||||
@ -1243,7 +1247,9 @@ public final class ActiveServices {
|
||||
|
||||
// We are now bringing the service up, so no longer in the
|
||||
// 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.
|
||||
if (r.delayed) {
|
||||
@ -1581,6 +1587,7 @@ public final class ActiveServices {
|
||||
}
|
||||
r.app.services.remove(r);
|
||||
if (r.app.thread != null) {
|
||||
updateServiceForegroundLocked(r.app, false);
|
||||
try {
|
||||
bumpServiceExecutingLocked(r, false, "destroy");
|
||||
mDestroyingServices.add(r);
|
||||
@ -1591,7 +1598,6 @@ public final class ActiveServices {
|
||||
+ r.shortName, e);
|
||||
serviceProcessGoneLocked(r);
|
||||
}
|
||||
updateServiceForegroundLocked(r.app, false);
|
||||
} else {
|
||||
if (DEBUG_SERVICE) Slog.v(
|
||||
TAG, "Removed service that has no process: " + r);
|
||||
@ -1816,6 +1822,9 @@ public final class ActiveServices {
|
||||
r.tracker = null;
|
||||
}
|
||||
}
|
||||
if (finishing) {
|
||||
r.app = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1960,8 +1969,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
final void killServicesLocked(ProcessRecord app,
|
||||
boolean allowRestart) {
|
||||
final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
|
||||
// Report disconnected services.
|
||||
if (false) {
|
||||
// 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.
|
||||
for (int i=app.connections.size()-1; i>=0; i--) {
|
||||
ConnectionRecord r = app.connections.valueAt(i);
|
||||
removeConnectionLocked(r, app, null);
|
||||
}
|
||||
app.connections.clear();
|
||||
|
||||
// First clear app state from services.
|
||||
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);
|
||||
synchronized (sr.stats.getBatteryStats()) {
|
||||
sr.stats.stopLaunchedLocked();
|
||||
@ -2020,8 +2020,21 @@ public final class ActiveServices {
|
||||
b.binder = null;
|
||||
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) {
|
||||
Slog.w(TAG, "Service crashed " + sr.crashCount
|
||||
+ " times, stopping: " + sr);
|
||||
@ -2054,6 +2067,17 @@ public final class ActiveServices {
|
||||
|
||||
if (!allowRestart) {
|
||||
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.
|
||||
|
@ -11901,6 +11901,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
boolean dumpDalvik = false;
|
||||
boolean oomOnly = false;
|
||||
boolean isCompact = false;
|
||||
boolean localOnly = false;
|
||||
|
||||
int opti = 0;
|
||||
while (opti < args.length) {
|
||||
@ -11919,12 +11920,15 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
isCompact = true;
|
||||
} else if ("--oom".equals(opt)) {
|
||||
oomOnly = true;
|
||||
} else if ("--local".equals(opt)) {
|
||||
localOnly = true;
|
||||
} else if ("-h".equals(opt)) {
|
||||
pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]");
|
||||
pw.println(" -a: include all available information for each process.");
|
||||
pw.println(" -d: include dalvik details when dumping process details.");
|
||||
pw.println(" -c: dump in a compact machine-parseable representation.");
|
||||
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("pid of a specific process to dump.");
|
||||
return;
|
||||
@ -12041,14 +12045,22 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
mi.dalvikPrivateDirty = (int)tmpLong[0];
|
||||
}
|
||||
if (dumpDetails) {
|
||||
try {
|
||||
pw.flush();
|
||||
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
|
||||
dumpDalvik, innerArgs);
|
||||
} catch (RemoteException e) {
|
||||
if (!isCheckinRequest) {
|
||||
pw.println("Got RemoteException!");
|
||||
if (localOnly) {
|
||||
ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
|
||||
dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0);
|
||||
if (isCheckinRequest) {
|
||||
pw.println();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
pw.flush();
|
||||
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
|
||||
dumpDalvik, innerArgs);
|
||||
} catch (RemoteException e) {
|
||||
if (!isCheckinRequest) {
|
||||
pw.println("Got RemoteException!");
|
||||
pw.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
final class ConnectionRecord {
|
||||
final AppBindRecord binding; // The application/service binding.
|
||||
final ActivityRecord activity; // If non-null, the owning activity.
|
||||
final ActivityRecord activity; // If non-null, the owning activity.
|
||||
final IServiceConnection conn; // The client connection.
|
||||
final int flags; // Binding options.
|
||||
final int clientLabel; // String resource labeling this client.
|
||||
|
@ -750,23 +750,12 @@ public final class ProcessStatsService extends IProcessStats.Stub {
|
||||
return;
|
||||
} else {
|
||||
// Not an option, last argument must be a package name.
|
||||
try {
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) {
|
||||
reqPackage = arg;
|
||||
// Include all details, since we know we are only going to
|
||||
// be dumping a smaller set of data. In fact only the details
|
||||
// container per-package data, so that are needed to be able
|
||||
// to dump anything at all when filtering by package.
|
||||
dumpDetails = true;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
if (reqPackage == null) {
|
||||
pw.println("Unknown package: " + arg);
|
||||
dumpHelp(pw);
|
||||
return;
|
||||
}
|
||||
reqPackage = arg;
|
||||
// Include all details, since we know we are only going to
|
||||
// be dumping a smaller set of data. In fact only the details
|
||||
// container per-package data, so that are needed to be able
|
||||
// to dump anything at all when filtering by package.
|
||||
dumpDetails = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -816,13 +805,14 @@ public final class ProcessStatsService extends IProcessStats.Stub {
|
||||
}
|
||||
return;
|
||||
} else if (aggregateHours != 0) {
|
||||
pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
|
||||
dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
|
||||
dumpDetails, dumpFullDetails, dumpAll, activeOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean sepNeeded = false;
|
||||
if (!currentOnly || isCheckin) {
|
||||
if (dumpAll || isCheckin) {
|
||||
mWriteLock.lock();
|
||||
try {
|
||||
ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
|
||||
@ -882,11 +872,11 @@ public final class ProcessStatsService extends IProcessStats.Stub {
|
||||
}
|
||||
}
|
||||
if (!isCheckin) {
|
||||
if (dumpAll) {
|
||||
if (!currentOnly) {
|
||||
if (sepNeeded) {
|
||||
pw.println();
|
||||
pw.println("AGGREGATED OVER LAST 24 HOURS:");
|
||||
}
|
||||
pw.println("AGGREGATED OVER LAST 24 HOURS:");
|
||||
dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
|
||||
dumpDetails, dumpFullDetails, dumpAll, activeOnly);
|
||||
pw.println();
|
||||
@ -901,8 +891,8 @@ public final class ProcessStatsService extends IProcessStats.Stub {
|
||||
} else {
|
||||
if (sepNeeded) {
|
||||
pw.println();
|
||||
pw.println("CURRENT STATS:");
|
||||
}
|
||||
pw.println("CURRENT STATS:");
|
||||
if (dumpDetails || dumpFullDetails) {
|
||||
mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
|
||||
activeOnly);
|
||||
|
@ -85,6 +85,7 @@ final class ServiceRecord extends Binder {
|
||||
ProcessRecord app; // where this service is running or null.
|
||||
ProcessRecord isolatedProc; // keep track of isolated process, if requested
|
||||
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 isForeground; // is service currently in foreground mode?
|
||||
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,
|
||||
ProcessRecord app) {
|
||||
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
|
||||
|
Reference in New Issue
Block a user