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/launcher3/logging | |
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/launcher3/logging')
-rw-r--r-- | src/com/android/launcher3/logging/LoggerUtils.java | 36 | ||||
-rw-r--r-- | src/com/android/launcher3/logging/UserEventLogger.java | 216 |
2 files changed, 184 insertions, 68 deletions
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); + } +} |