2016-04-12 18:32:04 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-03-04 11:02:40 -08:00
|
|
|
package com.android.launcher3.logging;
|
|
|
|
|
|
2016-05-10 16:59:55 -07:00
|
|
|
import android.content.ComponentName;
|
2016-04-12 18:32:04 -07:00
|
|
|
import android.content.Intent;
|
2016-09-01 12:47:12 -07:00
|
|
|
import android.os.SystemClock;
|
2016-06-20 14:56:28 -07:00
|
|
|
import android.util.Log;
|
2016-04-12 18:32:04 -07:00
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewParent;
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-09-01 12:47:12 -07:00
|
|
|
import com.android.launcher3.DropTarget;
|
2016-04-12 18:32:04 -07:00
|
|
|
import com.android.launcher3.ItemInfo;
|
2016-09-01 12:47:12 -07:00
|
|
|
import com.android.launcher3.Utilities;
|
|
|
|
|
import com.android.launcher3.config.ProviderConfig;
|
2016-04-15 13:01:40 -07:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
2016-04-12 18:32:04 -07:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
|
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
|
|
|
|
import com.android.launcher3.util.ComponentKey;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
2016-06-20 14:56:28 -07:00
|
|
|
import java.util.Locale;
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-04-19 18:30:24 -07:00
|
|
|
/**
|
|
|
|
|
* Manages the creation of {@link LauncherEvent}.
|
2016-09-27 18:07:00 -07:00
|
|
|
* To debug this class, execute following command before sideloading a new apk.
|
|
|
|
|
*
|
|
|
|
|
* $ adb shell setprop log.tag.UserEvent VERBOSE
|
2016-04-19 18:30:24 -07:00
|
|
|
*/
|
2016-06-20 14:56:28 -07:00
|
|
|
public class UserEventDispatcher {
|
|
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
|
2016-07-21 11:48:37 -07:00
|
|
|
|
2016-09-01 12:47:12 -07:00
|
|
|
private final boolean mIsVerbose;
|
|
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
/**
|
2016-09-01 12:47:12 -07:00
|
|
|
* TODO: change the name of this interface to LogContainerProvider
|
|
|
|
|
* and the method name to fillInLogContainerData. Not changed to minimize CL diff
|
|
|
|
|
* in this branch.
|
|
|
|
|
*
|
2016-04-12 18:32:04 -07:00
|
|
|
* Implemented by containers to provide a launch source for a given child.
|
|
|
|
|
*/
|
|
|
|
|
public interface LaunchSourceProvider {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Copies data from the source to the destination proto.
|
2016-07-21 11:48:37 -07:00
|
|
|
*
|
|
|
|
|
* @param v source of the data
|
|
|
|
|
* @param info source of the data
|
|
|
|
|
* @param target dest of the data
|
|
|
|
|
* @param targetParent dest of the data
|
2016-04-12 18:32:04 -07:00
|
|
|
*/
|
|
|
|
|
void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Recursively finds the parent of the given child which implements IconLogInfoProvider
|
|
|
|
|
*/
|
|
|
|
|
public static LaunchSourceProvider getLaunchProviderRecursive(View v) {
|
|
|
|
|
ViewParent parent = null;
|
2016-09-01 12:47:12 -07:00
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
if (v != null) {
|
|
|
|
|
parent = v.getParent();
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Optimization to only check up to 5 parents.
|
|
|
|
|
int count = MAXIMUM_VIEW_HIERARCHY_LEVEL;
|
|
|
|
|
while (parent != null && count-- > 0) {
|
|
|
|
|
if (parent instanceof LaunchSourceProvider) {
|
|
|
|
|
return (LaunchSourceProvider) parent;
|
|
|
|
|
} else {
|
|
|
|
|
parent = parent.getParent();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-19 18:30:24 -07:00
|
|
|
private String TAG = "UserEvent";
|
2016-03-08 16:55:47 -08:00
|
|
|
|
|
|
|
|
private long mElapsedContainerMillis;
|
|
|
|
|
private long mElapsedSessionMillis;
|
|
|
|
|
private long mActionDurationMillis;
|
|
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
// Used for filling in predictedRank on {@link Target}s.
|
|
|
|
|
private List<ComponentKey> mPredictedApps;
|
|
|
|
|
|
2016-09-01 12:47:12 -07:00
|
|
|
public UserEventDispatcher() {
|
|
|
|
|
if (ProviderConfig.IS_DOGFOOD_BUILD) {
|
|
|
|
|
mIsVerbose = Utilities.isPropertyEnabled(TAG);
|
|
|
|
|
} else {
|
|
|
|
|
mIsVerbose = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
// APP_ICON SHORTCUT WIDGET
|
|
|
|
|
// --------------------------------------------------------------
|
|
|
|
|
// packageNameHash required optional required
|
|
|
|
|
// componentNameHash required required
|
|
|
|
|
// intentHash required
|
|
|
|
|
// --------------------------------------------------------------
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-05-10 16:59:55 -07:00
|
|
|
protected LauncherEvent createLauncherEvent(View v, Intent intent) {
|
2016-04-12 18:32:04 -07:00
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(
|
2016-08-15 16:22:20 -07:00
|
|
|
Action.TOUCH, v, Target.CONTAINER);
|
2016-04-12 18:32:04 -07:00
|
|
|
event.action.touch = Action.TAP;
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
// Fill in grid(x,y), pageIndex of the child and container type of the parent
|
|
|
|
|
// TODO: make this percolate up the view hierarchy if needed.
|
|
|
|
|
int idx = 0;
|
|
|
|
|
LaunchSourceProvider provider = getLaunchProviderRecursive(v);
|
2016-09-01 12:47:12 -07:00
|
|
|
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
|
2016-08-15 16:22:20 -07:00
|
|
|
return null;
|
|
|
|
|
}
|
2016-05-10 16:59:55 -07:00
|
|
|
ItemInfo itemInfo = (ItemInfo) v.getTag();
|
|
|
|
|
provider.fillInLaunchSourceData(v, itemInfo, event.srcTarget[idx], event.srcTarget[idx + 1]);
|
|
|
|
|
|
|
|
|
|
event.srcTarget[idx].intentHash = intent.hashCode();
|
|
|
|
|
ComponentName cn = intent.getComponent();
|
|
|
|
|
if (cn != null) {
|
|
|
|
|
event.srcTarget[idx].packageNameHash = cn.getPackageName().hashCode();
|
|
|
|
|
event.srcTarget[idx].componentHash = cn.hashCode();
|
2016-05-11 11:26:01 -07:00
|
|
|
if (mPredictedApps != null) {
|
|
|
|
|
event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
|
|
|
|
|
new ComponentKey(cn, itemInfo.user));
|
|
|
|
|
}
|
2016-05-10 16:59:55 -07:00
|
|
|
}
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
// Fill in the duration of time spent navigating in Launcher and the container.
|
2016-09-01 12:47:12 -07:00
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
2016-04-15 13:01:40 -07:00
|
|
|
return event;
|
|
|
|
|
}
|
2016-04-12 18:32:04 -07:00
|
|
|
|
2016-04-19 18:30:24 -07:00
|
|
|
public void logAppLaunch(View v, Intent intent) {
|
2016-08-15 16:22:20 -07:00
|
|
|
LauncherEvent ev = createLauncherEvent(v, intent);
|
|
|
|
|
if (ev == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
dispatchUserEvent(ev, intent);
|
2016-04-12 18:32:04 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-27 18:07:00 -07:00
|
|
|
public void logActionOnItem(int action, int itemType) {
|
|
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.ITEM);
|
|
|
|
|
event.action.touch = action;
|
|
|
|
|
event.srcTarget[0].itemType = itemType;
|
|
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
|
|
|
|
dispatchUserEvent(event, null);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-21 11:48:37 -07:00
|
|
|
public void logActionOnControl(int action, int controlType) {
|
|
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.CONTROL);
|
|
|
|
|
event.action.touch = action;
|
|
|
|
|
event.srcTarget[0].controlType = controlType;
|
2016-09-01 12:47:12 -07:00
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
2016-07-21 11:48:37 -07:00
|
|
|
dispatchUserEvent(event, null);
|
2016-04-12 18:32:04 -07:00
|
|
|
}
|
|
|
|
|
|
2016-07-21 11:48:37 -07:00
|
|
|
public void logActionOnContainer(int action, int dir, int containerType) {
|
|
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.CONTAINER);
|
|
|
|
|
event.action.touch = action;
|
|
|
|
|
event.action.dir = dir;
|
|
|
|
|
event.srcTarget[0].containerType = containerType;
|
2016-09-01 12:47:12 -07:00
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
2016-07-21 11:48:37 -07:00
|
|
|
dispatchUserEvent(event, null);
|
2016-04-12 18:32:04 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-10 16:06:22 -07:00
|
|
|
public void logDeepShortcutsOpen(View icon) {
|
2016-08-01 16:42:19 -07:00
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(
|
2016-08-15 16:22:20 -07:00
|
|
|
Action.TOUCH, icon, Target.CONTAINER);
|
2016-08-10 16:06:22 -07:00
|
|
|
LaunchSourceProvider provider = getLaunchProviderRecursive(icon);
|
2016-09-01 12:47:12 -07:00
|
|
|
if (icon == null && !(icon.getTag() instanceof ItemInfo)) {
|
2016-08-15 16:22:20 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2016-08-10 16:06:22 -07:00
|
|
|
ItemInfo info = (ItemInfo) icon.getTag();
|
|
|
|
|
provider.fillInLaunchSourceData(icon, info, event.srcTarget[0], event.srcTarget[1]);
|
|
|
|
|
event.action.touch = Action.LONGPRESS;
|
2016-09-01 12:47:12 -07:00
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
2016-08-01 16:42:19 -07:00
|
|
|
dispatchUserEvent(event, null);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 18:32:04 -07:00
|
|
|
public void setPredictedApps(List<ComponentKey> predictedApps) {
|
|
|
|
|
mPredictedApps = predictedApps;
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-01 12:47:12 -07:00
|
|
|
public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
|
|
|
|
|
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH,
|
|
|
|
|
dragObj.dragView,
|
|
|
|
|
dragObj.originalDragInfo,
|
|
|
|
|
Target.CONTAINER,
|
|
|
|
|
dropTargetAsView);
|
|
|
|
|
event.action.touch = Action.DRAGDROP;
|
|
|
|
|
|
|
|
|
|
dragObj.dragSource.fillInLaunchSourceData(null, dragObj.originalDragInfo,
|
|
|
|
|
event.srcTarget[0], event.srcTarget[1]);
|
|
|
|
|
|
|
|
|
|
if (dropTargetAsView instanceof LaunchSourceProvider) {
|
|
|
|
|
((LaunchSourceProvider) dropTargetAsView).fillInLaunchSourceData(null,
|
|
|
|
|
dragObj.dragInfo, event.destTarget[0], event.destTarget[1]);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
event.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
|
|
|
|
|
event.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
|
|
|
|
|
event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis;
|
|
|
|
|
dispatchUserEvent(event, null);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 16:55:47 -08:00
|
|
|
/**
|
|
|
|
|
* Currently logs following containers: workspace, allapps, widget tray.
|
|
|
|
|
*/
|
|
|
|
|
public final void resetElapsedContainerMillis() {
|
2016-09-01 12:47:12 -07:00
|
|
|
mElapsedContainerMillis = SystemClock.uptimeMillis();
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public final void resetElapsedSessionMillis() {
|
2016-09-01 12:47:12 -07:00
|
|
|
mElapsedSessionMillis = SystemClock.uptimeMillis();
|
|
|
|
|
mElapsedContainerMillis = SystemClock.uptimeMillis();
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public final void resetActionDurationMillis() {
|
2016-09-01 12:47:12 -07:00
|
|
|
mActionDurationMillis = SystemClock.uptimeMillis();
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
|
|
|
|
|
2016-06-20 14:56:28 -07:00
|
|
|
public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
|
2016-09-01 12:47:12 -07:00
|
|
|
if (!mIsVerbose) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Log.d(TAG, String.format(Locale.US,
|
|
|
|
|
"\naction:%s\n Source child:%s\tparent:%s",
|
|
|
|
|
LoggerUtils.getActionStr(ev.action),
|
|
|
|
|
LoggerUtils.getTargetStr(ev.srcTarget != null ? ev.srcTarget[0] : null),
|
|
|
|
|
LoggerUtils.getTargetStr(ev.srcTarget != null && ev.srcTarget.length > 1 ?
|
|
|
|
|
ev.srcTarget[1] : null)));
|
|
|
|
|
if (ev.destTarget != null && ev.destTarget.length > 0) {
|
2016-08-15 16:22:20 -07:00
|
|
|
Log.d(TAG, String.format(Locale.US,
|
2016-09-01 12:47:12 -07:00
|
|
|
" Destination child:%s\tparent:%s",
|
|
|
|
|
LoggerUtils.getTargetStr(ev.destTarget != null ? ev.destTarget[0] : null),
|
|
|
|
|
LoggerUtils.getTargetStr(ev.destTarget != null && ev.destTarget.length > 1 ?
|
|
|
|
|
ev.destTarget[1] : null)));
|
2016-06-20 14:56:28 -07:00
|
|
|
}
|
2016-09-01 12:47:12 -07:00
|
|
|
Log.d(TAG, String.format(Locale.US,
|
|
|
|
|
" Elapsed container %d ms session %d ms action %d ms",
|
|
|
|
|
ev.elapsedContainerMillis,
|
|
|
|
|
ev.elapsedSessionMillis,
|
|
|
|
|
ev.actionDurationMillis));
|
2016-06-20 14:56:28 -07:00
|
|
|
}
|
2016-04-12 18:32:04 -07:00
|
|
|
}
|