Merge "Dumping the excoded view hierarchy instead of the default activity dump" into ub-launcher3-edmonton
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index 8398c48..5ddd904 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -26,9 +26,8 @@
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.OnAlarmListener;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 
@@ -124,9 +123,9 @@
                 mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable;
             }
         }
-        mActivity.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP,
-                ControlType.QUICK_SCRUB_BUTTON, null, mStartedFromHome ?
-                        ContainerType.WORKSPACE : ContainerType.APP);
+        mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP,
+                LauncherLogProto.Action.Direction.NONE, page,
+                TaskUtils.getComponentKeyForTask(mRecentsView.getPageAt(page).getTask().key));
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5c7118f..68432ab 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -418,6 +418,7 @@
         final int requiredChildCount = tasks.size();
         for (int i = getChildCount(); i < requiredChildCount; i++) {
             final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
+            taskView.setOnClickListener(this::onTaskClicked);
             addView(taskView);
         }
         while (getChildCount() > requiredChildCount) {
@@ -443,6 +444,17 @@
         onTaskStackUpdated();
     }
 
+    private void onTaskClicked(View v) {
+        TaskView taskView = (TaskView) v;
+        if (taskView.getTask() == null) {
+            return;
+        }
+        taskView.launchTask(true /* animate */);
+        mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
+                Touch.TAP, Direction.NONE, indexOfChild(taskView),
+                TaskUtils.getComponentKeyForTask(taskView.getTask().key));
+    }
+
     protected void onTaskStackUpdated() { }
 
     public void resetTaskVisuals() {
@@ -745,13 +757,13 @@
                 duration, LINEAR, anim);
     }
 
-    private void removeTask(Task task, PendingAnimation.OnEndListener onEndListener,
-            boolean shouldLog) {
+    private void removeTask(Task task, int index, PendingAnimation.OnEndListener onEndListener,
+                            boolean shouldLog) {
         if (task != null) {
             ActivityManagerWrapper.getInstance().removeTask(task.key.id);
             if (shouldLog) {
                 mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
-                        onEndListener.logAction, Direction.UP,
+                        onEndListener.logAction, Direction.UP, index,
                         TaskUtils.getComponentKeyForTask(task.key));
             }
         }
@@ -836,7 +848,7 @@
         mPendingAnimation.addEndListener((onEndListener) -> {
            if (onEndListener.isSuccess) {
                if (shouldRemoveTask) {
-                   removeTask(taskView.getTask(), onEndListener, true);
+                   removeTask(taskView.getTask(), draggedIndex, onEndListener, true);
                }
                int pageToSnapTo = mCurrentPage;
                if (draggedIndex < pageToSnapTo) {
@@ -872,7 +884,7 @@
             if (onEndListener.isSuccess) {
                 while (getChildCount() != 0) {
                     TaskView taskView = getPageAt(getChildCount() - 1);
-                    removeTask(taskView.getTask(), onEndListener, false);
+                    removeTask(taskView.getTask(), -1, onEndListener, false);
                     removeView(taskView);
                 }
                 onAllTasksRemoved();
@@ -1204,7 +1216,7 @@
                 Task task = tv.getTask();
                 if (task != null) {
                     mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
-                            onEndListener.logAction, Direction.DOWN,
+                            onEndListener.logAction, Direction.DOWN, indexOfChild(tv),
                             TaskUtils.getComponentKeyForTask(task.key));
                 }
             } else {
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 69b77b4..24afd48 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -28,6 +28,9 @@
 import android.graphics.Path;
 import android.graphics.Path.Direction;
 import android.graphics.Path.Op;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
 import android.util.AttributeSet;
 
 import com.android.launcher3.DeviceProfile;
@@ -48,6 +51,7 @@
     private static final int THRESHOLD_ALPHA_DARK = 102;
     private static final int THRESHOLD_ALPHA_LIGHT = 46;
     private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128;
+    private static final int CLEAR_ALL_TASKS = R.string.recents_clear_all;
 
     // In transposed layout, we simply draw a flat color.
     private boolean mDrawingFlatColor;
@@ -213,4 +217,43 @@
                 mRadius, mRadius, mPaint);
         return minTop - mDragHandleSize - top;
     }
+
+    @NonNull
+    @Override
+    protected AccessibilityHelper createAccessibilityHelper() {
+        return new ShelfScrimAccessibilityHelper();
+    }
+
+    protected class ShelfScrimAccessibilityHelper extends AccessibilityHelper {
+        @Override
+        protected void onPopulateNodeForVirtualView(int virtualViewId,
+                AccessibilityNodeInfoCompat node) {
+            super.onPopulateNodeForVirtualView(virtualViewId, node);
+
+            if (mLauncher.isInState(OVERVIEW)) {
+                final RecentsView overviewPanel = mLauncher.getOverviewPanel();
+                if (overviewPanel.getChildCount() != 0) {
+                    node.addAction(
+                            new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+                                    CLEAR_ALL_TASKS,
+                                    getContext().getText(CLEAR_ALL_TASKS)));
+                }
+            }
+        }
+
+        @Override
+        protected boolean onPerformActionForVirtualView(
+                int virtualViewId, int action, Bundle arguments) {
+            if (super.onPerformActionForVirtualView(virtualViewId, action, arguments)) return true;
+
+            if (action == CLEAR_ALL_TASKS) {
+                if (mLauncher.isInState(OVERVIEW)) {
+                    mLauncher.<RecentsView>getOverviewPanel().dismissAllTasks();
+                }
+                return true;
+            }
+
+            return false;
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 4b2ca45..0ddeae7 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -110,13 +110,6 @@
 
     public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        setOnClickListener((view) -> {
-            if (mTask != null) {
-                launchTask(true /* animate */);
-                BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
-                        Touch.TAP, Direction.NONE, TaskUtils.getComponentKeyForTask(mTask.key));
-            }
-        });
         setOutlineProvider(new TaskOutlineProvider(getResources()));
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bf73149..e851499 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -240,7 +240,6 @@
     private PendingRequestArgs mPendingRequestArgs;
 
     public ViewGroupFocusHelper mFocusHandler;
-    private boolean mAppLaunchSuccess;
 
     private RotationHelper mRotationHelper;
 
@@ -730,10 +729,8 @@
         }
         mAppWidgetHost.setListenIfResumed(false);
 
-        if (!mAppLaunchSuccess) {
-            getUserEventDispatcher().logActionCommand(Action.Command.STOP,
-                    mStateManager.getState().containerType, -1);
-        }
+        getUserEventDispatcher().logActionCommand(Action.Command.STOP,
+                mStateManager.getState().containerType, -1);
         NotificationListener.removeNotificationsChangedListener();
         getStateManager().moveToRestState();
 
@@ -760,7 +757,6 @@
         super.onResume();
         TraceHelper.partitionSection("ON_RESUME", "superCall");
 
-        mAppLaunchSuccess = false;
         getUserEventDispatcher().resetElapsedSessionMillis();
         setOnResumeCallback(null);
         // Process any items that were added while Launcher was away.
@@ -1634,8 +1630,8 @@
     }
 
     public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
-        mAppLaunchSuccess = super.startActivitySafely(v, intent, item);
-        if (mAppLaunchSuccess && v instanceof BubbleTextView) {
+        boolean success = super.startActivitySafely(v, intent, item);
+        if (success && v instanceof BubbleTextView) {
             // This is set to the view that launched the activity that navigated the user away
             // from launcher. Since there is no callback for when the activity has finished
             // launching, enable the press state and keep this reference to reset the press
@@ -1644,7 +1640,7 @@
             btv.setStayPressed(true);
             setOnResumeCallback(btv);
         }
-        return mAppLaunchSuccess;
+        return success;
     }
 
     boolean isHotseatLayout(View layout) {
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 442691f..83593aa 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -131,6 +131,9 @@
                     + "), pageIdx=" + t.pageIndex;
 
         }
+        if (t.itemType == ItemType.TASK) {
+            typeStr += ", pageIdx=" + t.pageIndex;
+        }
         return typeStr;
     }
 
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 07e1315..850c948 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -132,6 +132,7 @@
     private boolean mIsInLandscapeMode;
     private String mUuidStr;
     protected InstantAppResolver mInstantAppResolver;
+    private boolean mAppOrTaskLaunch;
 
     //                      APP_ICON    SHORTCUT    WIDGET
     // --------------------------------------------------------------
@@ -163,11 +164,13 @@
             fillIntentInfo(event.srcTarget[0], intent);
         }
         dispatchUserEvent(event, intent);
+        mAppOrTaskLaunch = true;
     }
 
     public void logActionTip(int actionType, int viewType) { }
 
-    public void logTaskLaunchOrDismiss(int action, int direction, ComponentKey componentKey) {
+    public void logTaskLaunchOrDismiss(int action, int direction, int taskIndex,
+            ComponentKey componentKey) {
         LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE or FLING
                 newTarget(Target.Type.ITEM));
         if (action == Action.Touch.SWIPE || action == Action.Touch.FLING) {
@@ -175,8 +178,10 @@
             event.action.dir = direction;
         }
         event.srcTarget[0].itemType = LauncherLogProto.ItemType.TASK;
+        event.srcTarget[0].pageIndex = taskIndex;
         fillComponentInfo(event.srcTarget[0], componentKey.componentName);
         dispatchUserEvent(event, null);
+        mAppOrTaskLaunch = true;
     }
 
     protected void fillIntentInfo(Target target, Intent intent) {
@@ -211,6 +216,11 @@
 
     public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
         LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget);
+        if (command == Action.Command.STOP && mAppOrTaskLaunch) {
+            // Prevent double logging by skipping STOP when app or task has been launched.
+            return;
+        }
+
         if (dstTarget != null) {
             event.destTarget = new Target[1];
             event.destTarget[0] = dstTarget;
@@ -405,6 +415,7 @@
     }
 
     public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
+        mAppOrTaskLaunch = false;
         ev.isInLandscapeMode = mIsInLandscapeMode;
         ev.isInMultiWindowMode = mIsInMultiWindowMode;
         ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
@@ -413,7 +424,8 @@
         if (!IS_VERBOSE) {
             return;
         }
-        String log = "\n\naction:" + LoggerUtils.getActionStr(ev.action);
+        String log = "\n-----------------------------------------------------"
+                + "\naction:" + LoggerUtils.getActionStr(ev.action);
         if (ev.srcTarget != null && ev.srcTarget.length > 0) {
             log += "\n Source " + getTargetsStr(ev.srcTarget);
         }
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 5dcfe4a..49e96be 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -38,6 +38,7 @@
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
@@ -113,12 +114,17 @@
                 .getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
         mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
 
-        mAccessibilityHelper = new AccessibilityHelper();
+        mAccessibilityHelper = createAccessibilityHelper();
         ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
 
         mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
     }
 
+    @NonNull
+    protected AccessibilityHelper createAccessibilityHelper() {
+        return new AccessibilityHelper();
+    }
+
     @Override
     public void setInsets(Rect insets) {
         updateDragHandleBounds();
@@ -190,6 +196,9 @@
         if (mCurrentFlatColor != 0) {
             canvas.drawColor(mCurrentFlatColor);
         }
+        if (mDragHandle != null) {
+            mDragHandle.draw(canvas);
+        }
     }
 
     @Override
@@ -323,7 +332,7 @@
                 : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
     }
 
-    private class AccessibilityHelper extends ExploreByTouchHelper {
+    protected class AccessibilityHelper extends ExploreByTouchHelper {
 
         private static final int DRAG_HANDLE_ID = 1;