mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 02:38:20 +00:00
<UserEventLogging> Log app launches
b/26494415 1) Current Logger can capture taps from - homescreen - folder inside homescreen - apps prediction - all apps a-z - tap from hotseat 2) Deprecate LauncherCallback methods that is no longer needed Future CL. 3) Stats and Logger will be merged. Bundle used for Stats can be replaced with LauncherLogProto 4) Logging anything else other than app launches Change-Id: Id52eb615f66142017b5c490a220ce6654d325681
This commit is contained in:
@@ -108,6 +108,7 @@ import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.userevent.Logger;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.LongArrayMap;
|
||||
import com.android.launcher3.util.TestingUtils;
|
||||
@@ -367,6 +368,8 @@ public class Launcher extends Activity
|
||||
}
|
||||
|
||||
private Stats mStats;
|
||||
private Logger mUserEventLogger;
|
||||
|
||||
public FocusIndicatorView mFocusHandler;
|
||||
private boolean mRotationEnabled = false;
|
||||
|
||||
@@ -424,6 +427,7 @@ public class Launcher extends Activity
|
||||
mDragController = new DragController(this);
|
||||
mStateTransitionAnimation = new LauncherStateTransitionAnimation(this);
|
||||
|
||||
mUserEventLogger = new Logger(this);
|
||||
mStats = new Stats(this);
|
||||
|
||||
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
|
||||
@@ -627,6 +631,7 @@ public class Launcher extends Activity
|
||||
public Stats getStats() {
|
||||
return mStats;
|
||||
}
|
||||
public Logger getLogger() {return mUserEventLogger; }
|
||||
|
||||
public boolean isDraggingEnabled() {
|
||||
// We prevent dragging when we are loading the workspace as it is possible to pick up a view
|
||||
@@ -950,6 +955,7 @@ public class Launcher extends Activity
|
||||
}
|
||||
|
||||
super.onResume();
|
||||
mUserEventLogger.resetElapsedSessionMillis();
|
||||
|
||||
// Restore the previous launcher state
|
||||
if (mOnResumeState == State.WORKSPACE) {
|
||||
@@ -3331,6 +3337,7 @@ public class Launcher extends Activity
|
||||
getWindow().getDecorView()
|
||||
.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
}
|
||||
mUserEventLogger.resetElapsedContainerMillis();
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,20 +54,33 @@ public interface LauncherCallbacks {
|
||||
*/
|
||||
public void onLauncherProviderChange();
|
||||
public void finishBindingItems(final boolean upgradePath);
|
||||
public void onClickAllAppsButton(View v);
|
||||
public void bindAllApplications(ArrayList<AppInfo> apps);
|
||||
public void onInteractionBegin();
|
||||
public void onInteractionEnd();
|
||||
|
||||
/**
|
||||
* Extension points for Gel Logging.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onClickAllAppsButton(View v);
|
||||
@Deprecated
|
||||
public void onClickFolderIcon(View v);
|
||||
@Deprecated
|
||||
public void onClickAppShortcut(View v);
|
||||
@Deprecated
|
||||
public void onClickPagedViewIcon(View v);
|
||||
@Deprecated
|
||||
public void onClickWallpaperPicker(View v);
|
||||
@Deprecated
|
||||
public void onClickSettingsButton(View v);
|
||||
@Deprecated
|
||||
public void onClickAddWidgetButton(View v);
|
||||
@Deprecated
|
||||
public void onPageSwitch(View newPage, int newPageIndex);
|
||||
@Deprecated
|
||||
public void onWorkspaceLockedChanged();
|
||||
@Deprecated
|
||||
public void onDragStarted(View view);
|
||||
public void onInteractionBegin();
|
||||
public void onInteractionEnd();
|
||||
|
||||
/*
|
||||
* Extension points for replacing the search experience
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.launcher3.config.ProviderConfig;
|
||||
import com.android.launcher3.userevent.Logger;
|
||||
|
||||
public class Stats {
|
||||
|
||||
@@ -145,5 +146,6 @@ public class Stats {
|
||||
LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras);
|
||||
broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras);
|
||||
mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
|
||||
mLauncher.getLogger().logAppLaunch(intent.getComponent().getPackageName(), shortcut, sourceExtras);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.android.launcher3.LauncherTransitionable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.userevent.Logger;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
@@ -312,6 +313,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
|
||||
icon.getMeasuredHeight());
|
||||
|
||||
updateBackgroundAndPaddings();
|
||||
mLauncher.getLogger().resetElapsedContainerMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,4 +35,5 @@ public final class FeatureFlags {
|
||||
public static boolean LAUNCHER3_LEGACY_WORKSPACE_DND = false;
|
||||
public static boolean LAUNCHER3_ICON_NORMALIZATION = true;
|
||||
public static boolean LAUNCHER3_CLIPPED_FOLDER_ICON = false;
|
||||
public static boolean LAUNCHER3_LEGACY_LOGGING = false;
|
||||
}
|
||||
|
||||
208
src/com/android/launcher3/userevent/Logger.java
Normal file
208
src/com/android/launcher3/userevent/Logger.java
Normal file
@@ -0,0 +1,208 @@
|
||||
package com.android.launcher3.userevent;
|
||||
|
||||
import com.android.launcher3.ShortcutInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.Stats;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Creates {@LauncherLogProto} nano protobuf object that can be used for user event
|
||||
* metrics analysis.
|
||||
*/
|
||||
public class Logger {
|
||||
|
||||
private static final String TAG = "UserEventLogger";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private long mActionDurationMillis;
|
||||
private long mElapsedContainerMillis;
|
||||
private long mElapsedSessionMillis;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public Logger(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void logAppLaunch(String provider, ShortcutInfo shortcut, Bundle bundle) {
|
||||
LauncherEvent event = new LauncherEvent();
|
||||
event.action = new Action();
|
||||
event.action.type = Action.TOUCH;
|
||||
event.action.touch = Action.TAP;
|
||||
|
||||
event.srcTarget = new Target();
|
||||
event.srcTarget.type = Target.ITEM;
|
||||
event.srcTarget.itemType = LauncherLogProto.APP_ICON;
|
||||
// TODO: package hash name should be different per device.
|
||||
event.srcTarget.packageNameHash = provider.hashCode();
|
||||
|
||||
event.srcTarget.parent = new Target();
|
||||
String subContainer = bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER);
|
||||
|
||||
if (shortcut != null) {
|
||||
event.srcTarget.parent.containerType = getContainerType(shortcut);
|
||||
event.srcTarget.pageIndex = (int) shortcut.screenId;
|
||||
event.srcTarget.gridX = shortcut.cellX;
|
||||
event.srcTarget.gridX = shortcut.cellY;
|
||||
}
|
||||
if (subContainer != null) {
|
||||
event.srcTarget.parent.type = Target.CONTAINER;
|
||||
if (subContainer.equals(Stats.SUB_CONTAINER_FOLDER)) {
|
||||
event.srcTarget.parent.containerType = LauncherLogProto.FOLDER;
|
||||
} else if (subContainer.equals(Stats.SUB_CONTAINER_ALL_APPS_A_Z)) {
|
||||
event.srcTarget.parent.containerType = LauncherLogProto.ALLAPPS;
|
||||
} else if (subContainer.equals(Stats.CONTAINER_HOTSEAT)) {
|
||||
event.srcTarget.parent.containerType = LauncherLogProto.HOTSEAT;
|
||||
} else if (subContainer.equals(Stats.SUB_CONTAINER_ALL_APPS_PREDICTION)) {
|
||||
event.srcTarget.parent.containerType = LauncherLogProto.PREDICTION;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("parent bundle: %s %s %s %s",
|
||||
bundle.getString(Stats.SOURCE_EXTRA_CONTAINER),
|
||||
bundle.getString(Stats.SOURCE_EXTRA_CONTAINER_PAGE),
|
||||
bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER),
|
||||
bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Assign timeToAction
|
||||
event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
|
||||
event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
|
||||
|
||||
// Debug
|
||||
processLauncherEvent(event);
|
||||
}
|
||||
|
||||
public void resetElapsedContainerMillis() {
|
||||
mElapsedContainerMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void resetElapsedSessionMillis() {
|
||||
mElapsedSessionMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
//
|
||||
// Debugging helper methods.
|
||||
// toString() cannot be overriden inside auto generated {@link LauncherLogProto}.
|
||||
// Note: switch statement cannot be replaced with reflection as proguard strips the constants
|
||||
|
||||
private static void processLauncherEvent(LauncherEvent ev) {
|
||||
if (DEBUG) {
|
||||
if (ev.action.touch == Action.TAP && ev.srcTarget.itemType == LauncherLogProto.APP_ICON) {
|
||||
Log.d(TAG, String.format(Locale.US, "action:%s target:%s\n\telapsed container %d ms session %d ms",
|
||||
getActionStr(ev.action),
|
||||
getTargetStr(ev.srcTarget),
|
||||
ev.elapsedContainerMillis,
|
||||
ev.elapsedSessionMillis));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getContainerType(ShortcutInfo shortcut) {
|
||||
switch ((int) shortcut.container) {
|
||||
case LauncherSettings.Favorites.CONTAINER_DESKTOP: return LauncherLogProto.WORKSPACE;
|
||||
case LauncherSettings.Favorites.CONTAINER_HOTSEAT: return LauncherLogProto.HOTSEAT;
|
||||
default:
|
||||
return (int) shortcut.container;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getActionStr(Action action) {
|
||||
switch(action.touch) {
|
||||
case Action.TAP: return "TAP";
|
||||
case Action.LONGPRESS: return "LONGPRESS";
|
||||
case Action.DRAGDROP: return "DRAGDROP";
|
||||
case Action.PINCH: return "PINCH";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTargetStr(Target t) {
|
||||
String typeStr;
|
||||
switch (t.type) {
|
||||
case LauncherLogProto.Target.ITEM:
|
||||
return getItemStr(t);
|
||||
case LauncherLogProto.Target.CONTROL:
|
||||
return getControlStr(t);
|
||||
case LauncherLogProto.Target.CONTAINER:
|
||||
return getContainerStr(t);
|
||||
default:
|
||||
return "UNKNOWN TARGET TYPE";
|
||||
}
|
||||
}
|
||||
|
||||
private static String getItemStr(Target t) {
|
||||
String typeStr = "";
|
||||
switch(t.itemType){
|
||||
case LauncherLogProto.APP_ICON: typeStr = "ICON"; break;
|
||||
case LauncherLogProto.SHORTCUT: typeStr = "SHORTCUT"; break;
|
||||
case LauncherLogProto.WIDGET: typeStr = "WIDGET"; break;
|
||||
default: typeStr = "UNKNOWN";
|
||||
}
|
||||
|
||||
return typeStr + " " + t.packageNameHash + " grid=(" + t.gridX + "," + t.gridY + ") "
|
||||
+ getContainerStr(t.parent);
|
||||
}
|
||||
|
||||
private static String getControlStr(Target t) {
|
||||
switch(t.controlType) {
|
||||
case LauncherLogProto.ALL_APPS_BUTTON: return "ALL_APPS_BUTTON";
|
||||
case LauncherLogProto.WIDGETS_BUTTON: return "WIDGETS_BUTTON";
|
||||
case LauncherLogProto.WALLPAPER_BUTTON: return "WALLPAPER_BUTTON";
|
||||
case LauncherLogProto.SETTINGS_BUTTON: return "SETTINGS_BUTTON";
|
||||
case LauncherLogProto.REMOVE_TARGET: return "REMOVE_TARGET";
|
||||
case LauncherLogProto.UNINSTALL_TARGET: return "UNINSTALL_TARGET";
|
||||
case LauncherLogProto.APPINFO_TARGET: return "APPINFO_TARGET";
|
||||
case LauncherLogProto.RESIZE_HANDLE: return "RESIZE_HANDLE";
|
||||
case LauncherLogProto.FAST_SCROLL_HANDLE: return "FAST_SCROLL_HANDLE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
private static String getContainerStr(Target t) {
|
||||
String str;
|
||||
Log.d(TAG, "t.containerType" + t.containerType);
|
||||
switch (t.containerType) {
|
||||
case LauncherLogProto.WORKSPACE:
|
||||
str = "WORKSPACE";
|
||||
break;
|
||||
case LauncherLogProto.HOTSEAT:
|
||||
str = "HOTSEAT";
|
||||
break;
|
||||
case LauncherLogProto.FOLDER:
|
||||
str = "FOLDER";
|
||||
break;
|
||||
case LauncherLogProto.ALLAPPS:
|
||||
str = "ALLAPPS";
|
||||
break;
|
||||
case LauncherLogProto.WIDGETS:
|
||||
str = "WIDGETS";
|
||||
break;
|
||||
case LauncherLogProto.OVERVIEW:
|
||||
str = "OVERVIEW";
|
||||
break;
|
||||
case LauncherLogProto.PREDICTION:
|
||||
str = "PREDICTION";
|
||||
break;
|
||||
case LauncherLogProto.SEARCHRESULT:
|
||||
str = "SEARCHRESULT";
|
||||
break;
|
||||
default:
|
||||
str = "UNKNOWN";
|
||||
}
|
||||
return str + " id=" + t.pageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user