diff options
author | Hyunyoung Song <hyunyoungs@google.com> | 2016-04-12 18:32:04 -0700 |
---|---|---|
committer | Hyunyoung Song <hyunyoungs@google.com> | 2016-04-13 10:58:33 -0700 |
commit | ddec1c739ef37c3a042982b8943fe42e04b65f4c (patch) | |
tree | 565933d46552049c8af29e8615964e47919fd81c /src/com/android | |
parent | 30a716157b748258e5461fe783298ba7c740835f (diff) | |
download | android_packages_apps_Trebuchet-ddec1c739ef37c3a042982b8943fe42e04b65f4c.tar.gz android_packages_apps_Trebuchet-ddec1c739ef37c3a042982b8943fe42e04b65f4c.tar.bz2 android_packages_apps_Trebuchet-ddec1c739ef37c3a042982b8943fe42e04b65f4c.zip |
Refactor UserEventLogging, Add predictedRank, replace Bundle with Proto
b/26494415
- Removed bundle object that became redundant now that we have LauncherEvent proto
- Combined Stats and UserEventLogger as they are effectively doing same thing
- Removed parent field inside Target
- added predictedRank target inside Target
b/27967359
- make com.android.launcher3.action.LAUNCH broadcast explicit
Later CL: finish packageName/intent/componentHash/predictedRank fields
Change-Id: I441fb46c834f73e58a4d2324e8da7971e8713ec8
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/Hotseat.java | 14 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 29 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherCallbacks.java | 3 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherFiles.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/Stats.java | 152 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 15 | ||||
-rw-r--r-- | src/com/android/launcher3/allapps/AllAppsRecyclerView.java | 22 | ||||
-rw-r--r-- | src/com/android/launcher3/folder/Folder.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher3/logging/LoggerUtils.java | 36 | ||||
-rw-r--r-- | src/com/android/launcher3/logging/UserEventLogger.java | 216 | ||||
-rw-r--r-- | src/com/android/launcher3/testing/LauncherExtension.java | 4 |
11 files changed, 242 insertions, 271 deletions
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index e691b480a..1af76682f 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -19,7 +19,6 @@ package com.android.launcher3; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.Bundle; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -28,8 +27,12 @@ import android.view.ViewDebug; import android.widget.FrameLayout; import android.widget.TextView; +import com.android.launcher3.logging.UserEventLogger; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.Target; + public class Hotseat extends FrameLayout - implements Stats.LaunchSourceProvider{ + implements UserEventLogger.LaunchSourceProvider{ private CellLayout mContent; @@ -157,7 +160,10 @@ public class Hotseat extends FrameLayout } @Override - public void fillInLaunchSourceData(View v, Bundle sourceData) { - sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOTSEAT); + public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) { + target.itemType = LauncherLogProto.APP_ICON; + target.gridX = info.cellX; + target.gridY = info.cellY; + targetParent.containerType = LauncherLogProto.HOTSEAT; } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d2d07cc5a..587336802 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -148,6 +148,7 @@ public class Launcher extends Activity static final boolean DEBUG_WIDGETS = false; static final boolean DEBUG_STRICT_MODE = false; static final boolean DEBUG_RESUME_TIME = false; + static final boolean DEBUG_LOGGING = false; static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run @@ -174,7 +175,7 @@ public class Launcher extends Activity protected static final int REQUEST_LAST = 100; // To turn on these properties, type - // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] + // adb shell setprop logTap.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] static final String DUMP_STATE_PROPERTY = "launcher_dump_state"; // The Intent extra that defines whether to ignore the launch animation @@ -365,7 +366,6 @@ public class Launcher extends Activity int appWidgetId; } - private Stats mStats; private UserEventLogger mUserEventLogger; public FocusIndicatorView mFocusHandler; @@ -425,7 +425,6 @@ public class Launcher extends Activity mDragController = new DragController(this); mStateTransitionAnimation = new LauncherStateTransitionAnimation(this); - mStats = new Stats(this); initLogger(); mAppWidgetManager = AppWidgetManagerCompat.getInstance(this); @@ -638,10 +637,6 @@ public class Launcher extends Activity } } - public Stats getStats() { - return mStats; - } - /** * Logger object is a singleton and does not have to be coupled with the foreground activity. * Since most user event logging is done on the UI, the object is retrieved from the @@ -652,16 +647,19 @@ public class Launcher extends Activity mUserEventLogger = mLauncherCallbacks.getLogger(); } if (mUserEventLogger == null) { - mUserEventLogger = new UserEventLogger() { + mUserEventLogger = new UserEventLogger(this) { @Override public void processEvent(LauncherLogProto.LauncherEvent ev) { - if (ev.action.touch == LauncherLogProto.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", - LoggerUtils.getActionStr(ev.action), - LoggerUtils.getTargetStr(ev.srcTarget), - ev.elapsedContainerMillis, - ev.elapsedSessionMillis)); + if (!DEBUG_LOGGING) { + return; } + Log.d("UserEvent", String.format(Locale.US, + "action:%s\nchild:%s\nparent:%s\nelapsed container %d ms session %d ms", + LoggerUtils.getActionStr(ev.action), + LoggerUtils.getTargetStr(ev.srcTarget[0]), + LoggerUtils.getTargetStr(ev.srcTarget[1]), + ev.elapsedContainerMillis, + ev.elapsedSessionMillis)); } }; } @@ -2705,7 +2703,7 @@ public class Launcher extends Activity } boolean success = startActivitySafely(v, intent, tag); - mStats.recordLaunch(v, intent, shortcut); + mUserEventLogger.logLaunch(v, intent); if (success && v instanceof BubbleTextView) { mWaitingForResume = (BubbleTextView) v; @@ -3488,6 +3486,7 @@ public class Launcher extends Activity List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps(); if (apps != null) { mAppsView.setPredictedApps(apps); + mUserEventLogger.setPredictedApps(apps); } } } diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java index 635d413ba..f33cf83e8 100644 --- a/src/com/android/launcher3/LauncherCallbacks.java +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -1,12 +1,11 @@ package com.android.launcher3; -import android.content.ComponentName; import android.content.Intent; import android.graphics.Rect; import android.os.Bundle; import android.view.Menu; import android.view.View; -import android.view.ViewGroup; + import com.android.launcher3.allapps.AllAppsSearchBarController; import com.android.launcher3.logging.UserEventLogger; import com.android.launcher3.util.ComponentKey; diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java index 6ce229382..adb503135 100644 --- a/src/com/android/launcher3/LauncherFiles.java +++ b/src/com/android/launcher3/LauncherFiles.java @@ -39,8 +39,8 @@ public class LauncherFiles { // TODO: Delete these files on upgrade public static final List<String> OBSOLETE_FILES = Collections.unmodifiableList(Arrays.asList( - "launches.log", - "stats.log", + "launches.logTap", + "stats.logTap", "launcher.preferences", "com.android.launcher3.compat.PackageInstallerCompatV16.queue")); } diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java deleted file mode 100644 index 10a26ad59..000000000 --- a/src/com/android/launcher3/Stats.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - */ - -package com.android.launcher3; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.view.ViewParent; - -import com.android.launcher3.config.ProviderConfig; - -public class Stats { - - /** - * Implemented by containers to provide a launch source for a given child. - */ - public interface LaunchSourceProvider { - void fillInLaunchSourceData(View v, Bundle sourceData); - } - - /** - * Helpers to add the source to a launch intent. - */ - public static class LaunchSourceUtils { - /** - * Create a default bundle for LaunchSourceProviders to fill in their data. - */ - public static Bundle createSourceData() { - Bundle sourceData = new Bundle(); - sourceData.putString(SOURCE_EXTRA_CONTAINER, CONTAINER_HOMESCREEN); - // Have default container/sub container pages - sourceData.putInt(SOURCE_EXTRA_CONTAINER_PAGE, 0); - sourceData.putInt(SOURCE_EXTRA_SUB_CONTAINER_PAGE, 0); - return sourceData; - } - - /** - * Finds the next launch source provider in the parents of the view hierarchy and populates - * the source data from that provider. - */ - public static void populateSourceDataFromAncestorProvider(View v, Bundle sourceData) { - if (v == null) { - return; - } - - Stats.LaunchSourceProvider provider = null; - ViewParent parent = v.getParent(); - while (parent != null && parent instanceof View) { - if (parent instanceof Stats.LaunchSourceProvider) { - provider = (Stats.LaunchSourceProvider) parent; - break; - } - parent = parent.getParent(); - } - - if (provider != null) { - provider.fillInLaunchSourceData(v, sourceData); - } else if (ProviderConfig.IS_DOGFOOD_BUILD) { - throw new RuntimeException("Expected LaunchSourceProvider"); - } - } - } - - private static final boolean DEBUG_BROADCASTS = false; - - public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH"; - public static final String EXTRA_INTENT = "intent"; - public static final String EXTRA_CONTAINER = "container"; - public static final String EXTRA_SCREEN = "screen"; - public static final String EXTRA_CELLX = "cellX"; - public static final String EXTRA_CELLY = "cellY"; - public static final String EXTRA_SOURCE = "source"; - - public static final String SOURCE_EXTRA_CONTAINER = "container"; - public static final String SOURCE_EXTRA_CONTAINER_PAGE = "container_page"; - public static final String SOURCE_EXTRA_SUB_CONTAINER = "sub_container"; - public static final String SOURCE_EXTRA_SUB_CONTAINER_PAGE = "sub_container_page"; - - public static final String CONTAINER_SEARCH_BOX = "search_box"; - public static final String CONTAINER_ALL_APPS = "all_apps"; - public static final String CONTAINER_HOMESCREEN = "homescreen"; // aka. Workspace - public static final String CONTAINER_HOTSEAT = "hotseat"; - - public static final String SUB_CONTAINER_FOLDER = "folder"; - public static final String SUB_CONTAINER_ALL_APPS_A_Z = "a-z"; - public static final String SUB_CONTAINER_ALL_APPS_PREDICTION = "prediction"; - public static final String SUB_CONTAINER_ALL_APPS_SEARCH = "search"; - - private final Launcher mLauncher; - private final String mLaunchBroadcastPermission; - - public Stats(Launcher launcher) { - mLauncher = launcher; - mLaunchBroadcastPermission = - launcher.getResources().getString(R.string.receive_launch_broadcasts_permission); - - if (DEBUG_BROADCASTS) { - launcher.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.v("Stats", "got broadcast: " + intent + " for launched intent: " - + intent.getStringExtra(EXTRA_INTENT)); - } - }, - new IntentFilter(ACTION_LAUNCH), - mLaunchBroadcastPermission, - null - ); - } - } - - public void recordLaunch(View v, Intent intent, ShortcutInfo shortcut) { - intent = new Intent(intent); - intent.setSourceBounds(null); - - final String flat = intent.toUri(0); - Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat); - if (shortcut != null) { - broadcastIntent.putExtra(EXTRA_CONTAINER, shortcut.container) - .putExtra(EXTRA_SCREEN, shortcut.screenId) - .putExtra(EXTRA_CELLX, shortcut.cellX) - .putExtra(EXTRA_CELLY, shortcut.cellY); - } - - Bundle sourceExtras = LaunchSourceUtils.createSourceData(); - LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras); - broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras); - mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission); - if (intent.getComponent() != null) { - mLauncher.getLogger().logAppLaunch(intent.getComponent().getPackageName(), shortcut, sourceExtras); - } - } -} diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 4aea85e6d..6b38f648c 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -39,7 +39,6 @@ import android.graphics.Rect; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.os.Build; -import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Parcelable; @@ -73,6 +72,9 @@ import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.SpringLoadedDragController; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.logging.UserEventLogger; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.Thunk; import com.android.launcher3.util.WallpaperOffsetInterpolator; @@ -92,7 +94,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class Workspace extends PagedView implements DropTarget, DragSource, DragScroller, View.OnTouchListener, DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener, - Insettable, DropTargetSource, AccessibilityDragSource, Stats.LaunchSourceProvider { + Insettable, DropTargetSource, AccessibilityDragSource, UserEventLogger.LaunchSourceProvider { private static final String TAG = "Launcher.Workspace"; private static boolean ENFORCE_DRAG_EVENT_ORDER = false; @@ -4264,9 +4266,12 @@ public class Workspace extends PagedView } @Override - public void fillInLaunchSourceData(View v, Bundle sourceData) { - sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOMESCREEN); - sourceData.putInt(Stats.SOURCE_EXTRA_CONTAINER_PAGE, getCurrentPage()); + public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) { + target.itemType = LauncherLogProto.APP_ICON; + target.gridX = info.cellX; + target.gridY = info.cellY; + target.pageIndex = getCurrentPage(); + targetParent.containerType = LauncherLogProto.WORKSPACE; } /** diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 2b3d061e6..32d444d8f 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.drawable.Drawable; -import android.os.Bundle; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; @@ -27,17 +26,19 @@ import android.view.View; import com.android.launcher3.BaseRecyclerView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.ItemInfo; import com.android.launcher3.R; -import com.android.launcher3.Stats; import com.android.launcher3.Utilities; - +import com.android.launcher3.logging.UserEventLogger.LaunchSourceProvider; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import java.util.List; /** * A RecyclerView with custom fast scroll support for the all apps view. */ public class AllAppsRecyclerView extends BaseRecyclerView - implements Stats.LaunchSourceProvider { + implements LaunchSourceProvider { private AlphabeticalAppsList mApps; private AllAppsFastScrollHelper mFastScrollHelper; @@ -165,11 +166,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView } @Override - public void fillInLaunchSourceData(View v, Bundle sourceData) { - sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS); + public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) { if (mApps.hasFilter()) { - sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, - Stats.SUB_CONTAINER_ALL_APPS_SEARCH); + targetParent.containerType = LauncherLogProto.SEARCHRESULT; } else { if (v instanceof BubbleTextView) { BubbleTextView icon = (BubbleTextView) v; @@ -178,14 +177,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems(); AlphabeticalAppsList.AdapterItem item = items.get(position); if (item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { - sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, - Stats.SUB_CONTAINER_ALL_APPS_PREDICTION); + targetParent.containerType = LauncherLogProto.PREDICTION; return; } } } - sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, - Stats.SUB_CONTAINER_ALL_APPS_A_Z); + + targetParent.containerType = LauncherLogProto.ALLAPPS; } } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 2b34a79e8..b6be8e04c 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -29,7 +29,6 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.os.Build; -import android.os.Bundle; import android.text.InputType; import android.text.Selection; import android.text.Spannable; @@ -70,7 +69,6 @@ import com.android.launcher3.LogDecelerateInterpolator; import com.android.launcher3.OnAlarmListener; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; -import com.android.launcher3.Stats; import com.android.launcher3.UninstallDropTarget.DropTargetSource; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace.ItemOperator; @@ -79,6 +77,9 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.logging.UserEventLogger.LaunchSourceProvider; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.Thunk; import com.android.launcher3.util.UiThreadCircularReveal; @@ -92,7 +93,7 @@ import java.util.Comparator; public class Folder extends LinearLayout implements DragSource, View.OnClickListener, View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource, - Stats.LaunchSourceProvider { + LaunchSourceProvider { private static final String TAG = "Launcher.Folder"; /** @@ -1416,11 +1417,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } @Override - public void fillInLaunchSourceData(View v, Bundle sourceData) { - // Fill in from the folder icon's launch source provider first - Stats.LaunchSourceUtils.populateSourceDataFromAncestorProvider(mFolderIcon, sourceData); - sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, Stats.SUB_CONTAINER_FOLDER); - sourceData.putInt(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE, mContent.getCurrentPage()); + public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) { + target.itemType = LauncherLogProto.APP_ICON; + target.gridX = info.cellX; + target.gridY = info.cellY; + target.pageIndex = mContent.getCurrentPage(); + targetParent.containerType = LauncherLogProto.FOLDER; } private class OnScrollHintListener implements OnAlarmListener { diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java index 4b30384f2..584e38e9e 100644 --- a/src/com/android/launcher3/logging/LoggerUtils.java +++ b/src/com/android/launcher3/logging/LoggerUtils.java @@ -5,7 +5,6 @@ import android.util.Log; import com.android.launcher3.LauncherSettings; import com.android.launcher3.ShortcutInfo; -import com.android.launcher3.Stats; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; @@ -18,16 +17,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Target; */ public class LoggerUtils { private static final String TAG = "LoggerUtils"; - private static final boolean DEBUG = false; - - 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; - } - } public static String getActionStr(LauncherLogProto.Action action) { switch(action.touch) { @@ -62,8 +51,10 @@ public class LoggerUtils { default: typeStr = "UNKNOWN"; } - return typeStr + " " + t.packageNameHash + " grid=(" + t.gridX + "," + t.gridY + ") " - + getContainerStr(t.parent); + return typeStr + ", packageHash=" + t.packageNameHash + + ", componentHash=" + t.componentHash + + ", intentHash=" + t.intentHash + + ", grid=(" + t.gridX + "," + t.gridY + "), id=" + t.pageIndex; } private static String getControlStr(Target t) { @@ -76,7 +67,6 @@ public class LoggerUtils { 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"; } } @@ -114,4 +104,22 @@ public class LoggerUtils { } return str + " id=" + t.pageIndex; } + + + public static LauncherLogProto.LauncherEvent initLauncherEvent( + int actionType, + int childTargetType, + int parentTargetType){ + LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent(); + + event.srcTarget = new LauncherLogProto.Target[2]; + event.srcTarget[0] = new LauncherLogProto.Target(); + event.srcTarget[0].type = childTargetType; + event.srcTarget[1] = new LauncherLogProto.Target(); + event.srcTarget[1].type = parentTargetType; + + event.action = new LauncherLogProto.Action(); + event.action.type = actionType; + return event; + } } diff --git a/src/com/android/launcher3/logging/UserEventLogger.java b/src/com/android/launcher3/logging/UserEventLogger.java index 4e5b2c1b4..bc3afeb8a 100644 --- a/src/com/android/launcher3/logging/UserEventLogger.java +++ b/src/com/android/launcher3/logging/UserEventLogger.java @@ -1,71 +1,182 @@ +/* + * 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. + */ + package com.android.launcher3.logging; -import android.os.Bundle; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.util.Log; +import android.view.View; +import android.view.ViewParent; -import com.android.launcher3.ShortcutInfo; -import com.android.launcher3.Stats; -import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.ItemInfo; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; +import com.android.launcher3.userevent.nano.LauncherLogProto.Target; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action; +import com.android.launcher3.util.ComponentKey; + +import com.google.protobuf.nano.MessageNano; -import java.util.Locale; +import java.util.List; public abstract class UserEventLogger { + private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5; + /** + * Implemented by containers to provide a launch source for a given child. + */ + public interface LaunchSourceProvider { + + /** + * Copies data from the source to the destination proto. + * @param v source of the data + * @param info source of the data + * @param target dest of the data + * @param targetParent dest of the data + */ + 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; + 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; + } + private String TAG = "UserEventLogger"; - private boolean DEBUG = false; + private static final boolean DEBUG_BROADCASTS = true; + + public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH"; + public static final String EXTRA_INTENT = "intent";; + public static final String EXTRA_SOURCE = "source"; + + private final Launcher mLauncher; + private final String mLaunchBroadcastPermission; private long mElapsedContainerMillis; private long mElapsedSessionMillis; private long mActionDurationMillis; + // Used for filling in predictedRank on {@link Target}s. + private List<ComponentKey> mPredictedApps; + + public UserEventLogger(Launcher launcher) { + mLauncher = launcher; + mLaunchBroadcastPermission = + launcher.getResources().getString(R.string.receive_launch_broadcasts_permission); + + if (DEBUG_BROADCASTS) { + launcher.registerReceiver( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.v(TAG, "got broadcast: " + intent + " for launched intent: " + + intent.getStringExtra(EXTRA_INTENT)); + } + }, + new IntentFilter(ACTION_LAUNCH), + mLaunchBroadcastPermission, + null + ); + } + } - public final void logAppLaunch(String provider, ShortcutInfo shortcut, Bundle bundle) { - if (FeatureFlags.LAUNCHER3_LEGACY_LOGGING) return; + // APP_ICON SHORTCUT WIDGET + // -------------------------------------------------------------- + // packageNameHash required optional required + // componentNameHash required required + // intentHash required + // -------------------------------------------------------------- - LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent(); - event.action = new LauncherLogProto.Action(); - event.action.type = LauncherLogProto.Action.TOUCH; - event.action.touch = LauncherLogProto.Action.TAP; + /** + * Prepare {@link LauncherEvent} and {@link Intent} and then attach the event + * to the intent and then broadcast. + */ + public final void broadcastEvent(LauncherEvent ev, Intent intent) { + intent = new Intent(intent); + intent.setSourceBounds(null); + + final String flat = intent.toUri(0); + Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat); + + broadcastIntent.putExtra(EXTRA_SOURCE, MessageNano.toByteArray(ev)); + String[] packages = ((Context)mLauncher).getResources().getStringArray(R.array.launch_broadcast_targets); + for(String p: packages) { + broadcastIntent.setPackage(p); + mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission); + } + } - event.srcTarget = new LauncherLogProto.Target(); - event.srcTarget.type = LauncherLogProto.Target.ITEM; - event.srcTarget.itemType = LauncherLogProto.APP_ICON; - // TODO: package hash name should be different per device. - event.srcTarget.packageNameHash = provider.hashCode(); + public final void logLaunch(View v, Intent intent) { + LauncherEvent event = LoggerUtils.initLauncherEvent( + Action.TOUCH, Target.ITEM, Target.CONTAINER); + event.action.touch = Action.TAP; - event.srcTarget.parent = new LauncherLogProto.Target(); - String subContainer = bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER); + // 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); + provider.fillInLaunchSourceData(v, (ItemInfo) v.getTag(), event.srcTarget[idx], event.srcTarget[idx + 1]); - if (shortcut != null) { - event.srcTarget.parent.containerType = LoggerUtils.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 = LauncherLogProto.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; - } + // TODO: Fill in all the hashes and the predictedRank - 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))); - } - } + // Fill in the duration of time spent navigating in Launcher and the container. event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis; event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis; processEvent(event); + + broadcastEvent(event, intent); + } + + public void logTap(View v) { + // TODO + } + + public void logLongPress() { + // TODO + } + + public void logDragNDrop() { + // TODO + } + + public void setPredictedApps(List<ComponentKey> predictedApps) { + mPredictedApps = predictedApps; } /** @@ -73,25 +184,22 @@ public abstract class UserEventLogger { */ public final void resetElapsedContainerMillis() { mElapsedContainerMillis = System.currentTimeMillis(); - if(DEBUG) { - Log.d(TAG, "resetElapsedContainerMillis " + mElapsedContainerMillis); - } } public final void resetElapsedSessionMillis() { mElapsedSessionMillis = System.currentTimeMillis(); mElapsedContainerMillis = System.currentTimeMillis(); - if(DEBUG) { - Log.d(TAG, "resetElapsedSessionMillis " + mElapsedSessionMillis); - } + } public final void resetActionDurationMillis() { mActionDurationMillis = System.currentTimeMillis(); - if(DEBUG) { - Log.d(TAG, "resetElapsedContainerMillis " + mElapsedContainerMillis); - } } public abstract void processEvent(LauncherLogProto.LauncherEvent ev); -}
\ No newline at end of file + + public int getPredictedRank(ComponentKey key) { + if (mPredictedApps == null) return -1; + return mPredictedApps.indexOf(key); + } +} diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java index de8da36f3..2fde8f3e4 100644 --- a/src/com/android/launcher3/testing/LauncherExtension.java +++ b/src/com/android/launcher3/testing/LauncherExtension.java @@ -1,6 +1,5 @@ package com.android.launcher3.testing; -import android.content.ComponentName; import android.content.Intent; import android.graphics.Color; import android.graphics.Rect; @@ -12,9 +11,8 @@ import android.widget.FrameLayout; import com.android.launcher3.AppInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherCallbacks; -import com.android.launcher3.compat.UserHandleCompat; -import com.android.launcher3.logging.UserEventLogger; import com.android.launcher3.allapps.AllAppsSearchBarController; +import com.android.launcher3.logging.UserEventLogger; import com.android.launcher3.util.ComponentKey; import java.io.FileDescriptor; |