OSDN Git Service

Don't log transition time if no process switch
authorJorim Jaggi <jjaggi@google.com>
Tue, 12 Apr 2016 07:53:16 +0000 (00:53 -0700)
committerJorim Jaggi <jjaggi@google.com>
Fri, 15 Apr 2016 03:12:16 +0000 (03:12 +0000)
If the process of an activity that is launching has another
non-stopped activity, the data is not that interesting,
so remove the logging in these cases.

Bug: 27295491
Change-Id: I65d4a0e01b1e634a589ce8ecbbab337f0e6497ca

services/core/java/com/android/server/am/ActivityMetricsLogger.java
services/core/java/com/android/server/am/ActivityStarter.java

index 43e1bdf..0331470 100644 (file)
@@ -98,13 +98,16 @@ class ActivityMetricsLogger {
      *                   launch
      * @param componentName the component name of the activity being launched
      * @param processRunning whether the process that will contains the activity is already running
+     * @param processSwitch whether the process that will contain the activity didn't have any
+     *                      activity that was stopped, i.e. the started activity is "switching"
+     *                      processes
      */
     void notifyActivityLaunched(int resultCode, @Nullable String componentName,
-            boolean processRunning) {
+            boolean processRunning, boolean processSwitch) {
 
-        if (resultCode < 0 || componentName == null) {
+        if (resultCode < 0 || componentName == null || !processSwitch) {
 
-            // Failed to launch, don't track anything.
+            // Failed to launch or it was not a process switch, so we don't care about the timing.
             reset();
             return;
         }
index 6fba8c8..a96f23a 100644 (file)
@@ -137,6 +137,7 @@ class ActivityStarter {
 
     // Share state variable among methods when starting an activity.
     private ActivityRecord mStartActivity;
+    private ActivityRecord mReusedActivity;
     private Intent mIntent;
     private int mCallingUid;
     private ActivityOptions mOptions;
@@ -785,15 +786,40 @@ class ActivityStarter {
 
             final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
                     : null;
-            final boolean processRunning = outRecord[0] != null &&
-                    mService.mProcessNames.get(outRecord[0].processName,
-                            outRecord[0].appInfo.uid) != null;
+            final ActivityRecord launchedActivity = mReusedActivity != null
+                    ? mReusedActivity : outRecord[0];
+            final ProcessRecord processRecord = launchedActivity != null
+                    ? mService.mProcessNames.get(launchedActivity.processName,
+                            launchedActivity.appInfo.uid)
+                    : null;
+            final boolean processRunning = processRecord != null;
+
+            // We consider this a "process switch" if the process of the activity that gets launched
+            // didn't have an activity that was in started state. In this case, we assume that lot
+            // of caches might be purged so the time until it produces the first frame is very
+            // interesting.
+            final boolean processSwitch = processRecord == null
+                    || !hasStartedActivity(processRecord, launchedActivity);
             mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
-                    processRunning);
+                    processRunning, processSwitch);
             return res;
         }
     }
 
+    final boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
+        final ArrayList<ActivityRecord> activities = record.activities;
+        for (int i = activities.size() - 1; i >= 0; i--) {
+            final ActivityRecord activity = activities.get(i);
+            if (launchedActivity == activity) {
+                continue;
+            }
+            if (!activity.stopped) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
             Bundle bOptions, int userId) {
@@ -883,16 +909,16 @@ class ActivityStarter {
 
         mIntent.setFlags(mLaunchFlags);
 
-        ActivityRecord intentActivity = getReusableIntentActivity();
+        mReusedActivity = getReusableIntentActivity();
 
         final int preferredLaunchStackId =
                 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
 
-        if (intentActivity != null) {
+        if (mReusedActivity != null) {
             // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
             // still needs to be a lock task mode violation since the task gets cleared out and
             // the device would otherwise leave the locked task.
-            if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
+            if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
                     (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                             == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                 mSupervisor.showLockTaskToast();
@@ -901,12 +927,12 @@ class ActivityStarter {
             }
 
             if (mStartActivity.task == null) {
-                mStartActivity.task = intentActivity.task;
+                mStartActivity.task = mReusedActivity.task;
             }
-            if (intentActivity.task.intent == null) {
+            if (mReusedActivity.task.intent == null) {
                 // This task was started because of movement of the activity based on affinity...
                 // Now that we are actually launching it, we can assign the base intent.
-                intentActivity.task.setIntent(mStartActivity);
+                mReusedActivity.task.setIntent(mStartActivity);
             }
 
             // This code path leads to delivering a new intent, we want to make sure we schedule it
@@ -917,7 +943,7 @@ class ActivityStarter {
                 // In this situation we want to remove all activities from the task up to the one
                 // being started. In most cases this means we are resetting the task to its initial
                 // state.
-                final ActivityRecord top = intentActivity.task.performClearTaskForReuseLocked(
+                final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
                         mStartActivity, mLaunchFlags);
                 if (top != null) {
                     if (top.frontOfTask) {
@@ -931,7 +957,7 @@ class ActivityStarter {
                 }
             }
 
-            intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
+            mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
 
             if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                 // We don't need to start a new activity, and the client said not to do anything
@@ -941,7 +967,7 @@ class ActivityStarter {
                 return START_RETURN_INTENT_TO_CALLER;
             }
 
-            setTaskFromIntentActivity(intentActivity);
+            setTaskFromIntentActivity(mReusedActivity);
 
             if (!mAddingToTask && mReuseTask == null) {
                 // We didn't do anything...  but it was needed (a.k.a., client don't use that