From c6b79e307f59e936ee380da07b0bd6fafe0a490c Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 1 Feb 2017 09:13:24 -0800 Subject: [PATCH] Add logging for notifications. - Log notification launches - Log notification swipes - Fix logDragNDrop() to only log if the pre-drag ends (so it doesn't log a long-press that only shows shortcuts without dragging). - Add shortcut rank to logs when launching deep shortcuts, where 0 is the shortcut closest to the app icon (highest rank). Bug: 34770729 Bug: 32410600 Change-Id: I99dcef9b6a71da2ef58e32397702bb137407b10f --- protos/launcher_log.proto | 1 + .../launcher3/dragndrop/DragController.java | 2 +- .../launcher3/logging/UserEventDispatcher.java | 27 ++++++++++++++++++---- .../launcher3/notification/NotificationInfo.java | 1 + .../notification/NotificationItemView.java | 16 +++++++++---- .../notification/NotificationMainView.java | 13 +++++++++-- .../launcher3/popup/PopupContainerWithArrow.java | 2 +- .../android/launcher3/popup/PopupPopulator.java | 1 + 8 files changed, 49 insertions(+), 14 deletions(-) diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto index 33041dbca..c42b142f7 100644 --- a/protos/launcher_log.proto +++ b/protos/launcher_log.proto @@ -64,6 +64,7 @@ enum ItemType { DEEPSHORTCUT = 5; SEARCHBOX = 6; EDITTEXT = 7; + NOTIFICATION = 8; } // Used to define what type of container a Target would represent. diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index e31c8ffdd..7410ae6c9 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -582,8 +582,8 @@ public class DragController implements DragDriver.EventListener, TouchController } } final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null; - mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView); if (!mIsInPreDrag) { + mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView); mDragObject.dragSource.onDropCompleted( dropTargetAsView, mDragObject, flingAnimation != null, accepted); } diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java index 8ab33dc57..b4b62a864 100644 --- a/src/com/android/launcher3/logging/UserEventDispatcher.java +++ b/src/com/android/launcher3/logging/UserEventDispatcher.java @@ -16,6 +16,7 @@ package com.android.launcher3.logging; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Intent; import android.os.SystemClock; @@ -112,7 +113,7 @@ public class UserEventDispatcher { // intentHash required // -------------------------------------------------------------- - protected LauncherEvent createLauncherEvent(View v, Intent intent) { + protected LauncherEvent createLauncherEvent(View v, int intentHashCode, ComponentName cn) { LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.TAP), newItemTarget(v), newTarget(Target.Type.CONTAINER)); @@ -120,8 +121,7 @@ public class UserEventDispatcher { int idx = 0; if (fillInLogContainerData(event, v)) { ItemInfo itemInfo = (ItemInfo) v.getTag(); - event.srcTarget[idx].intentHash = intent.hashCode(); - ComponentName cn = intent.getComponent(); + event.srcTarget[idx].intentHash = intentHashCode; if (cn != null) { event.srcTarget[idx].packageNameHash = cn.getPackageName().hashCode(); event.srcTarget[idx].componentHash = cn.hashCode(); @@ -146,13 +146,22 @@ public class UserEventDispatcher { } public void logAppLaunch(View v, Intent intent) { - LauncherEvent ev = createLauncherEvent(v, intent); + LauncherEvent ev = createLauncherEvent(v, intent.hashCode(), intent.getComponent()); if (ev == null) { return; } dispatchUserEvent(ev, intent); } + public void logNotificationLaunch(View v, PendingIntent intent) { + ComponentName dummyComponent = new ComponentName(intent.getCreatorPackage(), "--dummy--"); + LauncherEvent ev = createLauncherEvent(v, intent.hashCode(), dummyComponent); + if (ev == null) { + return; + } + dispatchUserEvent(ev, null); + } + public void logActionCommand(int command, int containerType) { logActionCommand(command, containerType, 0); } @@ -199,9 +208,17 @@ public class UserEventDispatcher { dispatchUserEvent(event, null); } + public void logActionOnItem(int action, int dir, int itemType) { + Target itemTarget = newTarget(Target.Type.ITEM); + itemTarget.itemType = itemType; + LauncherEvent event = newLauncherEvent(newTouchAction(action), itemTarget); + event.action.dir = dir; + dispatchUserEvent(event, null); + } + public void logDeepShortcutsOpen(View icon) { LogContainerProvider provider = getLaunchProviderRecursive(icon); - if (icon == null && !(icon.getTag() instanceof ItemInfo)) { + if (icon == null || !(icon.getTag() instanceof ItemInfo)) { return; } ItemInfo info = (ItemInfo) icon.getTag(); diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java index 6cc0e900d..a3e36f90e 100644 --- a/src/com/android/launcher3/notification/NotificationInfo.java +++ b/src/com/android/launcher3/notification/NotificationInfo.java @@ -85,6 +85,7 @@ public class NotificationInfo implements View.OnClickListener { view, 0, 0, view.getWidth(), view.getHeight()).toBundle(); try { intent.send(null, 0, null, null, null, null, activityOptions); + launcher.getUserEventDispatcher().logNotificationLaunch(view, intent); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java index 422722d8c..639447dc3 100644 --- a/src/com/android/launcher3/notification/NotificationItemView.java +++ b/src/com/android/launcher3/notification/NotificationItemView.java @@ -29,15 +29,16 @@ import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.TextView; +import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.R; import com.android.launcher3.graphics.IconPalette; +import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider; import com.android.launcher3.popup.PopupItemView; +import com.android.launcher3.userevent.nano.LauncherLogProto; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static com.android.launcher3.LauncherAnimUtils.animateViewHeight; @@ -47,7 +48,7 @@ import static com.android.launcher3.LauncherAnimUtils.animateViewHeight; * The footer contains: A list of just the icons of all the notifications past the first one. * @see NotificationFooterLayout */ -public class NotificationItemView extends PopupItemView { +public class NotificationItemView extends PopupItemView implements LogContainerProvider { private static final Rect sTempRect = new Rect(); @@ -57,7 +58,6 @@ public class NotificationItemView extends PopupItemView { private NotificationFooterLayout mFooter; private SwipeHelper mSwipeHelper; private boolean mAnimatingNextIcon; - private IconPalette mIconPalette; public NotificationItemView(Context context) { this(context, null, 0); @@ -114,7 +114,6 @@ public class NotificationItemView extends PopupItemView { } public void applyColors(IconPalette iconPalette) { - mIconPalette = iconPalette; setBackgroundTintList(ColorStateList.valueOf(iconPalette.secondaryColor)); mHeader.setBackgroundTintList(ColorStateList.valueOf(iconPalette.backgroundColor)); mHeader.setTextColor(ColorStateList.valueOf(iconPalette.textColor)); @@ -174,4 +173,11 @@ public class NotificationItemView extends PopupItemView { animation.playSequentially(removeMainView, removeRest); return animation; } + + @Override + public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target, + LauncherLogProto.Target targetParent) { + target.itemType = LauncherLogProto.ItemType.NOTIFICATION; + targetParent.containerType = LauncherLogProto.ContainerType.DEEPSHORTCUTS; + } } diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java index 76a84b7c6..6677c2fa2 100644 --- a/src/com/android/launcher3/notification/NotificationMainView.java +++ b/src/com/android/launcher3/notification/NotificationMainView.java @@ -20,18 +20,19 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.content.Context; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.LauncherViewPropertyAnimator; import com.android.launcher3.R; import com.android.launcher3.graphics.IconPalette; +import com.android.launcher3.userevent.nano.LauncherLogProto; /** * A {@link LinearLayout} that contains a single notification, e.g. icon + title + text. @@ -89,6 +90,9 @@ public class NotificationMainView extends LinearLayout implements SwipeHelper.Ca getContext(), mIconPalette.backgroundColor)); setOnClickListener(mNotificationInfo); setTranslationX(0); + // Add a dummy ItemInfo so that logging populates the correct container and item types + // instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively. + setTag(new ItemInfo()); if (animate) { AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); Animator textFade = new LauncherViewPropertyAnimator(mTextView).alpha(1); @@ -135,8 +139,13 @@ public class NotificationMainView extends LinearLayout implements SwipeHelper.Ca @Override public void onChildDismissed(View v) { - Launcher.getLauncher(getContext()).getPopupDataProvider().cancelNotification( + Launcher launcher = Launcher.getLauncher(getContext()); + launcher.getPopupDataProvider().cancelNotification( mNotificationInfo.notificationKey); + launcher.getUserEventDispatcher().logActionOnItem( + LauncherLogProto.Action.Touch.SWIPE, + LauncherLogProto.Action.Direction.RIGHT, // Assume all swipes are right for logging. + LauncherLogProto.ItemType.NOTIFICATION); } @Override diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index af1bd9b34..b8e2dc8a8 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -696,7 +696,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView @Override public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) { target.itemType = ItemType.DEEPSHORTCUT; - // TODO: add target.rank + target.rank = info.rank; targetParent.containerType = ContainerType.DEEPSHORTCUTS; } diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java index f990fa2d8..d2814ee7b 100644 --- a/src/com/android/launcher3/popup/PopupPopulator.java +++ b/src/com/android/launcher3/popup/PopupPopulator.java @@ -171,6 +171,7 @@ public class PopupPopulator { // Use unbadged icon for the menu. si.iconBitmap = LauncherIcons.createShortcutIcon( shortcut, launcher, false /* badged */); + si.rank = i; uiHandler.post(new UpdateShortcutChild(container, shortcutViews.get(i), si, shortcut)); } -- 2.11.0