Merge "Add in-task activity transition metrics" into udc-dev am: 648caea2c2

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23211056

Change-Id: I21be0e85f0766eed4c8d8503510ff48d5d765036
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Riddle Hsu
2023-05-17 06:05:22 +00:00
committed by Automerger Merge Worker
3 changed files with 61 additions and 19 deletions

View File

@@ -294,6 +294,8 @@ class ActivityMetricsLogger {
final int mProcessState; final int mProcessState;
/** The oom adj score of the launching activity prior to the launch */ /** The oom adj score of the launching activity prior to the launch */
final int mProcessOomAdj; final int mProcessOomAdj;
/** Whether the activity is launched above a visible activity in the same task. */
final boolean mIsInTaskActivityStart;
/** Whether the last launched activity has reported drawn. */ /** Whether the last launched activity has reported drawn. */
boolean mIsDrawn; boolean mIsDrawn;
/** The latest activity to have been launched. */ /** The latest activity to have been launched. */
@@ -330,7 +332,7 @@ class ActivityMetricsLogger {
static TransitionInfo create(@NonNull ActivityRecord r, static TransitionInfo create(@NonNull ActivityRecord r,
@NonNull LaunchingState launchingState, @Nullable ActivityOptions options, @NonNull LaunchingState launchingState, @Nullable ActivityOptions options,
boolean processRunning, boolean processSwitch, int processState, int processOomAdj, boolean processRunning, boolean processSwitch, int processState, int processOomAdj,
boolean newActivityCreated, int startResult) { boolean newActivityCreated, boolean isInTaskActivityStart, int startResult) {
if (startResult != START_SUCCESS && startResult != START_TASK_TO_FRONT) { if (startResult != START_SUCCESS && startResult != START_TASK_TO_FRONT) {
return null; return null;
} }
@@ -345,19 +347,21 @@ class ActivityMetricsLogger {
transitionType = TYPE_TRANSITION_COLD_LAUNCH; transitionType = TYPE_TRANSITION_COLD_LAUNCH;
} }
return new TransitionInfo(r, launchingState, options, transitionType, processRunning, return new TransitionInfo(r, launchingState, options, transitionType, processRunning,
processSwitch, processState, processOomAdj); processSwitch, processState, processOomAdj, isInTaskActivityStart);
} }
/** Use {@link TransitionInfo#create} instead to ensure the transition type is valid. */ /** Use {@link TransitionInfo#create} instead to ensure the transition type is valid. */
private TransitionInfo(ActivityRecord r, LaunchingState launchingState, private TransitionInfo(ActivityRecord r, LaunchingState launchingState,
ActivityOptions options, int transitionType, boolean processRunning, ActivityOptions options, int transitionType, boolean processRunning,
boolean processSwitch, int processState, int processOomAdj) { boolean processSwitch, int processState, int processOomAdj,
boolean isInTaskActivityStart) {
mLaunchingState = launchingState; mLaunchingState = launchingState;
mTransitionType = transitionType; mTransitionType = transitionType;
mProcessRunning = processRunning; mProcessRunning = processRunning;
mProcessSwitch = processSwitch; mProcessSwitch = processSwitch;
mProcessState = processState; mProcessState = processState;
mProcessOomAdj = processOomAdj; mProcessOomAdj = processOomAdj;
mIsInTaskActivityStart = isInTaskActivityStart;
setLatestLaunchedActivity(r); setLatestLaunchedActivity(r);
// The launching state can be reused by consecutive launch. Its original association // The launching state can be reused by consecutive launch. Its original association
// shouldn't be changed by a separated transition. // shouldn't be changed by a separated transition.
@@ -515,7 +519,7 @@ class ActivityMetricsLogger {
} }
} }
boolean isIntresetedToEventLog() { boolean isInterestedToEventLog() {
return type == TYPE_TRANSITION_WARM_LAUNCH || type == TYPE_TRANSITION_COLD_LAUNCH; return type == TYPE_TRANSITION_WARM_LAUNCH || type == TYPE_TRANSITION_COLD_LAUNCH;
} }
@@ -728,9 +732,10 @@ class ActivityMetricsLogger {
return; return;
} }
final boolean isInTaskActivityStart = launchedActivity.getTask().isVisible();
final TransitionInfo newInfo = TransitionInfo.create(launchedActivity, launchingState, final TransitionInfo newInfo = TransitionInfo.create(launchedActivity, launchingState,
options, processRunning, processSwitch, processState, processOomAdj, options, processRunning, processSwitch, processState, processOomAdj,
newActivityCreated, resultCode); newActivityCreated, isInTaskActivityStart, resultCode);
if (newInfo == null) { if (newInfo == null) {
abort(launchingState, "unrecognized launch"); abort(launchingState, "unrecognized launch");
return; return;
@@ -1042,18 +1047,23 @@ class ActivityMetricsLogger {
// Take a snapshot of the transition info before sending it to the handler for logging. // Take a snapshot of the transition info before sending it to the handler for logging.
// This will avoid any races with other operations that modify the ActivityRecord. // This will avoid any races with other operations that modify the ActivityRecord.
final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info); final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info);
if (info.isInterestingToLoggerAndObserver()) { final boolean isOpaque = info.mLastLaunchedActivity.mStyleFillsParent;
final long uptimeNs = info.mLaunchingState.mStartUptimeNs; final long uptimeNs = info.mLaunchingState.mStartUptimeNs;
final int transitionDelay = info.mCurrentTransitionDelayMs; final int transitionDelay = info.mCurrentTransitionDelayMs;
final int processState = info.mProcessState; final int processState = info.mProcessState;
final int processOomAdj = info.mProcessOomAdj; final int processOomAdj = info.mProcessOomAdj;
mLoggerHandler.post(() -> logAppTransition( mLoggerHandler.post(() -> {
uptimeNs, transitionDelay, infoSnapshot, isHibernating, if (info.isInterestingToLoggerAndObserver()) {
processState, processOomAdj)); logAppTransition(uptimeNs, transitionDelay, infoSnapshot, isHibernating,
processState, processOomAdj);
} }
if (infoSnapshot.isIntresetedToEventLog()) { if (info.mIsInTaskActivityStart) {
mLoggerHandler.post(() -> logAppDisplayed(infoSnapshot)); logInTaskActivityStart(infoSnapshot, isOpaque, transitionDelay);
} }
if (infoSnapshot.isInterestedToEventLog()) {
logAppDisplayed(infoSnapshot);
}
});
if (info.mPendingFullyDrawn != null) { if (info.mPendingFullyDrawn != null) {
info.mPendingFullyDrawn.run(); info.mPendingFullyDrawn.run();
} }
@@ -1158,6 +1168,22 @@ class ActivityMetricsLogger {
return info != null && info.isLoading(); return info != null && info.isLoading();
} }
@VisibleForTesting
void logInTaskActivityStart(TransitionInfoSnapshot info, boolean isOpaque,
int transitionDelayMs) {
if (DEBUG_METRICS) {
Slog.i(TAG, "IN_TASK_ACTIVITY_STARTED " + info.launchedActivityName
+ " transitionDelayMs=" + transitionDelayMs + "ms");
}
FrameworkStatsLog.write(FrameworkStatsLog.IN_TASK_ACTIVITY_STARTED,
info.applicationInfo.uid,
getAppStartTransitionType(info.type, info.relaunched),
isOpaque,
transitionDelayMs,
info.windowsDrawnDelayMs,
TimeUnit.NANOSECONDS.toMillis(info.timestampNs));
}
private void logAppDisplayed(TransitionInfoSnapshot info) { private void logAppDisplayed(TransitionInfoSnapshot info) {
EventLog.writeEvent(WM_ACTIVITY_LAUNCH_TIME, EventLog.writeEvent(WM_ACTIVITY_LAUNCH_TIME,
info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName, info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName,
@@ -1228,7 +1254,7 @@ class ActivityMetricsLogger {
currentTimestampNs - info.mLaunchingState.mStartUptimeNs); currentTimestampNs - info.mLaunchingState.mStartUptimeNs);
final TransitionInfoSnapshot infoSnapshot = final TransitionInfoSnapshot infoSnapshot =
new TransitionInfoSnapshot(info, r, (int) startupTimeMs); new TransitionInfoSnapshot(info, r, (int) startupTimeMs);
if (infoSnapshot.isIntresetedToEventLog()) { if (infoSnapshot.isInterestedToEventLog()) {
mLoggerHandler.post(() -> logAppFullyDrawn(infoSnapshot)); mLoggerHandler.post(() -> logAppFullyDrawn(infoSnapshot));
} }
mLastTransitionInfo.remove(r); mLastTransitionInfo.remove(r);

View File

@@ -712,7 +712,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* when running ANIM_SCENE_TRANSITION. * when running ANIM_SCENE_TRANSITION.
* @see WindowContainer#providesOrientation() * @see WindowContainer#providesOrientation()
*/ */
private final boolean mStyleFillsParent; final boolean mStyleFillsParent;
// The input dispatching timeout for this application token in milliseconds. // The input dispatching timeout for this application token in milliseconds.
long mInputDispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; long mInputDispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;

View File

@@ -23,12 +23,15 @@ import static android.view.WindowManager.TRANSIT_OPEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@@ -388,6 +391,19 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
return mActivityMetricsLogger.notifyWindowsDrawn(r); return mActivityMetricsLogger.notifyWindowsDrawn(r);
} }
@Test
public void testInTaskActivityStart() {
mTrampolineActivity.setVisible(true);
doReturn(true).when(mTrampolineActivity).isReportedDrawn();
spyOn(mActivityMetricsLogger);
onActivityLaunched(mTopActivity);
transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
verify(mActivityMetricsLogger, timeout(TIMEOUT_MS)).logInTaskActivityStart(
any(), anyBoolean(), anyInt());
}
@Test @Test
public void testOnActivityLaunchFinishedTrampoline() { public void testOnActivityLaunchFinishedTrampoline() {
onActivityLaunchedTrampoline(); onActivityLaunchedTrampoline();