UserEventDispatcher.java revision 8ce6063c4a5bd90810f0a21c946e5bbad3ce9de4
1ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song/*
2ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * Copyright (C) 2012 The Android Open Source Project
3ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song *
4ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * Licensed under the Apache License, Version 2.0 (the "License");
5ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * you may not use this file except in compliance with the License.
6ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * You may obtain a copy of the License at
7ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song *
8ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song *      http://www.apache.org/licenses/LICENSE-2.0
9ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song *
10ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * Unless required by applicable law or agreed to in writing, software
11ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * distributed under the License is distributed on an "AS IS" BASIS,
12ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * See the License for the specific language governing permissions and
14ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song * limitations under the License.
15ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song */
16ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
17a9c69ce09c164c8ad0191e05318460d0955825a7Hyunyoung Songpackage com.android.launcher3.logging;
18a9c69ce09c164c8ad0191e05318460d0955825a7Hyunyoung Song
196470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Songimport android.content.ComponentName;
20ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport android.content.Intent;
2164976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyalimport android.util.Log;
22ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport android.view.View;
23ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport android.view.ViewParent;
248fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
25ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport com.android.launcher3.ItemInfo;
2655c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickhamimport com.android.launcher3.userevent.nano.LauncherLogProto;
2746ab2276f97518e9ba71e4bf3109b8ebd924cbabSunny Goyalimport com.android.launcher3.userevent.nano.LauncherLogProto.Action;
28ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
29ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport com.android.launcher3.userevent.nano.LauncherLogProto.Target;
30ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport com.android.launcher3.util.ComponentKey;
31ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
32ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Songimport java.util.List;
3364976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyalimport java.util.Locale;
348fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
35aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song/**
36aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song * Manages the creation of {@link LauncherEvent}.
37aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song */
3864976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyalpublic class UserEventDispatcher {
3964976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal
4064976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal    private static final boolean DEBUG_LOGGING = false;
41ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
425aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song
43ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    /**
44ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song     * Implemented by containers to provide a launch source for a given child.
45ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song     */
46ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    public interface LaunchSourceProvider {
47ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
48ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        /**
49ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song         * Copies data from the source to the destination proto.
505aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song         *
515aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song         * @param v            source of the data
525aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song         * @param info         source of the data
535aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song         * @param target       dest of the data
545aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song         * @param targetParent dest of the data
55ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song         */
56ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent);
57ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    }
58ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
59ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    /**
60ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song     * Recursively finds the parent of the given child which implements IconLogInfoProvider
61ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song     */
62ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    public static LaunchSourceProvider getLaunchProviderRecursive(View v) {
63ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        ViewParent parent = null;
64ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        if (v != null) {
65ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song            parent = v.getParent();
66ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        } else {
67ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song            return null;
68ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        }
69ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
70ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        // Optimization to only check up to 5 parents.
71ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        int count = MAXIMUM_VIEW_HIERARCHY_LEVEL;
72ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        while (parent != null && count-- > 0) {
73ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song            if (parent instanceof LaunchSourceProvider) {
74ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song                return (LaunchSourceProvider) parent;
75ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song            } else {
76ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song                parent = parent.getParent();
77ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song            }
78ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        }
79ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        return null;
80ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    }
81ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
82aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song    private String TAG = "UserEvent";
838fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
848fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    private long mElapsedContainerMillis;
858fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    private long mElapsedSessionMillis;
868fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    private long mActionDurationMillis;
878fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
88ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // Used for filling in predictedRank on {@link Target}s.
89ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    private List<ComponentKey> mPredictedApps;
90ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
91ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    //                      APP_ICON    SHORTCUT    WIDGET
92ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // --------------------------------------------------------------
93ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // packageNameHash      required    optional    required
94ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // componentNameHash    required                required
95ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // intentHash                       required
96ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    // --------------------------------------------------------------
978fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
986470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song    protected LauncherEvent createLauncherEvent(View v, Intent intent) {
99ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        LauncherEvent event = LoggerUtils.initLauncherEvent(
1008ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                Action.TOUCH, v, Target.CONTAINER);
101ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        event.action.touch = Action.TAP;
1028fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
103ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        // Fill in grid(x,y), pageIndex of the child and container type of the parent
104ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        // TODO: make this percolate up the view hierarchy if needed.
105ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        int idx = 0;
106ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        LaunchSourceProvider provider = getLaunchProviderRecursive(v);
1078ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        if (!(v.getTag() instanceof ItemInfo)) {
1088ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            return null;
1098ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        }
1106470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        ItemInfo itemInfo = (ItemInfo) v.getTag();
1116470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        provider.fillInLaunchSourceData(v, itemInfo, event.srcTarget[idx], event.srcTarget[idx + 1]);
1126470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song
1136470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        event.srcTarget[idx].intentHash = intent.hashCode();
1146470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        ComponentName cn = intent.getComponent();
1156470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        if (cn != null) {
1166470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song            event.srcTarget[idx].packageNameHash = cn.getPackageName().hashCode();
1176470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song            event.srcTarget[idx].componentHash = cn.hashCode();
118373f5718f6ace627cfb17a4c9da2acfb9263c0f5Hyunyoung Song            if (mPredictedApps != null) {
119373f5718f6ace627cfb17a4c9da2acfb9263c0f5Hyunyoung Song                event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
120373f5718f6ace627cfb17a4c9da2acfb9263c0f5Hyunyoung Song                        new ComponentKey(cn, itemInfo.user));
121373f5718f6ace627cfb17a4c9da2acfb9263c0f5Hyunyoung Song            }
1226470cf449f1caf6a030e7ea93e785bb6ba414a59Hyunyoung Song        }
1238fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
124ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        // Fill in the duration of time spent navigating in Launcher and the container.
1258fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
1268fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
12746ab2276f97518e9ba71e4bf3109b8ebd924cbabSunny Goyal        return event;
12846ab2276f97518e9ba71e4bf3109b8ebd924cbabSunny Goyal    }
129ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
130aa953654279d7cca29682d85111e398ea1f20390Hyunyoung Song    public void logAppLaunch(View v, Intent intent) {
1318ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        LauncherEvent ev = createLauncherEvent(v, intent);
1328ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        if (ev == null) {
1338ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            return;
1348ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        }
1358ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        dispatchUserEvent(ev, intent);
136ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    }
137ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
1385aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song    public void logActionOnControl(int action, int controlType) {
1395aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.CONTROL);
1405aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.action.touch = action;
1415aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.srcTarget[0].controlType = controlType;
1425aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
1435aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
1445aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        dispatchUserEvent(event, null);
145ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    }
146ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
1475aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song    public void logActionOnContainer(int action, int dir, int containerType) {
1485aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.CONTAINER);
1495aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.action.touch = action;
1505aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.action.dir = dir;
1515aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.srcTarget[0].containerType = containerType;
1525aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
1535aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
1545aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song        dispatchUserEvent(event, null);
155ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    }
156ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song
157be06874c8105cf1beec8171235600da9f4ee035eTony Wickham    public void logDeepShortcutsOpen(View icon) {
15855c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham        LauncherEvent event = LoggerUtils.initLauncherEvent(
1598ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                Action.TOUCH, icon, Target.CONTAINER);
160be06874c8105cf1beec8171235600da9f4ee035eTony Wickham        LaunchSourceProvider provider = getLaunchProviderRecursive(icon);
1618ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        if (!(icon.getTag() instanceof ItemInfo)) {
1628ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            return;
1638ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song        }
164be06874c8105cf1beec8171235600da9f4ee035eTony Wickham        ItemInfo info = (ItemInfo) icon.getTag();
165be06874c8105cf1beec8171235600da9f4ee035eTony Wickham        provider.fillInLaunchSourceData(icon, info, event.srcTarget[0], event.srcTarget[1]);
166be06874c8105cf1beec8171235600da9f4ee035eTony Wickham        event.action.touch = Action.LONGPRESS;
16755c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham        event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
16855c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham        event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
16955c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham        dispatchUserEvent(event, null);
17055c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham    }
17155c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham
172ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song    public void setPredictedApps(List<ComponentKey> predictedApps) {
173ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song        mPredictedApps = predictedApps;
1748fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    }
1758fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
1768fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    /**
1778fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song     * Currently logs following containers: workspace, allapps, widget tray.
1788fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song     */
1798fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    public final void resetElapsedContainerMillis() {
1808fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        mElapsedContainerMillis = System.currentTimeMillis();
1818fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    }
1828fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
1838fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    public final void resetElapsedSessionMillis() {
1848fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        mElapsedSessionMillis = System.currentTimeMillis();
1858fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        mElapsedContainerMillis = System.currentTimeMillis();
1868fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    }
1878fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
1888fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    public final void resetActionDurationMillis() {
1898fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song        mActionDurationMillis = System.currentTimeMillis();
1908fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song    }
1918fd5e938d34ee84d076b5c5d2575cc6c46c254ceHyunyoung Song
19264976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal    public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
19364976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal        if (DEBUG_LOGGING) {
19455c6691e3a2e953dc9882ad0bc0a4c1ee2d42e67Tony Wickham            Log.d(TAG, String.format(Locale.US,
1958ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                    "\naction:%s\n Source child:%s\tparent:%s",
19664976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal                    LoggerUtils.getActionStr(ev.action),
1975aa2714959405043639cb2d0b8d9ab8c6eef0bd2Hyunyoung Song                    LoggerUtils.getTargetStr(ev.srcTarget != null ? ev.srcTarget[0] : null),
1988ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                    LoggerUtils.getTargetStr(ev.srcTarget.length > 1 ? ev.srcTarget[1] : null)));
1998ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            if (ev.destTarget != null && ev.destTarget.length > 0) {
2008ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                Log.d(TAG, String.format(Locale.US,
2018ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                        " Destination child:%s\tparent:%s",
2028ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                        LoggerUtils.getTargetStr(ev.destTarget != null ? ev.destTarget[0] : null),
2038ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                        LoggerUtils.getTargetStr(ev.destTarget.length > 1 ? ev.destTarget[1] : null)));
2048ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            }
2058ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song            Log.d(TAG, String.format(Locale.US,
2068ce6063c4a5bd90810f0a21c946e5bbad3ce9de4Hyunyoung Song                    " Elapsed container %d ms session %d ms",
20764976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal                    ev.elapsedContainerMillis,
20864976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal                    ev.elapsedSessionMillis));
20964976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal        }
21064976d5a5667f52ed3fe4346ea5ab910dcc2dc2dSunny Goyal    }
211ddec1c739ef37c3a042982b8943fe42e04b65f4cHyunyoung Song}
212