Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e40d1d3 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by The Android Automerger
Browse files

Fix issue #11223338: Not retaining service started state while restarting

When I cleaned up how we maintained the lifecycle of the tracker with a
service, I broke most tracking of the service restart state.  (Since at
that point the service is no longer associated with a process, so I
must clean up the tracker state).  This change introduces a new special
case for interacting with a service tracker to explicitly tell it when
a service is being restarted.  It also fixes how we update the process
state when services are attached to it, so it goes in and out of the
restarting state correctly.

In addition:

- Maybe fix issue #11224000 (APR: Dependent processes not getting added
  to LRU list).  We were not clearing ServiceRecord.app when bringing
  down a service, so if for some reason there were still connections to
  it at that point (which could happen for example for non-create bindings),
  then we would so it when updating the LRU state of that client process.
- dumpsys procstats's package argument can now be a package or process
  name, and we will dump all relevent information we can find about that
  name.
- Generally improved the quality of the dumpsys procstats output with its
  various options.
- Fixed a bug in ActivityManager.dumpPackageState() where it would hang if
  the service was dumping too much, added meminfo to the set of things
  dumped, and tweaked command line options to include more data.
- Added some more cleaning code to ActiveServices.killServices() to make
  sure we clean out any restarting ServiceRecord entries when a process is
  being force stopped.
- Re-arranged ActiveServices.killServices() to do the main killing of the
  service first, to avoid some wtf() calls that could happen when removing
  connections.

Bug: 11223338
Bug: 11224000

Change-Id: I5db28561c2c78aa43561e52256ff92c02311c56f
parent 275232a7
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -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) {
+141 −80
Original line number Diff line number Diff line
@@ -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,12 +1866,15 @@ 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;
@@ -1860,10 +1889,20 @@ public final class ProcessStats implements Parcelable {
                        && proc.mPssTableSize == 0) {
                    continue;
                }
                if (!proc.mMultiPackage) {
                    continue;
                }
                if (reqPackage != null && !reqPackage.equals(procName)
                        && !reqPackage.equals(proc.mPackage)) {
                    continue;
                }
                numShownProcs++;
                    if (!printedHeader) {
                if (sepNeeded) {
                    pw.println();
                        pw.println("Per-Process Stats:");
                }
                sepNeeded = true;
                if (!printedHeader) {
                    pw.println("Multi-Package Common Processes:");
                    printedHeader = true;
                }
                if (activeOnly && !proc.isInUse()) {
@@ -1878,28 +1917,24 @@ public final class ProcessStats implements Parcelable {
                        ALL_PROC_STATES, now);
                dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                        ALL_PROC_STATES);
                    if (dumpAll) {
                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 (sepNeeded) {
            pw.println();
        }
        if (dumpSummary) {
            pw.println("Summary:");
            dumpSummaryLocked(pw, reqPackage, now, activeOnly);
        } else {
            dumpTotalsLocked(pw, now);
        }
        } else {
            pw.println();
            dumpTotalsLocked(pw, now);
        }

        if (dumpAll) {
            pw.println();
@@ -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))) {
            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;
                    }
            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()) {
                        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);
+38 −14
Original line number Diff line number Diff line
@@ -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.
+19 −7
Original line number Diff line number Diff line
@@ -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,6 +12045,13 @@ public final class ActivityManagerService extends ActivityManagerNative
                    mi.dalvikPrivateDirty = (int)tmpLong[0];
                }
                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 {
                            pw.flush();
                            thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
@@ -12052,6 +12063,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                            }
                        }
                    }
                }
                final long myTotalPss = mi.getTotalPss();
                final long myTotalUss = mi.getTotalUss();
+11 −21
Original line number Diff line number Diff line
@@ -750,9 +750,6 @@ 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
@@ -760,14 +757,6 @@ public final class ProcessStatsService extends IProcessStats.Stub {
                    // 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;
                    }
                }
            }
        }

@@ -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);
Loading