ActivityMetricsLogger.java revision f970410afef518003c84eef022194848b2a4f606
177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskipackage com.android.server.am;
277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
577d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
677d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport static android.app.ActivityManager.StackId.HOME_STACK_ID;
7caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynskiimport static android.app.ActivityManager.StackId.PINNED_STACK_ID;
8f970410afef518003c84eef022194848b2a4f606Jorim Jaggiimport static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
9f970410afef518003c84eef022194848b2a4f606Jorim Jaggiimport static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
100e381e278a2c2a3a7c86c9951ac5cbcdc3a186f4Filip Gruszczynskiimport static com.android.server.am.ActivityStack.STACK_INVISIBLE;
1177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
12275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggiimport android.annotation.Nullable;
1377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport android.app.ActivityManager.StackId;
1477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport android.content.Context;
1577d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport android.os.SystemClock;
16f970410afef518003c84eef022194848b2a4f606Jorim Jaggiimport android.util.Slog;
1777d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
1877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiimport com.android.internal.logging.MetricsLogger;
19275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggiimport com.android.internal.logging.MetricsProto.MetricsEvent;
2077d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
2177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski/**
2277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski * Handles logging into Tron.
2377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski */
2477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynskiclass ActivityMetricsLogger {
25f970410afef518003c84eef022194848b2a4f606Jorim Jaggi
26f970410afef518003c84eef022194848b2a4f606Jorim Jaggi    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM;
27f970410afef518003c84eef022194848b2a4f606Jorim Jaggi
2877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    // Window modes we are interested in logging. If we ever introduce a new type, we need to add
2977d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
3077d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private static final int WINDOW_STATE_STANDARD = 0;
3177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
3277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private static final int WINDOW_STATE_FREEFORM = 2;
3377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private static final int WINDOW_STATE_INVALID = -1;
3477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
35275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private static final long INVALID_START_TIME = -1;
36275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
3777d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
3877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    // time we log.
3977d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
40ae255ee61b5e174c2164e58389b8a7ff8a95e14dChris Wren            "window_time_0", "window_time_1", "window_time_2"};
4177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
4277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private int mWindowState = WINDOW_STATE_STANDARD;
4377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private long mLastLogTimeSecs;
4477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private final ActivityStackSupervisor mSupervisor;
4577d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    private final Context mContext;
4677d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
47275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private long mCurrentTransitionStartTime = INVALID_START_TIME;
48275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private boolean mLoggedWindowsDrawn;
49275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private boolean mLoggedStartingWindowDrawn;
50275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private boolean mLoggedTransitionStarting;
51275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
5277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
5377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
5477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        mSupervisor = supervisor;
5577d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        mContext = context;
5677d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    }
5777d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
5877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    void logWindowState() {
5977d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        final long now = SystemClock.elapsedRealtime() / 1000;
6077d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        if (mWindowState != WINDOW_STATE_INVALID) {
6177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski            // We log even if the window state hasn't changed, because the user might remain in
6277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski            // home/fullscreen move forever and we would like to track this kind of behavior
6377d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski            // too.
6477d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski            MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
6577d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski                    (int) (now - mLastLogTimeSecs));
6677d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        }
6777d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        mLastLogTimeSecs = now;
6877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski
6977d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
708051c5c89060906f5a3a1ca4adb3b53bb423e56bWale Ogunwale        if (stack != null && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
7177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski            mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
72caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski            return;
73caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        }
74caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        mWindowState = WINDOW_STATE_INVALID;
75caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        stack = mSupervisor.getFocusedStack();
76caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        if (stack.mStackId == PINNED_STACK_ID) {
77caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski            stack = mSupervisor.findStackBehind(stack);
7877d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        }
79caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        if (stack.mStackId == HOME_STACK_ID
80caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski                || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
81caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski            mWindowState = WINDOW_STATE_STANDARD;
82caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        } else if (stack.mStackId == DOCKED_STACK_ID) {
83f970410afef518003c84eef022194848b2a4f606Jorim Jaggi            Slog.wtf(TAG, "Docked stack shouldn't be the focused stack, because it reported not"
84f970410afef518003c84eef022194848b2a4f606Jorim Jaggi                    + " being visible.");
85f970410afef518003c84eef022194848b2a4f606Jorim Jaggi            mWindowState = WINDOW_STATE_INVALID;
86caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        } else if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
87caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski            mWindowState = WINDOW_STATE_FREEFORM;
88caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski        } else if (StackId.isStaticStack(stack.mStackId)) {
89caae14e478e115d01f9b32890cb31231575e65ddFilip Gruszczynski            throw new IllegalStateException("Unknown stack=" + stack);
9077d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski        }
9177d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski    }
92275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
93275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    /**
94275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * Notifies the tracker at the earliest possible point when we are starting to launch an
95275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * activity.
96275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     */
97275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    void notifyActivityLaunching() {
98275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mCurrentTransitionStartTime = System.currentTimeMillis();
99275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
100275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
101275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    /**
102275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * Notifies the tracker the the activity is actually launching.
103275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     *
104275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
105275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     *                   launch
106275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * @param componentName the component name of the activity being launched
107275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * @param processRunning whether the process that will contains the activity is already running
108be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi     * @param processSwitch whether the process that will contain the activity didn't have any
109be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi     *                      activity that was stopped, i.e. the started activity is "switching"
110be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi     *                      processes
111275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     */
112275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    void notifyActivityLaunched(int resultCode, @Nullable String componentName,
113be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi            boolean processRunning, boolean processSwitch) {
114275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
115be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi        if (resultCode < 0 || componentName == null || !processSwitch) {
116275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
117be67c90f4c2255cab3bc036ecdc8d9636ed5e4b5Jorim Jaggi            // Failed to launch or it was not a process switch, so we don't care about the timing.
118275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            reset();
119275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            return;
120275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
121275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
122275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_COMPONENT_NAME,
123275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                componentName);
124275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_PROCESS_RUNNING,
125275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                processRunning);
126275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS,
127275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                (int) (SystemClock.uptimeMillis() / 1000));
128275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
129275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
130275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    /**
131275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * Notifies the tracker that all windows of the app have been drawn.
132275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     */
133275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    void notifyWindowsDrawn() {
134275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        if (!isTransitionActive() || mLoggedWindowsDrawn) {
135275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            return;
136275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
137275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS,
138275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                calculateCurrentDelay());
139275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedWindowsDrawn = true;
140275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        if (mLoggedTransitionStarting) {
141275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            reset();
142275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
143275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
144275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
145275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    /**
146275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * Notifies the tracker that the starting window was drawn.
147275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     */
148275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    void notifyStartingWindowDrawn() {
149275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        if (!isTransitionActive() || mLoggedStartingWindowDrawn) {
150275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            return;
151275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
152275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedStartingWindowDrawn = true;
153275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
154275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                calculateCurrentDelay());
155275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
156275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
157275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    /**
158275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * Notifies the tracker that the app transition is starting.
159275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     *
160275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     * @param reason The reason why we started it. Must be on of
161275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     *               ActivityManagerInternal.APP_TRANSITION_* reasons.
162275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi     */
163275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    void notifyTransitionStarting(int reason) {
164275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        if (!isTransitionActive() || mLoggedTransitionStarting) {
165275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            return;
166275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
167275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_REASON, reason);
168275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DELAY_MS,
169275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi                calculateCurrentDelay());
170275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedTransitionStarting = true;
171275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        if (mLoggedWindowsDrawn) {
172275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi            reset();
173275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        }
174275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
175275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
176275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private boolean isTransitionActive() {
177275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        return mCurrentTransitionStartTime != INVALID_START_TIME;
178275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
179275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
180275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private void reset() {
181275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mCurrentTransitionStartTime = INVALID_START_TIME;
182275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedWindowsDrawn = false;
183275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedTransitionStarting = false;
184275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        mLoggedStartingWindowDrawn = false;
185275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
186275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
187275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    private int calculateCurrentDelay() {
188275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi
189275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        // Shouldn't take more than 25 days to launch an app, so int is fine here.
190275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi        return (int) (System.currentTimeMillis() - mCurrentTransitionStartTime);
191275561a74677f9d6c8f3f2cebc3cfea416ca586dJorim Jaggi    }
19277d9448e2d6dd8a45c5fedef43c8a1cf4afd28b9Filip Gruszczynski}
193