Added logging for HOME_INTENT and BACK commands.

Document: go/false-longpress-overview

Change-Id: If6ba4996c861a44f4950b41acb4246e3a483d8f2
This commit is contained in:
Jon Miranda 2016-10-06 10:53:29 -07:00
parent 0860e41d50
commit feba90fe80
6 changed files with 146 additions and 38 deletions

View File

@ -63,6 +63,7 @@ enum ItemType {
FOLDER_ICON = 4;
DEEPSHORTCUT = 5;
SEARCHBOX = 6;
EDITTEXT = 7;
}
// Used to define what type of container a Target would represent.
@ -91,7 +92,9 @@ enum ControlType {
APPINFO_TARGET = 7;
RESIZE_HANDLE = 8;
VERTICAL_SCROLL = 9;
// HOME, BACK, GO_TO_PLAYSTORE
HOME_INTENT = 10; // Deprecated, use enum Command instead
BACK_BUTTON = 11; // Deprecated, use enum Command instead
// GO_TO_PLAYSTORE
}
// Used to define the action component of the LauncherEvent.
@ -99,6 +102,7 @@ message Action {
enum Type {
TOUCH = 0;
AUTOMATED = 1;
COMMAND = 2;
// SOFT_KEYBOARD, HARD_KEYBOARD, ASSIST
}
enum Touch {
@ -116,9 +120,16 @@ message Action {
LEFT = 3;
RIGHT = 4;
}
enum Command {
HOME_INTENT = 0;
BACK = 1;
}
optional Type type = 1;
optional Touch touch = 2;
optional Direction dir = 3;
optional Command command = 4;
// Log if the action was performed on outside of the container
optional bool is_outside = 5;
}
//

View File

@ -1681,9 +1681,27 @@ public class Launcher extends Activity
// Can be cases where mWorkspace is null, this prevents a NPE
return;
}
// In all these cases, only animate if we're already on home
// Note: There should be at most one log per method call. This is enforced implicitly
// by using if-else statements.
UserEventDispatcher ued = getUserEventDispatcher();
// TODO: Log this case.
mWorkspace.exitWidgetResizeMode();
AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this);
if (topOpenView instanceof DeepShortcutsContainer) {
ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
topOpenView.getExtendedTouchView(), LauncherLogProto.DEEPSHORTCUTS);
} else if (topOpenView instanceof Folder) {
ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
((Folder) topOpenView).getFolderIcon(), LauncherLogProto.FOLDER);
} else if (alreadyOnHome) {
ued.logActionCommand(LauncherLogProto.Action.HOME_INTENT,
mWorkspace.getState().containerType, mWorkspace.getCurrentPage());
}
// In all these cases, only animate if we're already on home
AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
exitSpringLoadedDragMode();
@ -2187,20 +2205,34 @@ public class Launcher extends Activity
return;
}
// Note: There should be at most one log per method call. This is enforced implicitly
// by using if-else statements.
UserEventDispatcher ued = getUserEventDispatcher();
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
if (topView != null) {
if (topView.getActiveTextView() != null) {
topView.getActiveTextView().dispatchBackKey();
} else {
if (topView instanceof DeepShortcutsContainer) {
ued.logActionCommand(LauncherLogProto.Action.BACK,
topView.getExtendedTouchView(), LauncherLogProto.DEEPSHORTCUTS);
} else if (topView instanceof Folder) {
ued.logActionCommand(LauncherLogProto.Action.BACK,
((Folder) topView).getFolderIcon(), LauncherLogProto.FOLDER);
}
topView.close(true);
}
} else if (isAppsViewVisible()) {
ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.ALLAPPS);
showWorkspace(true);
} else if (isWidgetsViewVisible()) {
ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.WIDGETS);
showOverviewMode(true);
} else if (mWorkspace.isInOverviewMode()) {
ued.logActionCommand(LauncherLogProto.Action.BACK, LauncherLogProto.OVERVIEW);
showWorkspace(true);
} else {
// TODO: Log this case.
mWorkspace.exitWidgetResizeMode();
// Back button is a no-op here, but give at least some feedback for the button press

View File

@ -183,18 +183,20 @@ public class Workspace extends PagedView
// in all apps or customize mode)
public enum State {
NORMAL (false, false),
NORMAL_HIDDEN (false, false),
SPRING_LOADED (false, true),
OVERVIEW (true, true),
OVERVIEW_HIDDEN (true, false);
NORMAL (false, false, LauncherLogProto.WORKSPACE),
NORMAL_HIDDEN (false, false, LauncherLogProto.ALLAPPS),
SPRING_LOADED (false, true, LauncherLogProto.WORKSPACE),
OVERVIEW (true, true, LauncherLogProto.OVERVIEW),
OVERVIEW_HIDDEN (true, false, LauncherLogProto.WIDGETS);
public final boolean shouldUpdateWidget;
public final boolean hasMultipleVisiblePages;
public final int containerType;
State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages) {
State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages, int containerType) {
this.shouldUpdateWidget = shouldUpdateWidget;
this.hasMultipleVisiblePages = hasMultipleVisiblePages;
this.containerType = containerType;
}
}

View File

@ -79,7 +79,6 @@ import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.shortcuts.DeepShortcutsContainer;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.CircleRevealOutlineProvider;
@ -388,6 +387,10 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
return isEditingName() ? mFolderName : null;
}
public FolderIcon getFolderIcon() {
return mFolderIcon;
}
/**
* We need to handle touch events to prevent them from falling through to the workspace below.
*/

View File

@ -20,8 +20,16 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
public class LoggerUtils {
private static final String TAG = "LoggerUtils";
public static String getActionStr(LauncherLogProto.Action action) {
switch(action.touch) {
private static String getCommandStr(Action action) {
switch (action.command) {
case Action.HOME_INTENT: return "HOME_INTENT";
case Action.BACK: return "BACK";
default: return "UNKNOWN";
}
}
private static String getTouchStr(Action action) {
switch (action.touch) {
case Action.TAP: return "TAP";
case Action.LONGPRESS: return "LONGPRESS";
case Action.DRAGDROP: return "DRAGDROP";
@ -32,6 +40,14 @@ public class LoggerUtils {
}
}
public static String getActionStr(LauncherLogProto.Action action) {
switch (action.type) {
case Action.TOUCH: return getTouchStr(action);
case Action.COMMAND: return getCommandStr(action);
default: return "UNKNOWN";
}
}
public static String getTargetStr(Target t) {
String typeStr = "";
if (t == null){
@ -61,6 +77,7 @@ public class LoggerUtils {
case LauncherLogProto.DEEPSHORTCUT: typeStr = "DEEPSHORTCUT"; break;
case LauncherLogProto.FOLDER_ICON: typeStr = "FOLDERICON"; break;
case LauncherLogProto.SEARCHBOX: typeStr = "SEARCHBOX"; break;
case LauncherLogProto.EDITTEXT: typeStr = "EDITTEXT"; break;
default: typeStr = "UNKNOWN";
}
@ -172,24 +189,42 @@ public class LoggerUtils {
return event;
}
/**
* Used for commands.
*/
public static LauncherLogProto.LauncherEvent initLauncherEvent(int command,
boolean createSrcTarget) {
LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
event.action = new LauncherLogProto.Action();
event.action.type = Action.COMMAND;
event.action.command = command;
event.srcTarget = null;
if (createSrcTarget) {
event.srcTarget = new LauncherLogProto.Target[1];
event.srcTarget[0] = new LauncherLogProto.Target();
event.srcTarget[0].type = Target.CONTAINER;
}
return event;
}
/**
* Used for drag and drop interaction.
*/
public static LauncherLogProto.LauncherEvent initLauncherEvent(
int actionType,
View v,
ItemInfo info,
int parentSrcTargetType,
View parentDestTargetType){
LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
event.srcTarget = new LauncherLogProto.Target[2];
event.srcTarget[0] = initTarget(v, info);
event.srcTarget[0] = initTarget(info);
event.srcTarget[1] = new LauncherLogProto.Target();
event.srcTarget[1].type = parentSrcTargetType;
event.destTarget = new LauncherLogProto.Target[2];
event.destTarget[0] = initTarget(v, info);
event.destTarget[0] = initTarget(info);
event.destTarget[1] = initDropTarget(parentDestTargetType);
event.action = new LauncherLogProto.Action();
@ -197,7 +232,7 @@ public class LoggerUtils {
return event;
}
private static Target initTarget(View v, ItemInfo info) {
private static Target initTarget(ItemInfo info) {
Target t = new LauncherLogProto.Target();
t.type = Target.ITEM;
switch (info.itemType) {
@ -243,6 +278,6 @@ public class LoggerUtils {
if (!(v.getTag() instanceof ItemInfo)) {
return t;
}
return initTarget(v, (ItemInfo) v.getTag());
return initTarget((ItemInfo) v.getTag());
}
}

View File

@ -117,29 +117,35 @@ public class UserEventDispatcher {
Action.TOUCH, v, Target.CONTAINER);
event.action.touch = Action.TAP;
// 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.
// TODO: make idx percolate up the view hierarchy if needed.
int idx = 0;
LogContainerProvider provider = getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
return null;
}
ItemInfo itemInfo = (ItemInfo) v.getTag();
provider.fillInLogContainerData(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();
if (mPredictedApps != null) {
event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
new ComponentKey(cn, itemInfo.user));
if (fillInLogContainerData(event, v)) {
ItemInfo itemInfo = (ItemInfo) v.getTag();
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();
if (mPredictedApps != null) {
event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
new ComponentKey(cn, itemInfo.user));
}
}
}
return event;
}
public boolean fillInLogContainerData(LauncherEvent event, View v) {
// Fill in grid(x,y), pageIndex of the child and container type of the parent
LogContainerProvider provider = getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
return false;
}
ItemInfo itemInfo = (ItemInfo) v.getTag();
provider.fillInLogContainerData(v, itemInfo, event.srcTarget[0], event.srcTarget[1]);
return true;
}
public void logAppLaunch(View v, Intent intent) {
LauncherEvent ev = createLauncherEvent(v, intent);
if (ev == null) {
@ -148,10 +154,30 @@ public class UserEventDispatcher {
dispatchUserEvent(ev, intent);
}
public void logActionOnItem(int action, int itemType) {
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH, Target.ITEM);
event.action.touch = action;
event.srcTarget[0].itemType = itemType;
public void logActionCommand(int command, int containerType) {
logActionCommand(command, containerType, 0);
}
public void logActionCommand(int command, int containerType, int pageIndex) {
LauncherEvent event = LoggerUtils.initLauncherEvent(command, true);
event.srcTarget[0].containerType = containerType;
event.srcTarget[0].pageIndex = pageIndex;
dispatchUserEvent(event, null);
}
/**
* TODO: Make this function work when a container view is passed as the 2nd param.
*/
public void logActionCommand(int command, View itemView, int containerType) {
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.COMMAND, itemView,
Target.CONTAINER);
event.action.command = command;
if (fillInLogContainerData(event, itemView)) {
// TODO: Remove the following two lines once fillInLogContainerData can take in a
// container view.
event.srcTarget[0].type = Target.CONTAINER;
event.srcTarget[0].containerType = containerType;
}
dispatchUserEvent(event, null);
}
@ -215,7 +241,6 @@ public class UserEventDispatcher {
}
public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
LauncherEvent event = LoggerUtils.initLauncherEvent(Action.TOUCH,
dragObj.dragView,
dragObj.originalDragInfo,
Target.CONTAINER,
dropTargetAsView);