2017-02-06 10:46:24 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2016 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-08 16:55:47 -08:00
|
|
|
package com.android.launcher3.logging;
|
|
|
|
|
|
2019-04-02 11:18:06 -07:00
|
|
|
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
|
|
|
|
|
|
2016-11-23 02:24:32 +05:30
|
|
|
import android.util.ArrayMap;
|
|
|
|
|
import android.util.SparseArray;
|
2016-08-15 16:22:20 -07:00
|
|
|
import android.view.View;
|
|
|
|
|
|
2018-03-29 21:12:12 +02:00
|
|
|
import com.android.launcher3.AppInfo;
|
2016-09-01 12:47:12 -07:00
|
|
|
import com.android.launcher3.ButtonDropTarget;
|
2016-08-15 16:22:20 -07:00
|
|
|
import com.android.launcher3.ItemInfo;
|
|
|
|
|
import com.android.launcher3.LauncherSettings;
|
2017-07-19 01:24:07 -07:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension;
|
2016-03-08 16:55:47 -08:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
2016-11-23 02:24:32 +05:30
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
|
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
|
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
|
2016-11-22 23:49:52 +05:30
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
2016-03-08 16:55:47 -08:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
2018-05-09 16:18:58 -07:00
|
|
|
import com.android.launcher3.userevent.nano.LauncherLogProto.TipType;
|
2018-03-29 21:12:12 +02:00
|
|
|
import com.android.launcher3.util.InstantAppResolver;
|
2016-03-08 16:55:47 -08:00
|
|
|
|
2016-11-23 02:24:32 +05:30
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.lang.reflect.Modifier;
|
|
|
|
|
|
2016-03-08 16:55:47 -08:00
|
|
|
/**
|
2016-11-23 02:24:32 +05:30
|
|
|
* Helper methods for logging.
|
2016-03-08 16:55:47 -08:00
|
|
|
*/
|
|
|
|
|
public class LoggerUtils {
|
2016-11-23 02:24:32 +05:30
|
|
|
private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
|
|
|
|
|
private static final String UNKNOWN = "UNKNOWN";
|
2019-11-11 15:55:27 -08:00
|
|
|
private static final int DEFAULT_PREDICTED_RANK = -100;
|
2016-11-23 02:24:32 +05:30
|
|
|
|
2017-02-06 10:46:24 -08:00
|
|
|
public static String getFieldName(int value, Class c) {
|
2016-11-23 02:24:32 +05:30
|
|
|
SparseArray<String> cache;
|
|
|
|
|
synchronized (sNameCache) {
|
|
|
|
|
cache = sNameCache.get(c);
|
|
|
|
|
if (cache == null) {
|
|
|
|
|
cache = new SparseArray<>();
|
|
|
|
|
for (Field f : c.getDeclaredFields()) {
|
|
|
|
|
if (f.getType() == int.class && Modifier.isStatic(f.getModifiers())) {
|
|
|
|
|
try {
|
|
|
|
|
f.setAccessible(true);
|
|
|
|
|
cache.put(f.getInt(null), f.getName());
|
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
|
// Ignore
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sNameCache.put(c, cache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String result = cache.get(value);
|
|
|
|
|
return result != null ? result : UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static String getActionStr(Action action) {
|
2017-06-29 16:42:04 -07:00
|
|
|
String str = "";
|
2016-10-06 10:53:29 -07:00
|
|
|
switch (action.type) {
|
2017-06-29 16:42:04 -07:00
|
|
|
case Action.Type.TOUCH:
|
|
|
|
|
str += getFieldName(action.touch, Action.Touch.class);
|
Quick step/scrub/switch logging
- state transition happening due to Home and back is handled by
specifying src target as 'from' container and dst target as the 'to'
container
- Source and Destination container shows FROM and TO state for SWIPE/FLING
- event.isStateChange = true indicates that an action resulted in
state transition
- Elapsed container millis is the screen time on the source container
Bug: 70181187
- logcat printout with setprop log.tag.UserEvent VERBOSE
1) State: WORKSPACE -> ALLAPPS
action:FLING direction=UP
Source child:HOTSEAT id=0 parent:WORKSPACE id=0
Destination child:ALLAPPS
Elapsed container 1225 ms, session 1225 ms, action 0 ms
2) ALLAPPS -> HOMESCREEN
action:FLING direction=DOWN
Source child:ALLAPPS parent:ALLAPPS
Destination child:WORKSPACE id=0
Elapsed container 971 ms, session 2197 ms, action 0 ms
3) HOMESCREEN -> OVERVIEW
action:FLING direction=UP
Source child:NAVBAR parent:WORKSPACE id=0
Destination child:TASKSWITCHER
Elapsed container 4834 ms, session 4834 ms, action 0 ms
4) OVERVIEW-> ALLAPPS
action:FLING direction=UP
Source child:TASK parent:TASKSWITCHER
Destination child:ALLAPPS
Elapsed container 2176 ms, session 7010 ms, action 0 ms
5) ALLAPPS->OVERVIEW
action:FLING direction=DOWN
Source child:ALLAPPS parent:ALLAPPS
Destination child:TASKSWITCHER
Elapsed container 3683 ms, session 10693 ms, action 0 ms
6) OVERVIEW-> HOMESCREEN
action:FLING direction=DOWN
Source child:TASK parent:TASKSWITCHER
Destination child:WORKSPACE id=0
Elapsed container 2108 ms, session 12801 ms, action 0 ms
7) APPS-> OVERVIEW
action:FLING direction=UP
Source child:NAVBAR parent:APP
Destination child:TASKSWITCHER
Elapsed container 104 ms, session 104 ms, action 0 ms
8) Quickscrub: action:DRAGANDDROP Source child: QUICK
9) Quickswitch: action:FLING Source child: QUICK
Change-Id: I5898230859ff600f48a2a873a40b670fe4d39a0d
2018-02-14 13:40:25 -08:00
|
|
|
if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING) {
|
2017-06-29 16:42:04 -07:00
|
|
|
str += " direction=" + getFieldName(action.dir, Action.Direction.class);
|
|
|
|
|
}
|
2019-04-24 11:32:20 -07:00
|
|
|
break;
|
|
|
|
|
case Action.Type.COMMAND:
|
|
|
|
|
str += getFieldName(action.command, Action.Command.class);
|
|
|
|
|
break;
|
2018-05-09 16:18:58 -07:00
|
|
|
default: return getFieldName(action.type, Action.Type.class);
|
2016-10-06 10:53:29 -07:00
|
|
|
}
|
2019-04-24 11:32:20 -07:00
|
|
|
if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING ||
|
|
|
|
|
(action.command == Action.Command.BACK && action.dir != Action.Direction.NONE)) {
|
|
|
|
|
str += " direction=" + getFieldName(action.dir, Action.Direction.class);
|
|
|
|
|
}
|
|
|
|
|
return str;
|
2016-10-06 10:53:29 -07:00
|
|
|
}
|
|
|
|
|
|
2016-03-08 16:55:47 -08:00
|
|
|
public static String getTargetStr(Target t) {
|
2019-11-06 15:43:30 -08:00
|
|
|
if (t == null) {
|
2016-11-23 02:24:32 +05:30
|
|
|
return "";
|
2016-07-21 11:48:37 -07:00
|
|
|
}
|
2018-05-09 16:18:58 -07:00
|
|
|
String str = "";
|
2016-03-08 16:55:47 -08:00
|
|
|
switch (t.type) {
|
2016-11-23 02:24:32 +05:30
|
|
|
case Target.Type.ITEM:
|
2018-05-09 16:18:58 -07:00
|
|
|
str = getItemStr(t);
|
|
|
|
|
break;
|
2016-11-23 02:24:32 +05:30
|
|
|
case Target.Type.CONTROL:
|
2018-05-09 16:18:58 -07:00
|
|
|
str = getFieldName(t.controlType, ControlType.class);
|
|
|
|
|
break;
|
2016-11-23 02:24:32 +05:30
|
|
|
case Target.Type.CONTAINER:
|
2018-05-09 16:18:58 -07:00
|
|
|
str = getFieldName(t.containerType, ContainerType.class);
|
2017-10-17 15:39:46 -07:00
|
|
|
if (t.containerType == ContainerType.WORKSPACE ||
|
2019-04-02 11:18:06 -07:00
|
|
|
t.containerType == ContainerType.HOTSEAT ||
|
|
|
|
|
t.containerType == NAVBAR) {
|
2017-02-06 10:46:24 -08:00
|
|
|
str += " id=" + t.pageIndex;
|
|
|
|
|
} else if (t.containerType == ContainerType.FOLDER) {
|
2019-04-24 11:32:20 -07:00
|
|
|
str += " grid(" + t.gridX + "," + t.gridY + ")";
|
2017-02-06 10:46:24 -08:00
|
|
|
}
|
2018-05-09 16:18:58 -07:00
|
|
|
break;
|
2016-03-08 16:55:47 -08:00
|
|
|
default:
|
2018-05-09 16:18:58 -07:00
|
|
|
str += "UNKNOWN TARGET TYPE";
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
2018-05-09 16:18:58 -07:00
|
|
|
|
2019-04-24 11:32:20 -07:00
|
|
|
if (t.spanX != 1 || t.spanY != 1) {
|
|
|
|
|
str += " span(" + t.spanX + "," + t.spanY + ")";
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-09 16:18:58 -07:00
|
|
|
if (t.tipType != TipType.DEFAULT_NONE) {
|
|
|
|
|
str += " " + getFieldName(t.tipType, TipType.class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str;
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static String getItemStr(Target t) {
|
2016-11-23 02:24:32 +05:30
|
|
|
String typeStr = getFieldName(t.itemType, ItemType.class);
|
2016-08-15 16:22:20 -07:00
|
|
|
if (t.packageNameHash != 0) {
|
2017-10-17 15:39:46 -07:00
|
|
|
typeStr += ", packageHash=" + t.packageNameHash;
|
2016-08-15 16:22:20 -07:00
|
|
|
}
|
|
|
|
|
if (t.componentHash != 0) {
|
2017-10-17 15:39:46 -07:00
|
|
|
typeStr += ", componentHash=" + t.componentHash;
|
2016-08-15 16:22:20 -07:00
|
|
|
}
|
|
|
|
|
if (t.intentHash != 0) {
|
2017-10-17 15:39:46 -07:00
|
|
|
typeStr += ", intentHash=" + t.intentHash;
|
|
|
|
|
}
|
2019-11-06 15:43:30 -08:00
|
|
|
if (t.itemType == ItemType.FOLDER_ICON) {
|
|
|
|
|
typeStr += ", grid(" + t.gridX + "," + t.gridY + ")";
|
|
|
|
|
} else if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0)
|
|
|
|
|
&& t.itemType != ItemType.TASK) {
|
2019-12-10 13:23:51 -08:00
|
|
|
typeStr +=
|
|
|
|
|
", isWorkApp=" + t.isWorkApp + ", predictiveRank=" + t.predictedRank + ", grid("
|
|
|
|
|
+ t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
|
|
|
|
|
+ "), pageIdx=" + t.pageIndex;
|
2016-08-15 16:22:20 -07:00
|
|
|
}
|
2019-05-06 21:20:07 -07:00
|
|
|
if (t.searchQueryLength != 0) {
|
|
|
|
|
typeStr += ", searchQueryLength=" + t.searchQueryLength;
|
|
|
|
|
}
|
2018-05-15 21:46:51 -07:00
|
|
|
if (t.itemType == ItemType.TASK) {
|
|
|
|
|
typeStr += ", pageIdx=" + t.pageIndex;
|
|
|
|
|
}
|
Quick step/scrub/switch logging
- state transition happening due to Home and back is handled by
specifying src target as 'from' container and dst target as the 'to'
container
- Source and Destination container shows FROM and TO state for SWIPE/FLING
- event.isStateChange = true indicates that an action resulted in
state transition
- Elapsed container millis is the screen time on the source container
Bug: 70181187
- logcat printout with setprop log.tag.UserEvent VERBOSE
1) State: WORKSPACE -> ALLAPPS
action:FLING direction=UP
Source child:HOTSEAT id=0 parent:WORKSPACE id=0
Destination child:ALLAPPS
Elapsed container 1225 ms, session 1225 ms, action 0 ms
2) ALLAPPS -> HOMESCREEN
action:FLING direction=DOWN
Source child:ALLAPPS parent:ALLAPPS
Destination child:WORKSPACE id=0
Elapsed container 971 ms, session 2197 ms, action 0 ms
3) HOMESCREEN -> OVERVIEW
action:FLING direction=UP
Source child:NAVBAR parent:WORKSPACE id=0
Destination child:TASKSWITCHER
Elapsed container 4834 ms, session 4834 ms, action 0 ms
4) OVERVIEW-> ALLAPPS
action:FLING direction=UP
Source child:TASK parent:TASKSWITCHER
Destination child:ALLAPPS
Elapsed container 2176 ms, session 7010 ms, action 0 ms
5) ALLAPPS->OVERVIEW
action:FLING direction=DOWN
Source child:ALLAPPS parent:ALLAPPS
Destination child:TASKSWITCHER
Elapsed container 3683 ms, session 10693 ms, action 0 ms
6) OVERVIEW-> HOMESCREEN
action:FLING direction=DOWN
Source child:TASK parent:TASKSWITCHER
Destination child:WORKSPACE id=0
Elapsed container 2108 ms, session 12801 ms, action 0 ms
7) APPS-> OVERVIEW
action:FLING direction=UP
Source child:NAVBAR parent:APP
Destination child:TASKSWITCHER
Elapsed container 104 ms, session 104 ms, action 0 ms
8) Quickscrub: action:DRAGANDDROP Source child: QUICK
9) Quickswitch: action:FLING Source child: QUICK
Change-Id: I5898230859ff600f48a2a873a40b670fe4d39a0d
2018-02-14 13:40:25 -08:00
|
|
|
return typeStr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Target newItemTarget(int itemType) {
|
|
|
|
|
Target t = newTarget(Target.Type.ITEM);
|
|
|
|
|
t.itemType = itemType;
|
|
|
|
|
return t;
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|
2016-04-12 18:32:04 -07:00
|
|
|
|
2018-03-29 21:12:12 +02:00
|
|
|
public static Target newItemTarget(View v, InstantAppResolver instantAppResolver) {
|
2018-07-03 15:53:39 -07:00
|
|
|
return (v != null) && (v.getTag() instanceof ItemInfo)
|
2018-03-29 21:12:12 +02:00
|
|
|
? newItemTarget((ItemInfo) v.getTag(), instantAppResolver)
|
2016-11-23 02:24:32 +05:30
|
|
|
: newTarget(Target.Type.ITEM);
|
2016-09-01 12:47:12 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-29 21:12:12 +02:00
|
|
|
public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) {
|
2016-11-23 02:24:32 +05:30
|
|
|
Target t = newTarget(Target.Type.ITEM);
|
2016-09-01 12:47:12 -07:00
|
|
|
switch (info.itemType) {
|
2016-08-15 16:22:20 -07:00
|
|
|
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
|
2018-03-29 21:12:12 +02:00
|
|
|
t.itemType = (instantAppResolver != null && info instanceof AppInfo
|
2019-11-06 15:43:30 -08:00
|
|
|
&& instantAppResolver.isInstantApp(((AppInfo) info)))
|
2018-03-29 21:12:12 +02:00
|
|
|
? ItemType.WEB_APP
|
|
|
|
|
: ItemType.APP_ICON;
|
2019-11-11 15:55:27 -08:00
|
|
|
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
2016-08-15 16:22:20 -07:00
|
|
|
break;
|
|
|
|
|
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
2016-11-23 02:24:32 +05:30
|
|
|
t.itemType = ItemType.SHORTCUT;
|
2019-11-11 15:55:27 -08:00
|
|
|
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
2016-08-15 16:22:20 -07:00
|
|
|
break;
|
|
|
|
|
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
|
2016-11-23 02:24:32 +05:30
|
|
|
t.itemType = ItemType.FOLDER_ICON;
|
2016-08-15 16:22:20 -07:00
|
|
|
break;
|
|
|
|
|
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
2016-11-23 02:24:32 +05:30
|
|
|
t.itemType = ItemType.WIDGET;
|
2016-08-15 16:22:20 -07:00
|
|
|
break;
|
|
|
|
|
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
2016-11-23 02:24:32 +05:30
|
|
|
t.itemType = ItemType.DEEPSHORTCUT;
|
2019-11-11 15:55:27 -08:00
|
|
|
t.predictedRank = DEFAULT_PREDICTED_RANK;
|
2016-08-15 16:22:20 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return t;
|
|
|
|
|
}
|
2016-09-01 12:47:12 -07:00
|
|
|
|
2016-11-22 23:49:52 +05:30
|
|
|
public static Target newDropTarget(View v) {
|
|
|
|
|
if (!(v instanceof ButtonDropTarget)) {
|
2016-11-23 02:24:32 +05:30
|
|
|
return newTarget(Target.Type.CONTAINER);
|
2016-09-01 12:47:12 -07:00
|
|
|
}
|
2018-03-05 19:39:21 +00:00
|
|
|
if (v instanceof ButtonDropTarget) {
|
2018-05-01 19:26:05 -07:00
|
|
|
return ((ButtonDropTarget) v).getDropTargetForLogging();
|
2016-09-01 12:47:12 -07:00
|
|
|
}
|
2018-05-01 19:26:05 -07:00
|
|
|
return newTarget(Target.Type.CONTROL);
|
2017-07-19 01:24:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Target newTarget(int targetType, TargetExtension extension) {
|
|
|
|
|
Target t = new Target();
|
|
|
|
|
t.type = targetType;
|
|
|
|
|
t.extension = extension;
|
|
|
|
|
return t;
|
2016-09-01 12:47:12 -07:00
|
|
|
}
|
|
|
|
|
|
2016-11-22 23:49:52 +05:30
|
|
|
public static Target newTarget(int targetType) {
|
2016-11-23 02:24:32 +05:30
|
|
|
Target t = new Target();
|
2016-11-22 23:49:52 +05:30
|
|
|
t.type = targetType;
|
|
|
|
|
return t;
|
|
|
|
|
}
|
2018-05-01 19:26:05 -07:00
|
|
|
|
2018-05-09 16:18:58 -07:00
|
|
|
public static Target newControlTarget(int controlType) {
|
|
|
|
|
Target t = newTarget(Target.Type.CONTROL);
|
|
|
|
|
t.controlType = controlType;
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-22 23:49:52 +05:30
|
|
|
public static Target newContainerTarget(int containerType) {
|
2016-11-23 02:24:32 +05:30
|
|
|
Target t = newTarget(Target.Type.CONTAINER);
|
2016-11-22 23:49:52 +05:30
|
|
|
t.containerType = containerType;
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Action newAction(int type) {
|
|
|
|
|
Action a = new Action();
|
|
|
|
|
a.type = type;
|
|
|
|
|
return a;
|
|
|
|
|
}
|
2018-05-01 19:26:05 -07:00
|
|
|
|
2016-11-22 23:49:52 +05:30
|
|
|
public static Action newCommandAction(int command) {
|
2016-11-23 02:24:32 +05:30
|
|
|
Action a = newAction(Action.Type.COMMAND);
|
2016-11-22 23:49:52 +05:30
|
|
|
a.command = command;
|
|
|
|
|
return a;
|
|
|
|
|
}
|
2018-05-01 19:26:05 -07:00
|
|
|
|
2016-11-22 23:49:52 +05:30
|
|
|
public static Action newTouchAction(int touch) {
|
2016-11-23 02:24:32 +05:30
|
|
|
Action a = newAction(Action.Type.TOUCH);
|
2016-11-22 23:49:52 +05:30
|
|
|
a.touch = touch;
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static LauncherEvent newLauncherEvent(Action action, Target... srcTargets) {
|
2016-11-23 02:24:32 +05:30
|
|
|
LauncherEvent event = new LauncherEvent();
|
2016-11-22 23:49:52 +05:30
|
|
|
event.srcTarget = srcTargets;
|
|
|
|
|
event.action = action;
|
|
|
|
|
return event;
|
2016-09-01 12:47:12 -07:00
|
|
|
}
|
2016-03-08 16:55:47 -08:00
|
|
|
}
|