diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 20 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.aidl | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityRecord.java | 8 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStarter.java | 6 |
8 files changed, 48 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index 8754d21b14ac..d90d34fccff6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3615,6 +3615,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); diff --git a/api/system-current.txt b/api/system-current.txt index fd176d0f8a7f..19c2f4dd7565 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3743,6 +3743,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); diff --git a/api/test-current.txt b/api/test-current.txt index 5e87ab981ced..671e24edeca0 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -3617,6 +3617,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 950991b75546..b36a1600bae5 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -18,6 +18,7 @@ package android.app; import android.metrics.LogMaker; import android.graphics.Rect; +import android.os.SystemClock; import android.view.ViewRootImpl.ActivityConfigCallback; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; @@ -7433,6 +7434,25 @@ public class Activity extends ContextThemeWrapper } } + /** + * Return the timestamp at which this activity start was last initiated by the system in the + * {@link SystemClock#uptimeMillis()} time base. + * + * This can be used to understand how much time is taken for an activity to be started and + * displayed to the user. + * + * @return timestamp at which this activity start was initiated by the system + * or {@code 0} if for any reason the timestamp could not be retrieved. + */ + public long getStartInitiatedTime() { + try { + return ActivityManager.getService().getActivityStartInitiatedTime(mToken); + } catch (RemoteException e) { + Log.e(TAG, "Failed to call getActivityStartTime", e); + return 0; + } + } + class HostCallbacks extends FragmentHostCallback<Activity> { public HostCallbacks() { super(Activity.this /*activity*/); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index fc827a946a44..4210d2e7d3ec 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -632,6 +632,8 @@ interface IActivityManager { */ void backgroundWhitelistUid(int uid); + long getActivityStartInitiatedTime(IBinder token); + // WARNING: when these transactions are updated, check if they are any callers on the native // side. If so, make sure they are using the correct transaction ids and arguments. // If a transaction which will also be used on the native side is being inserted, add it diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2be53136bb74..6b0a73b25e71 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -23885,6 +23885,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @Override + public long getActivityStartInitiatedTime(IBinder token) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r != null) { + return r.mStartInitiatedTimeMs; + } + return 0; + } + void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) { final PackageManagerInternal packageManager = getPackageManagerInternalLocked(); final boolean updateFrameworkRes = packagesToUpdate.contains("android"); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 276b267edb5b..17c7dde11726 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -341,6 +341,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private final Rect mBounds = new Rect(); /** + * Denotes the timestamp at which this activity start was last initiated in the + * {@link SystemClock#uptimeMillis()} time base. + */ + long mStartInitiatedTimeMs; + + /** * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)} */ private final Configuration mTmpConfig1 = new Configuration(); @@ -498,6 +504,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print(" forceNewConfig="); pw.println(forceNewConfig); pw.print(prefix); pw.print("mActivityType="); pw.println(activityTypeToString(mActivityType)); + pw.print(prefix); pw.print("mStartInitiatedTimeMs="); + TimeUtils.formatDuration(mStartInitiatedTimeMs, now, pw); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 56594d3fdf48..8f1c20330e53 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -244,6 +244,7 @@ class ActivityStarter { ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { + final long activityStartTime = SystemClock.uptimeMillis(); int err = ActivityManager.START_SUCCESS; ProcessRecord callerApp = null; @@ -478,6 +479,7 @@ class ActivityStarter { callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, container, options, sourceRecord); + r.mStartInitiatedTimeMs = activityStartTime; if (outActivity != null) { outActivity[0] = r; } @@ -1029,6 +1031,7 @@ class ActivityStarter { // so make sure the task now has the identity of the new intent. top.getTask().setIntent(mStartActivity); } + top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask()); top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); @@ -1052,6 +1055,7 @@ class ActivityStarter { setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { + reusedActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); @@ -1084,6 +1088,7 @@ class ActivityStarter { || mLaunchSingleTop || mLaunchSingleTask); if (dontStart) { ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask()); + top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { @@ -1664,6 +1669,7 @@ class ActivityStarter { // desires. if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop) && intentActivity.realActivity.equals(mStartActivity.realActivity)) { + intentActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, intentActivity.getTask()); if (intentActivity.frontOfTask) { |