Add NIU Actions buttons to the Go Overview

The buttons send Intents to the designated app (specified by
niu_actions_package) to do the following:
Listen - Read the contents of the screen aloud
Translate - Translate the contents of the screen
Search - Perform a visual search on the contents of the screen

The Intents also include (via URI) the screenshot of current app used as
a thumbnail by Recents.

The feature is controlled by the enable_niu_actions flag, set to false
here. Both this flag and the niu_actions_package String must be set for
a given Launcher to use these buttons.

Bug: 177955244
Bug: 177955748
Test: Manual (enabled on LauncherGoGoogle and sent Intents to demo Lens
app)

Change-Id: I3d1f870bb176ed0cbae637a45c072bd8acac1d4b
diff --git a/Android.mk b/Android.mk
index 19ad328..127df79 100644
--- a/Android.mk
+++ b/Android.mk
@@ -145,7 +145,9 @@
     $(call all-java-files-under, quickstep/src) \
     $(call all-java-files-under, src_shortcuts_overrides)
 
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/quickstep/res \
+    $(LOCAL_PATH)/quickstep/overview_ui_overrides/res
 LOCAL_PROGUARD_ENABLED := disabled
 
 
@@ -174,7 +176,9 @@
 LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3
 LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
 
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/quickstep/res \
+    $(LOCAL_PATH)/quickstep/overview_ui_overrides/res
 
 LOCAL_FULL_LIBS_MANIFEST_FILES := \
     $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
@@ -213,7 +217,8 @@
 LOCAL_RESOURCE_DIR := \
     $(LOCAL_PATH)/quickstep/res \
     $(LOCAL_PATH)/go/res \
-    $(LOCAL_PATH)/go/quickstep/res
+    $(LOCAL_PATH)/go/quickstep/res \
+    $(LOCAL_PATH)/go/quickstep/overview_ui_overrides/res
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 LOCAL_PROGUARD_ENABLED := full
diff --git a/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml b/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml
new file mode 100644
index 0000000..b438da3
--- /dev/null
+++ b/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+<com.android.quickstep.views.GoOverviewActionsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/overview_actions_height"
+    android:layout_gravity="center_horizontal|bottom">
+
+    <LinearLayout
+        android:id="@+id/action_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:orientation="horizontal">
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="1dp"
+            android:layout_weight="1" />
+
+        <Button
+            android:id="@+id/action_listen"
+            style="@style/OverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/ic_listen"
+            android:drawablePadding="1dp"
+            android:text="@string/action_listen"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
+        <Button
+            android:id="@+id/action_translate"
+            style="@style/OverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/ic_translate"
+            android:drawablePadding="1dp"
+            android:text="@string/action_translate"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
+        <Button
+            android:id="@+id/action_search"
+            style="@style/OverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/ic_search"
+            android:drawablePadding="1dp"
+            android:text="@string/action_search"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
+        <Button
+            android:id="@+id/action_screenshot"
+            style="@style/OverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/ic_screenshot"
+            android:drawablePadding="1dp"
+            android:text="@string/action_screenshot"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="1dp"
+            android:layout_weight="1" />
+
+        <Button
+            android:id="@+id/action_share"
+            style="@style/OverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableStart="@drawable/ic_share"
+            android:text="@string/action_share"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor"
+            android:visibility="gone" />
+
+        <Space
+            android:id="@+id/oav_three_button_space"
+            android:layout_width="0dp"
+            android:layout_height="1dp"
+            android:layout_weight="1"
+            android:visibility="gone" />
+    </LinearLayout>
+
+</com.android.quickstep.views.GoOverviewActionsView>
\ No newline at end of file
diff --git a/go/quickstep/overview_ui_overrides/res/values/config.xml b/go/quickstep/overview_ui_overrides/res/values/config.xml
new file mode 100644
index 0000000..ec21a01
--- /dev/null
+++ b/go/quickstep/overview_ui_overrides/res/values/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2021 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.
+*/
+-->
+<resources>
+    <string name="task_overlay_factory_class" translatable="false">
+        com.android.quickstep.TaskOverlayFactoryGo</string>
+</resources>
\ No newline at end of file
diff --git a/go/quickstep/res/drawable/ic_listen.xml b/go/quickstep/res/drawable/ic_listen.xml
new file mode 100644
index 0000000..a8e6c93
--- /dev/null
+++ b/go/quickstep/res/drawable/ic_listen.xml
@@ -0,0 +1,32 @@
+<!-- Copyright (C) 2021 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+  <path
+      android:pathData="M10.5,15.17c2.58,0 4.67,-2.09 4.67,-4.67s-2.09,-4.67 -4.67,-4.67c-2.58,0 -4.67,2.09 -4.67,4.67S7.92,15.17 10.5,15.17zM10.5,8.17c1.28,0 2.33,1.05 2.33,2.33s-1.05,2.33 -2.33,2.33c-1.28,0 -2.33,-1.05 -2.33,-2.33S9.22,8.17 10.5,8.17z"
+      android:fillColor="#4285F4"/>
+  <path
+      android:pathData="M10.5,17.5c-3.11,0 -9.33,1.56 -9.33,4.67v2.33h18.67v-2.33C19.83,19.06 13.62,17.5 10.5,17.5zM3.5,22.17c0.26,-0.84 3.86,-2.33 7,-2.33c3.15,0 6.77,1.5 7,2.33H3.5z"
+      android:fillColor="#4285F4"/>
+  <path
+      android:pathData="M25.67,10.5c0,0.36 -0.02,0.71 -0.05,1.05c-0.01,0.15 -0.03,0.29 -0.05,0.43c-0.02,0.18 -0.05,0.36 -0.08,0.54c-0.04,0.2 -0.07,0.39 -0.12,0.58c-0.01,0.06 -0.03,0.11 -0.04,0.17c-0.59,2.34 -1.81,4.01 -2.52,4.82c-0.09,0.1 -0.18,0.2 -0.28,0.3c-0.17,0.18 -0.27,0.27 -0.27,0.27l-1.65,-1.63c1.34,-1.33 2.27,-3.07 2.6,-5.01c0.01,-0.08 0.02,-0.16 0.04,-0.24c0.06,-0.42 0.1,-0.85 0.1,-1.29c0,-0.44 -0.04,-0.88 -0.1,-1.3c-0.01,-0.06 -0.02,-0.13 -0.03,-0.19c-0.32,-1.95 -1.25,-3.7 -2.6,-5.04l1.65,-1.63c0,0 0.11,0.1 0.27,0.27c0.09,0.1 0.19,0.2 0.28,0.3c0.71,0.82 1.93,2.48 2.52,4.82c0.01,0.06 0.03,0.11 0.04,0.17c0.04,0.19 0.08,0.38 0.12,0.58c0.03,0.18 0.06,0.36 0.08,0.54c0.02,0.14 0.04,0.28 0.05,0.43C25.65,9.79 25.67,10.14 25.67,10.5z"
+      android:fillColor="#EA4335"/>
+  <path
+      android:pathData="M20.61,8.4C20.85,9.06 21,9.76 21,10.5s-0.15,1.44 -0.39,2.1c-0.28,0.77 -0.71,1.46 -1.25,2.05l-1.66,-1.64c0.56,-0.63 0.91,-1.44 0.95,-2.34c0,-0.06 0.02,-0.11 0.02,-0.17s-0.01,-0.11 -0.02,-0.17c-0.04,-0.9 -0.39,-1.71 -0.95,-2.34l1.66,-1.64C19.9,6.94 20.32,7.63 20.61,8.4z"
+      android:fillColor="#FBBC04"/>
+</vector>
diff --git a/go/quickstep/res/drawable/ic_search.xml b/go/quickstep/res/drawable/ic_search.xml
new file mode 100644
index 0000000..4307330
--- /dev/null
+++ b/go/quickstep/res/drawable/ic_search.xml
@@ -0,0 +1,32 @@
+<!-- Copyright (C) 2021 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+  <path
+      android:pathData="M24.5,22.75l-6.84,-6.84c1,-1.35 1.59,-3.02 1.59,-4.83h-2.33c0,3.22 -2.62,5.83 -5.83,5.83v2.33c1.81,0 3.47,-0.6 4.83,-1.59l6.84,6.84L24.5,22.75z"
+      android:fillColor="#4285F4"/>
+  <path
+      android:pathData="M11.08,2.92v2.33c3.22,0 5.83,2.62 5.83,5.83h2.33C19.25,6.57 15.59,2.92 11.08,2.92z"
+      android:fillColor="#34A853"/>
+  <path
+      android:pathData="M5.25,11.08H2.92c0,4.51 3.66,8.17 8.17,8.17v-2.33C7.87,16.92 5.25,14.3 5.25,11.08z"
+      android:fillColor="#EA4335"/>
+  <path
+      android:pathData="M2.92,11.08h2.33c0,-3.22 2.62,-5.83 5.83,-5.83V2.92C6.57,2.92 2.92,6.57 2.92,11.08z"
+      android:fillColor="#FBBC04"/>
+</vector>
diff --git a/go/quickstep/res/drawable/ic_translate.xml b/go/quickstep/res/drawable/ic_translate.xml
new file mode 100644
index 0000000..1247807
--- /dev/null
+++ b/go/quickstep/res/drawable/ic_translate.xml
@@ -0,0 +1,32 @@
+<!-- Copyright (C) 2021 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+  <path
+      android:pathData="M12.28,15.19l-0.07,-0.05c-0.61,-0.49 -1.15,-1.05 -1.65,-1.63c-1.05,-1.22 -1.88,-2.63 -2.39,-4.17H5.83c0.54,2.17 1.58,4.16 3.01,5.85l-5.93,5.23l1.75,1.75l5.91,-5.26c0.05,0.04 0.1,0.09 0.15,0.13l3.42,2.79l1.02,-2.33L12.28,15.19z"
+      android:fillColor="#FBBC04"/>
+  <path
+      android:pathData="M21.58,11.67h-2.33l-5.25,14h2.33l1.31,-3.5h5.54l1.32,3.5h2.33L21.58,11.67zM18.53,19.83l1.89,-5.05l1.89,5.05H18.53z"
+      android:fillColor="#4285F4"/>
+  <path
+      android:pathData="M11.67,2.33l-2.34,0l0,2.34l-8.16,0l0,2.33l10.5,0l0,-2.33z"
+      android:fillColor="#EA4335"/>
+  <path
+      android:pathData="M11.67,4.67V7H14c-0.61,2.42 -1.79,4.65 -3.44,6.5c0.5,0.59 1.04,1.15 1.65,1.63l0.07,0.05c2.03,-2.32 3.44,-5.14 4.05,-8.19h3.5V4.67H11.67z"
+      android:fillColor="#34A853"/>
+</vector>
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
index f376774..9dca137 100644
--- a/go/quickstep/res/values/config.xml
+++ b/go/quickstep/res/values/config.xml
@@ -14,5 +14,11 @@
      limitations under the License.
 -->
 <resources>
+    <!-- The component to receive app sharing Intents -->
     <string name="app_sharing_component" translatable="false"/>
+    <!-- The package to receive Listen, Translate, and Search Intents -->
+    <string name="niu_actions_package" translatable="false"/>
+
+    <!-- Feature Flags -->
+    <bool name="enable_niu_actions">false</bool>
 </resources>
\ No newline at end of file
diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml
index fdd8397..71e2f3a 100644
--- a/go/quickstep/res/values/strings.xml
+++ b/go/quickstep/res/values/strings.xml
@@ -3,4 +3,12 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Label for app share drop target. [CHAR_LIMIT=20] -->
     <string name="app_share_drop_target_label">Share App</string>
+
+    <!-- ******* Overview ******* -->
+    <!-- Label for a button that lets the user listen to the content of the current app. [CHAR_LIMIT=40] -->
+    <string name="action_listen">Listen</string>
+    <!-- Label for a button that translates a screenshot of the current app. [CHAR_LIMIT=40] -->
+    <string name="action_translate">Translate</string>
+    <!-- Label for a button that triggers Search on a screenshot of the current app. [CHAR_LIMIT=40] -->
+    <string name="action_search">Search</string>
 </resources>
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
new file mode 100644
index 0000000..b102a39
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 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.quickstep;
+
+import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
+import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Matrix;
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+import com.android.launcher3.R;
+import com.android.quickstep.views.OverviewActionsView;
+import com.android.quickstep.views.TaskThumbnailView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+/**
+ * Go-specific extension of the factory class that adds an overlay to TaskView
+ */
+public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
+    public static final String ACTION_LISTEN = "com.android.quickstep.ACTION_LISTEN";
+    public static final String ACTION_TRANSLATE = "com.android.quickstep.ACTION_TRANSLATE";
+    public static final String ACTION_SEARCH = "com.android.quickstep.ACTION_SEARCH";
+    public static final String ELAPSED_NANOS = "niu_actions_elapsed_realtime_nanos";
+
+    // Empty constructor required for ResourceBasedOverride
+    public TaskOverlayFactoryGo(Context context) {}
+
+    /**
+     * Create a new overlay instance for the given View
+     */
+    public TaskOverlayGo createOverlay(TaskThumbnailView thumbnailView) {
+        return new TaskOverlayGo(thumbnailView);
+    }
+
+    /**
+     * Overlay on each task handling Overview Action Buttons.
+     * @param <T> The type of View in which the overlay will be placed
+     */
+    public static final class TaskOverlayGo<T extends OverviewActionsView> extends TaskOverlay {
+
+        private String mPackageName;
+
+        private TaskOverlayGo(TaskThumbnailView taskThumbnailView) {
+            super(taskThumbnailView);
+        }
+
+        /**
+         * Called when the current task is interactive for the user
+         */
+        @Override
+        public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
+                boolean rotated) {
+            getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
+            mPackageName =
+                    mApplicationContext.getResources().getString(R.string.niu_actions_package);
+
+            if (thumbnail == null || TextUtils.isEmpty(mPackageName)) {
+                return;
+            }
+
+            getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
+            boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
+            getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
+        }
+
+        private void sendNIUIntent(String actionType) {
+            Intent intent = createNIUIntent(actionType);
+            mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
+        }
+
+        private Intent createNIUIntent(String actionType) {
+            return new Intent(actionType)
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+                    .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
+                    .setPackage(mPackageName)
+                    .putExtra(ELAPSED_NANOS, SystemClock.elapsedRealtimeNanos());
+        }
+
+        protected class OverlayUICallbacksGoImpl extends OverlayUICallbacksImpl
+                implements OverlayUICallbacksGo {
+            public OverlayUICallbacksGoImpl(boolean isAllowedByPolicy, Task task) {
+                super(isAllowedByPolicy, task);
+            }
+
+            @SuppressLint("NewApi")
+            public void onListen() {
+                if (mIsAllowedByPolicy) {
+                    sendNIUIntent(ACTION_LISTEN);
+                } else {
+                    showBlockedByPolicyMessage();
+                }
+            }
+
+            @SuppressLint("NewApi")
+            public void onTranslate() {
+                if (mIsAllowedByPolicy) {
+                    sendNIUIntent(ACTION_TRANSLATE);
+                } else {
+                    showBlockedByPolicyMessage();
+                }
+            }
+
+            @SuppressLint("NewApi")
+            public void onSearch() {
+                if (mIsAllowedByPolicy) {
+                    sendNIUIntent(ACTION_SEARCH);
+                } else {
+                    showBlockedByPolicyMessage();
+                }
+            }
+        }
+    }
+
+    /**
+     * Callbacks the Ui can generate. This is the only way for a Ui to call methods on the
+     * controller.
+     */
+    public interface OverlayUICallbacksGo extends OverlayUICallbacks {
+        /** User has requested to listen to the current content read aloud */
+        void onListen();
+
+        /** User has requested a translation of the current content */
+        void onTranslate();
+
+        /** User has requested a visual search of the current content */
+        void onSearch();
+    }
+}
diff --git a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
new file mode 100644
index 0000000..9997d16
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 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.quickstep.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+import com.android.quickstep.TaskOverlayFactoryGo.OverlayUICallbacksGo;
+
+/**
+ * View for showing Go-specific action buttons in Overview
+ */
+public final class GoOverviewActionsView extends OverviewActionsView<OverlayUICallbacksGo> {
+    public GoOverviewActionsView(Context context) {
+        this(context, null);
+    }
+
+    public GoOverviewActionsView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public GoOverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        if (getResources().getBoolean(R.bool.enable_niu_actions)) {
+            findViewById(R.id.action_listen).setOnClickListener(this);
+            findViewById(R.id.action_translate).setOnClickListener(this);
+            findViewById(R.id.action_search).setOnClickListener(this);
+        } else {
+            findViewById(R.id.action_listen).setVisibility(View.GONE);
+            findViewById(R.id.action_translate).setVisibility(View.GONE);
+            findViewById(R.id.action_search).setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        super.onClick(view);
+
+        if (mCallbacks == null) {
+            return;
+        }
+        int id = view.getId();
+        if (id == R.id.action_listen) {
+            mCallbacks.onListen();
+        } else if (id == R.id.action_translate) {
+            mCallbacks.onTranslate();
+        } else if (id == R.id.action_search) {
+            mCallbacks.onSearch();
+        }
+    }
+}
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml
similarity index 100%
rename from quickstep/res/layout/overview_actions_container.xml
rename to quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml
diff --git a/quickstep/overview_ui_overrides/res/values/config.xml b/quickstep/overview_ui_overrides/res/values/config.xml
new file mode 100644
index 0000000..0f09439
--- /dev/null
+++ b/quickstep/overview_ui_overrides/res/values/config.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<resources>
+    <string name="task_overlay_factory_class" translatable="false"/>
+</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 9ec303a..be66104 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -14,8 +14,6 @@
      limitations under the License.
 -->
 <resources>
-    <string name="task_overlay_factory_class" translatable="false"/>
-
     <string name="overscroll_plugin_factory_class" translatable="false" />
 
     <!-- Activities which block home gesture -->
diff --git a/quickstep/src/com/android/quickstep/ImageActionsApi.java b/quickstep/src/com/android/quickstep/ImageActionsApi.java
index cb4d53a..8cb64c2 100644
--- a/quickstep/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/src/com/android/quickstep/ImageActionsApi.java
@@ -64,6 +64,20 @@
      */
     @UiThread
     public void shareWithExplicitIntent(@Nullable Rect crop, Intent intent) {
+        addImageAndSendIntent(crop, intent, false);
+    }
+
+    /**
+     * Share the image this api was constructed with using the provided intent. The implementation
+     * should set the intent's data field to the URI pointing to the image.
+     */
+    @UiThread
+    public void shareAsDataWithExplicitIntent(@Nullable Rect crop, Intent intent) {
+        addImageAndSendIntent(crop, intent, true);
+    }
+
+    @UiThread
+    private void addImageAndSendIntent(@Nullable Rect crop, Intent intent, boolean setData) {
         if (mBitmapSupplier.get() == null) {
             Log.e(TAG, "No snapshot available, not starting share.");
             return;
@@ -71,12 +85,14 @@
 
         UI_HELPER_EXECUTOR.execute(() -> persistBitmapAndStartActivity(mContext,
                 mBitmapSupplier.get(), crop, intent, (uri, intentForUri) -> {
-                    intentForUri
-                            .addFlags(FLAG_GRANT_READ_URI_PERMISSION)
-                            .putExtra(EXTRA_STREAM, uri);
+                    intentForUri.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+                    if (setData) {
+                        intentForUri.setData(uri);
+                    } else {
+                        intentForUri.putExtra(EXTRA_STREAM, uri);
+                    }
                     return new Intent[]{intentForUri};
                 }, TAG));
-
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 93ebd5a..3befb9c 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -122,12 +122,11 @@
      */
     public static class TaskOverlay<T extends OverviewActionsView> {
 
-        private final Context mApplicationContext;
+        protected final Context mApplicationContext;
         protected final TaskThumbnailView mThumbnailView;
 
         private T mActionsView;
-        private ImageActionsApi mImageApi;
-        private boolean mIsAllowedByPolicy;
+        protected ImageActionsApi mImageApi;
 
         protected TaskOverlay(TaskThumbnailView taskThumbnailView) {
             mApplicationContext = taskThumbnailView.getContext().getApplicationContext();
@@ -153,24 +152,8 @@
 
             if (thumbnail != null) {
                 getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
-                final boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
-
-                getActionsView().setCallbacks(new OverlayUICallbacks() {
-                    @Override
-                    public void onShare() {
-                        if (isAllowedByPolicy) {
-                            endLiveTileMode(() -> mImageApi.startShareActivity(null));
-                        } else {
-                            showBlockedByPolicyMessage();
-                        }
-                    }
-
-                    @SuppressLint("NewApi")
-                    @Override
-                    public void onScreenshot() {
-                        endLiveTileMode(() -> saveScreenshot(task));
-                    }
-                });
+                boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
+                getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
             }
         }
 
@@ -193,7 +176,7 @@
          * Called to save screenshot of the task thumbnail.
          */
         @SuppressLint("NewApi")
-        private void saveScreenshot(Task task) {
+        protected void saveScreenshot(Task task) {
             if (mThumbnailView.isRealSnapshot()) {
                 mImageApi.saveScreenshot(mThumbnailView.getThumbnail(),
                         getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key);
@@ -251,7 +234,7 @@
             return mThumbnailView.getScaledInsets();
         }
 
-        private void showBlockedByPolicyMessage() {
+        protected void showBlockedByPolicyMessage() {
             Toast.makeText(
                     mThumbnailView.getContext(),
                     R.string.blocked_by_policy,
@@ -273,6 +256,29 @@
                 dismissTaskMenuView(mActivity);
             }
         }
+
+        protected class OverlayUICallbacksImpl implements OverlayUICallbacks {
+            protected final boolean mIsAllowedByPolicy;
+            protected final Task mTask;
+
+            public OverlayUICallbacksImpl(boolean isAllowedByPolicy, Task task) {
+                mIsAllowedByPolicy = isAllowedByPolicy;
+                mTask = task;
+            }
+
+            public void onShare() {
+                if (mIsAllowedByPolicy) {
+                    endLiveTileMode(() -> mImageApi.startShareActivity(null));
+                } else {
+                    showBlockedByPolicyMessage();
+                }
+            }
+
+            @SuppressLint("NewApi")
+            public void onScreenshot() {
+                endLiveTileMode(() -> saveScreenshot(mTask));
+            }
+        }
     }
 
     /**