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

Commit f210d6b7 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Let's do bug #1769910 actually right.

My original implementation was computing averages and medians.  Now we do binning, as requested.  So much simpler, too!  In addition, it fixes a bug where when hoping across activities we were only accounting for the last activity as the total time; now we count the time from the start of the initial activity.

This also includes some reduction and optimization of the activity manager dumpsys output.
parent 7680d67d
Loading
Loading
Loading
Loading
+42 −16
Original line number Diff line number Diff line
@@ -681,6 +681,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
     */
    HashMap<String, IBinder> mAppBindArgs;

    /**
     * Temporary to avoid allocations.  Protected by main lock.
     */
    final StringBuilder mStringBuilder = new StringBuilder(256);
    
    /**
     * Used to control how we initialize the service.
     */
@@ -778,6 +783,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
    long mLastCpuTime = 0;
    long mLastWriteTime = 0;

    long mInitialStartTime = 0;
    
    /**
     * Set to true after the system has finished booting.
     */
@@ -1635,6 +1642,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        
        if (r.startTime == 0) {
            r.startTime = SystemClock.uptimeMillis();
            if (mInitialStartTime == 0) {
                mInitialStartTime = r.startTime;
            }
        } else if (mInitialStartTime == 0) {
            mInitialStartTime = SystemClock.uptimeMillis();
        }
        
        if (app != null && app.thread != null) {
@@ -1785,7 +1797,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                Watchdog.getInstance().processStarted(app, app.processName, pid);
            }
            
            StringBuilder buf = new StringBuilder(128);
            StringBuilder buf = mStringBuilder;
            buf.setLength(0);
            buf.append("Start proc ");
            buf.append(app.processName);
            buf.append(" for ");
@@ -2813,7 +2826,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
                intent, resolvedType, aInfo, mConfiguration,
                resultRecord, resultWho, requestCode, componentSpecified);
        r.startTime = SystemClock.uptimeMillis();

        HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                != 0 ? r : null;
@@ -4095,7 +4107,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
        }

        StringBuilder info = new StringBuilder();
        StringBuilder info = mStringBuilder;
        info.setLength(0);
        info.append("ANR (application not responding) in process: ");
        info.append(app.processName);
        if (annotation != null) {
@@ -4517,7 +4530,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
        } else if (mStartingProcesses.size() > 0) {
            app = mStartingProcesses.remove(0);
            app.pid = pid;
            app.setPid(pid);
        } else {
            app = null;
        }
@@ -7877,24 +7890,24 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                return;
            }
            pw.println("Activities in Current Activity Manager State:");
            dumpHistoryList(pw, mHistory, "  ", "History");
            dumpHistoryList(pw, mHistory, "  ", "History", true);
            pw.println(" ");
            pw.println("  Running activities (most recent first):");
            dumpHistoryList(pw, mLRUActivities, "  ", "Running");
            dumpHistoryList(pw, mLRUActivities, "  ", "Running", false);
            if (mWaitingVisibleActivities.size() > 0) {
                pw.println(" ");
                pw.println("  Activities waiting for another to become visible:");
                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting");
                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting", false);
            }
            if (mStoppingActivities.size() > 0) {
                pw.println(" ");
                pw.println("  Activities waiting to stop:");
                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping");
                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping", false);
            }
            if (mFinishingActivities.size() > 0) {
                pw.println(" ");
                pw.println("  Activities waiting to finish:");
                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing");
                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing", false);
            }

            pw.println(" ");
@@ -7931,8 +7944,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                        needSep = true;
                    }
                    ProcessRecord r = procs.valueAt(ia);
                    pw.println((r.persistent ? "  *PERSISTENT* Process [" : "  Process [")
                            + r.processName + "] UID " + procs.keyAt(ia));
                    pw.print(r.persistent ? "  *PERSISTENT* Process [" : "  Process [");
                    pw.print(r.processName); pw.print("] UID "); pw.println(procs.keyAt(ia));
                    r.dump(pw, "    ");
                    if (r.persistent) {
                        numPers++;
@@ -8360,16 +8373,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
    }

    private static final void dumpHistoryList(PrintWriter pw, List list,
            String prefix, String label) {
            String prefix, String label, boolean complete) {
        TaskRecord lastTask = null;
        for (int i=list.size()-1; i>=0; i--) {
            HistoryRecord r = (HistoryRecord)list.get(i);
            if (lastTask != r.task) {
                lastTask = r.task;
                if (complete || !r.inHistory) {
                    lastTask.dump(pw, prefix + "  ");
                } else {
                    pw.print(prefix);
                    pw.print("  ");
                    pw.println(lastTask);
                }
            }
            pw.println(prefix + "    " + label + " #" + i + ":");
            if (complete || !r.inHistory) {
                pw.print(prefix); pw.print("    "); pw.print(label);
                        pw.print(" #"); pw.print(i); pw.println(":");
                r.dump(pw, prefix + "      ");
            } else {
                pw.print(prefix); pw.print("    "); pw.print(label);
                        pw.print(" #"); pw.print(i); pw.print(": ");
                        pw.println(r);
            }
        }
    }

@@ -8738,7 +8764,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                mPidsSelfLocked.remove(app.pid);
                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
            }
            app.pid = 0;
            app.setPid(0);
        }
    }

+14 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ class ConnectionRecord {
    final HistoryRecord activity;   // If non-null, the owning activity.
    final IServiceConnection conn;  // The client connection.
    final int flags;                // Binding options.
    String stringName;              // Caching of toString.
    
    void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + this);
@@ -46,9 +47,17 @@ class ConnectionRecord {
    }

    public String toString() {
        return "ConnectionRecord{"
            + Integer.toHexString(System.identityHashCode(this))
            + " " + binding.service.shortName
            + ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("ConnectionRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(binding.service.shortName);
        sb.append(":@");
        sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
        sb.append('}');
        return stringName = sb.toString();
    }
}
+12 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ class ContentProviderRecord extends ContentProviderHolder {
    int externals;     // number of non-framework processes supported by this provider
    ProcessRecord app; // if non-null, hosting application
    ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
    String stringName;
    
    public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
        super(_info);
@@ -69,8 +70,15 @@ class ContentProviderRecord extends ContentProviderHolder {
    }

    public String toString() {
        return "ContentProviderRecord{"
            + Integer.toHexString(System.identityHashCode(this))
            + " " + info.name + "}";
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("ContentProviderRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(info.name);
        sb.append('}');
        return stringName = sb.toString();
    }
}
+96 −49
Original line number Diff line number Diff line
@@ -100,46 +100,74 @@ class HistoryRecord extends IApplicationToken.Stub {
    boolean hasBeenLaunched;// has this activity ever been launched?
    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.

    String stringName;      // for caching of toString().
    
    void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + this);
        pw.println(prefix + "packageName=" + packageName
              + " processName=" + processName);
        pw.println(prefix + "launchedFromUid=" + launchedFromUid
                + " app=" + app);
        pw.println(prefix + intent);
        pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
        pw.println(prefix + "taskAffinity=" + taskAffinity);
        pw.println(prefix + "realActivity=" + realActivity);
        pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
        pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
                + " icon=0x" + Integer.toHexString(icon)
                + " theme=0x" + Integer.toHexString(theme));
        pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
                + " componentSpecified=" + componentSpecified
                + " isHomeActivity=" + isHomeActivity);
        pw.println(prefix + "configuration=" + configuration);
        pw.println(prefix + "resultTo=" + resultTo
              + " resultWho=" + resultWho + " resultCode=" + requestCode);
        pw.println(prefix + "results=" + results);
        pw.println(prefix + "pendingResults=" + pendingResults);
        pw.println(prefix + "readUriPermissions=" + readUriPermissions);
        pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
        pw.println(prefix + "launchFailed=" + launchFailed
              + " haveState=" + haveState + " icicle=" + icicle);
        pw.println(prefix + "state=" + state
              + " stopped=" + stopped + " finishing=" + finishing);
        pw.println(prefix + "keysPaused=" + keysPaused
              + " inHistory=" + inHistory + " persistent=" + persistent
              + " launchMode=" + launchMode);
        pw.println(prefix + "fullscreen=" + fullscreen
              + " visible=" + visible
              + " frozenBeforeDestroy=" + frozenBeforeDestroy
              + " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
        pw.println(prefix + "waitingVisible=" + waitingVisible
              + " nowVisible=" + nowVisible);
        pw.println(prefix + "configDestroy=" + configDestroy
                + " configChangeFlags=" + Integer.toHexString(configChangeFlags));
        pw.println(prefix + "connections=" + connections);
        pw.print(prefix); pw.println(this);
        pw.print(prefix); pw.print("packageName="); pw.print(packageName);
                pw.print(" processName="); pw.println(processName);
        pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
                pw.print(" app="); pw.println(app);
        pw.print(prefix); pw.println(intent);
        pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
                pw.print(" task="); pw.println(task);
        pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
        pw.print(prefix); pw.print("realActivity="); pw.println(realActivity);
        pw.print(prefix); pw.print("dir="); pw.print(baseDir);
                pw.print(" res="); pw.print(resDir);
                pw.print(" data="); pw.println(dataDir);
        pw.print(prefix); pw.print("labelRes=0x");
                pw.print(Integer.toHexString(labelRes));
                pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
                pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
        pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
                pw.print(" componentSpecified="); pw.print(componentSpecified);
                pw.print(" isHomeActivity="); pw.println(isHomeActivity);
        pw.print(prefix); pw.print("configuration="); pw.println(configuration);
        if (resultTo != null || resultWho != null) {
            pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
                    pw.print(" resultWho="); pw.print(resultWho);
                    pw.print(" resultCode="); pw.println(requestCode);
        }
        if (results != null) {
            pw.print(prefix); pw.print("results="); pw.println(results);
        }
        if (pendingResults != null) {
            pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
        }
        if (readUriPermissions != null) {
            pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
        }
        if (writeUriPermissions != null) {
            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
        }
        pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
                pw.print(" haveState="); pw.print(haveState);
                pw.print(" icicle="); pw.println(icicle);
        pw.print(prefix); pw.print("state="); pw.print(state);
                pw.print(" stopped="); pw.print(stopped);
                pw.print(" finishing="); pw.println(finishing);
        pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
                pw.print(" inHistory="); pw.print(inHistory);
                pw.print(" persistent="); pw.print(persistent);
                pw.print(" launchMode="); pw.println(launchMode);
        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
                pw.print(" visible="); pw.print(visible);
                pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
                pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
                pw.print(" idle="); pw.println(idle);
        if (waitingVisible || nowVisible) {
            pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
                    pw.print(" nowVisible="); pw.println(nowVisible);
        }
        if (configDestroy || configChangeFlags != 0) {
            pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
                    pw.print(" configChangeFlags=");
                    pw.println(Integer.toHexString(configChangeFlags));
        }
        if (connections != null) {
            pw.print(prefix); pw.print("connections="); pw.println(connections);
        }
    }

    HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -336,18 +364,30 @@ class HistoryRecord extends IApplicationToken.Stub {
    public void windowsVisible() {
        synchronized(service) {
            if (startTime != 0) {
                long time = SystemClock.uptimeMillis() - startTime;
                final long curTime = SystemClock.uptimeMillis();
                final long thisTime = curTime - startTime;
                final long totalTime = service.mInitialStartTime != 0
                        ? (curTime - service.mInitialStartTime) : thisTime;
                if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
                    EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
                            System.identityHashCode(this), shortComponentName, time);
                    Log.i(ActivityManagerService.TAG, "Displayed activity "
                            + shortComponentName
                            + ": " + time + " ms");
                }
                if (time > 0) {
                    service.mUsageStatsService.noteLaunchTime(realActivity, (int)time);
                            System.identityHashCode(this), shortComponentName,
                            thisTime, totalTime);
                    StringBuilder sb = service.mStringBuilder;
                    sb.setLength(0);
                    sb.append("Displayed activity ");
                    sb.append(shortComponentName);
                    sb.append(": ");
                    sb.append(thisTime);
                    sb.append(" ms (total ");
                    sb.append(totalTime);
                    sb.append(" ms)");
                    Log.i(ActivityManagerService.TAG, sb.toString());
                }
                if (totalTime > 0) {
                    service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
                }
                startTime = 0;
                service.mInitialStartTime = 0;
            }
            if (ActivityManagerService.DEBUG_SWITCH) Log.v(
                    ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -457,8 +497,15 @@ class HistoryRecord extends IApplicationToken.Stub {
    
    
    public String toString() {
        return "HistoryRecord{"
            + Integer.toHexString(System.identityHashCode(this))
            + " " + intent.getComponent().toShortString() + "}";
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("HistoryRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(intent.getComponent().toShortString());
        sb.append('}');
        return stringName = sb.toString();
    }
}
+89 −35
Original line number Diff line number Diff line
@@ -98,44 +98,82 @@ class ProcessRecord implements Watchdog.PssRequestor {
    boolean waitedForDebugger;  // has process show wait for debugger dialog?
    Dialog waitDialog;          // current wait for debugger dialog
    
    String stringName;          // caching of toString() result.
    
    // These reports are generated & stored when an app gets into an error condition.
    // They will be "null" when all is OK.
    ActivityManager.ProcessErrorStateInfo crashingReport;
    ActivityManager.ProcessErrorStateInfo notRespondingReport;

    void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + this);
        pw.println(prefix + "class=" + info.className);
        pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
        pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir 
              + " data=" + info.dataDir);
        pw.println(prefix + "packageList=" + pkgList);
        pw.println(prefix + "instrumentationClass=" + instrumentationClass
              + " instrumentationProfileFile=" + instrumentationProfileFile);
        pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
        pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
        pw.println(prefix + "pid=" + pid + " starting=" + starting
                + " lastPss=" + lastPss);
        pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
                + " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
                + " curAdj=" + curAdj + " setAdj=" + setAdj);
        pw.println(prefix + "isForeground=" + isForeground
                + " setIsForeground=" + setIsForeground
                + " foregroundServices=" + foregroundServices
                + " forcingToForeground=" + forcingToForeground);
        pw.println(prefix + "persistent=" + persistent + " removed=" + removed
                + " persistentActivities=" + persistentActivities);
        pw.println(prefix + "debugging=" + debugging
                + " crashing=" + crashing + " " + crashDialog
                + " notResponding=" + notResponding + " " + anrDialog
                + " bad=" + bad);
        pw.println(prefix + "activities=" + activities);
        pw.println(prefix + "services=" + services);
        pw.println(prefix + "executingServices=" + executingServices);
        pw.println(prefix + "connections=" + connections);
        pw.println(prefix + "pubProviders=" + pubProviders);
        pw.println(prefix + "conProviders=" + conProviders);
        pw.println(prefix + "receivers=" + receivers);
        pw.print(prefix); pw.println(this);
        if (info.className != null) {
            pw.print(prefix); pw.print("class="); pw.println(info.className);
        }
        if (info.manageSpaceActivityName != null) {
            pw.print(prefix); pw.print("manageSpaceActivityName=");
            pw.println(info.manageSpaceActivityName);
        }
        pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
                pw.print(" publicDir="); pw.print(info.publicSourceDir);
                pw.print(" data="); pw.println(info.dataDir);
        pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
        if (instrumentationClass != null || instrumentationProfileFile != null
                || instrumentationArguments != null) {
            pw.print(prefix); pw.print("instrumentationClass=");
                    pw.print(instrumentationClass);
                    pw.print(" instrumentationProfileFile=");
                    pw.println(instrumentationProfileFile);
            pw.print(prefix); pw.print("instrumentationArguments=");
                    pw.println(instrumentationArguments);
        }
        pw.print(prefix); pw.print("thread="); pw.print(thread);
                pw.print(" curReceiver="); pw.println(curReceiver);
        pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
                pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
        pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
                pw.print(" hidden="); pw.print(hiddenAdj);
                pw.print(" curRaw="); pw.print(curRawAdj);
                pw.print(" setRaw="); pw.print(setRawAdj);
                pw.print(" cur="); pw.print(curAdj);
                pw.print(" set="); pw.println(setAdj);
        pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
                pw.print(" setIsForeground="); pw.print(setIsForeground);
                pw.print(" foregroundServices="); pw.print(foregroundServices);
                pw.print(" forcingToForeground="); pw.println(forcingToForeground);
        pw.print(prefix); pw.print("persistent="); pw.print(persistent);
                pw.print(" removed="); pw.print(removed);
                pw.print(" persistentActivities="); pw.println(persistentActivities);
        if (debugging || crashing || crashDialog != null || notResponding
                || anrDialog != null || bad) {
            pw.print(prefix); pw.print("debugging="); pw.print(debugging);
                    pw.print(" crashing="); pw.print(crashing);
                    pw.print(" "); pw.print(crashDialog);
                    pw.print(" notResponding="); pw.print(notResponding);
                    pw.print(" " ); pw.print(anrDialog);
                    pw.print(" bad="); pw.println(bad);
        }
        if (activities.size() > 0) {
            pw.print(prefix); pw.print("activities="); pw.println(activities);
        }
        if (services.size() > 0) {
            pw.print(prefix); pw.print("services="); pw.println(services);
        }
        if (executingServices.size() > 0) {
            pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
        }
        if (connections.size() > 0) {
            pw.print(prefix); pw.print("connections="); pw.println(connections);
        }
        if (pubProviders.size() > 0) {
            pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
        }
        if (conProviders.size() > 0) {
            pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
        }
        if (receivers.size() > 0) {
            pw.print(prefix); pw.print("receivers="); pw.println(receivers);
        }
    }
    
    ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
@@ -154,6 +192,11 @@ class ProcessRecord implements Watchdog.PssRequestor {
        persistentActivities = 0;
    }

    public void setPid(int _pid) {
        pid = _pid;
        stringName = null;
    }
    
    /**
     * This method returns true if any of the activities within the process record are interesting
     * to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -188,9 +231,20 @@ class ProcessRecord implements Watchdog.PssRequestor {
    }
    
    public String toString() {
        return "ProcessRecord{"
            + Integer.toHexString(System.identityHashCode(this))
            + " " + pid + ":" + processName + "/" + info.uid + "}";
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("ProcessRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(pid);
        sb.append(':');
        sb.append(processName);
        sb.append('/');
        sb.append(info.uid);
        sb.append('}');
        return stringName = sb.toString();
    }
    
    /*
Loading