Merge "Disable Database overwrite upon restore"
diff --git a/Android.mk b/Android.mk
index 349a134..503f9ae 100644
--- a/Android.mk
+++ b/Android.mk
@@ -208,11 +208,13 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src) \
     $(call all-java-files-under, quickstep/src) \
-    $(call all-java-files-under, go/src)
+    $(call all-java-files-under, go/src) \
+    $(call all-java-files-under, go/quickstep/src)
 
 LOCAL_RESOURCE_DIR := \
     $(LOCAL_PATH)/quickstep/res \
-    $(LOCAL_PATH)/go/res
+    $(LOCAL_PATH)/go/res \
+    $(LOCAL_PATH)/go/quickstep/res
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 LOCAL_PROGUARD_ENABLED := full
@@ -225,7 +227,7 @@
 
 LOCAL_FULL_LIBS_MANIFEST_FILES := \
     $(LOCAL_PATH)/go/AndroidManifest.xml \
-    $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
+    $(LOCAL_PATH)/go/AndroidManifest-launcher.xml \
     $(LOCAL_PATH)/AndroidManifest-common.xml
 
 LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
diff --git a/go/AndroidManifest-launcher.xml b/go/AndroidManifest-launcher.xml
new file mode 100644
index 0000000..2223036
--- /dev/null
+++ b/go/AndroidManifest-launcher.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2020, 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.
+*/
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.launcher3">
+    <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
+    <!--
+    Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
+    Refer comments around specific entries on how to extend individual components.
+    -->
+
+    <application
+        android:backupAgent="com.android.launcher3.LauncherBackupAgent"
+        android:fullBackupOnly="true"
+        android:fullBackupContent="@xml/backupscheme"
+        android:hardwareAccelerated="true"
+        android:icon="@drawable/ic_launcher_home"
+        android:label="@string/derived_app_name"
+        android:theme="@style/AppTheme"
+        android:largeHeap="@bool/config_largeHeap"
+        android:restoreAnyVersion="true"
+        android:supportsRtl="true" >
+
+        <!--
+        Main launcher activity. When extending only change the name, and keep all the
+        attributes and intent filters the same
+        -->
+        <activity
+            android:name="com.android.launcher3.Launcher3QuickStepGo"
+            android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true"
+            android:stateNotNeeded="true"
+            android:windowSoftInputMode="adjustPan"
+            android:screenOrientation="unspecified"
+            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
+            android:resizeableActivity="true"
+            android:resumeWhilePausing="true"
+            android:taskAffinity=""
+            android:exported="true"
+            android:enabled="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY"/>
+                <category android:name="android.intent.category.LAUNCHER_APP" />
+            </intent-filter>
+            <meta-data
+                android:name="com.android.launcher3.grid.control"
+                android:value="${packageName}.grid_control" />
+        </activity>
+
+    </application>
+</manifest>
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
new file mode 100644
index 0000000..f376774
--- /dev/null
+++ b/go/quickstep/res/values/config.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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="app_sharing_component" translatable="false"/>
+</resources>
\ No newline at end of file
diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml
new file mode 100644
index 0000000..fdd8397
--- /dev/null
+++ b/go/quickstep/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<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>
+</resources>
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
new file mode 100644
index 0000000..b72e71c
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 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.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+
+import androidx.core.content.FileProvider;
+
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.SystemShortcut;
+
+import java.io.File;
+
+/**
+ * Defines the Share system shortcut and its factory.
+ * This shortcut can be added to the app long-press menu on the home screen.
+ * Clicking the button will initiate peer-to-peer sharing of the app.
+ */
+public final class AppSharing {
+    /**
+     * This flag enables this feature. It is defined here rather than in launcher3's FeatureFlags
+     * because it is unique to Go and not toggleable at runtime.
+     */
+    public static final boolean ENABLE_APP_SHARING = true;
+
+    private static final String TAG = "AppSharing";
+    private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider";
+    private static final String APP_EXSTENSION = ".apk";
+    private static final String APP_MIME_TYPE = "application/application";
+
+    private final String mSharingComponent;
+
+    private AppSharing(Launcher launcher) {
+        mSharingComponent = launcher.getText(R.string.app_sharing_component).toString();
+    }
+
+    private boolean canShare(ItemInfo info) {
+        /**
+         * TODO: Implement once b/168831749 has been resolved
+         * The implementation should check the validity of the app.
+         * It should also check whether the app is free or paid, returning false in the latter case.
+         * For now, all checks occur in the sharing app.
+         * So, we simply check whether the sharing app is defined.
+         */
+        return !TextUtils.isEmpty(mSharingComponent);
+    }
+
+    private Uri getShareableUri(Context context, String path, String displayName) {
+        String authority = BuildConfig.APPLICATION_ID + FILE_PROVIDER_SUFFIX;
+        File pathFile = new File(path);
+        return FileProvider.getUriForFile(context, authority, pathFile, displayName);
+    }
+
+    private SystemShortcut<Launcher> getShortcut(Launcher launcher, ItemInfo info) {
+        if (!canShare(info)) {
+            return null;
+        }
+
+        return new Share(launcher, info);
+    }
+
+    /**
+     * The Share App system shortcut, used to initiate p2p sharing of a given app
+     */
+    public final class Share extends SystemShortcut<Launcher> {
+        public Share(Launcher target, ItemInfo itemInfo) {
+            super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo);
+        }
+
+        @Override
+        public void onClick(View view) {
+            Intent sendIntent = new Intent();
+            sendIntent.setAction(Intent.ACTION_SEND);
+
+            ComponentName targetComponent = mItemInfo.getTargetComponent();
+            if (targetComponent == null) {
+                Log.e(TAG, "Item missing target component");
+                return;
+            }
+            String packageName = targetComponent.getPackageName();
+            PackageManager packageManager = view.getContext().getPackageManager();
+            String sourceDir, appLabel;
+            try {
+                PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
+                sourceDir = packageInfo.applicationInfo.sourceDir;
+                appLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo)
+                        .toString() + APP_EXSTENSION;
+            } catch (Exception e) {
+                Log.e(TAG, "Could not find info for package \"" + packageName + "\"");
+                return;
+            }
+            Uri uri = getShareableUri(view.getContext(), sourceDir, appLabel);
+            sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
+            sendIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+
+            sendIntent.setType(APP_MIME_TYPE);
+            sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent));
+
+            mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+
+            AbstractFloatingView.closeAllOpenViews(mTarget);
+        }
+    }
+
+    /**
+     * Shortcut factory for generating the Share App button
+     */
+    public static final SystemShortcut.Factory<Launcher> SHORTCUT_FACTORY = (launcher, itemInfo) ->
+            (new AppSharing(launcher)).getShortcut(launcher, itemInfo);
+}
diff --git a/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java
new file mode 100644
index 0000000..8bd0fec
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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 com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+
+import java.util.stream.Stream;
+
+/**
+ * The Launcher variant used for Android Go Edition
+ */
+public class Launcher3QuickStepGo extends QuickstepLauncher {
+    private static final String TAG = "Launcher3QuickStepGo";
+
+    @Override
+    public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
+        Stream<SystemShortcut.Factory> shortcuts = super.getSupportedShortcuts();
+
+        if (AppSharing.ENABLE_APP_SHARING) {
+            shortcuts = Stream.concat(shortcuts, Stream.of(AppSharing.SHORTCUT_FACTORY));
+        }
+
+        return shortcuts;
+    }
+}
diff --git a/quickstep/res/drawable/default_sandbox_app_icon.xml b/quickstep/res/drawable/default_sandbox_app_icon.xml
new file mode 100644
index 0000000..e9c9701
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_app_icon.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+  <solid android:color="@color/gesture_tutorial_fake_task_view_color" />
+</shape>
diff --git a/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml b/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml
new file mode 100644
index 0000000..9d4cc95
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+  <solid android:color="@color/gesture_tutorial_fake_task_view_color" />
+</shape>
diff --git a/quickstep/res/drawable/default_sandbox_wallpaper.xml b/quickstep/res/drawable/default_sandbox_wallpaper.xml
new file mode 100644
index 0000000..816d1d6
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_wallpaper.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+  <solid android:color="?android:attr/colorBackground" />
+</shape>
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 52475df..2ff3a5e 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -16,8 +16,7 @@
 <com.android.quickstep.interaction.RootSandboxLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="?android:attr/colorBackground">
+    android:layout_height="match_parent">
 
     <View
         android:id="@+id/gesture_tutorial_ripple_view"
@@ -29,15 +28,12 @@
         android:id="@+id/gesture_tutorial_fake_icon_view"
         android:layout_width="20dp"
         android:layout_height="20dp"
-        android:background="@drawable/bg_circle"
-        android:backgroundTint="@color/gesture_tutorial_fake_task_view_color"
         android:visibility="invisible" />
 
     <View
         android:id="@+id/gesture_tutorial_fake_task_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/gesture_tutorial_fake_task_view_color"
         android:visibility="invisible" />
 
     <ImageView
diff --git a/quickstep/res/xml/overview_file_provider_paths.xml b/quickstep/res/xml/overview_file_provider_paths.xml
index 14d7459..07e3236 100644
--- a/quickstep/res/xml/overview_file_provider_paths.xml
+++ b/quickstep/res/xml/overview_file_provider_paths.xml
@@ -2,4 +2,5 @@
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <cache-path name="shared_images" path="/" />
     <files-path name="log_files" path="/" />
+    <root-path name="apps" path="/" />
 </paths>
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
index d54efc5..4c1a595 100644
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
@@ -46,7 +46,7 @@
     @Nullable
     @Override
     Integer getActionButtonStringId() {
-        return R.string.gesture_tutorial_action_button_label_done;
+        return null;
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 2198ade..0d5a110 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -25,8 +25,10 @@
 import android.widget.TextView;
 
 import androidx.annotation.CallSuper;
+import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.views.ClipIconView;
 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
@@ -63,13 +65,13 @@
         mTutorialType = tutorialType;
         mContext = mTutorialFragment.getContext();
 
-        View rootView = tutorialFragment.getRootView();
+        RootSandboxLayout rootView = tutorialFragment.getRootView();
         mCloseButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
         mCloseButton.setOnClickListener(button -> mTutorialFragment.closeTutorial());
         mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
         mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
         mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
-        mLauncherView = tutorialFragment.getLauncherView();
+        mLauncherView = getMockLauncherView();
         mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
         mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
         mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
@@ -84,6 +86,15 @@
         mHideFeedbackRunnable =
                 () -> mFeedbackView.animate().alpha(0).setDuration(FEEDBACK_ANIMATION_MS)
                         .withEndAction(this::showHandCoachingAnimation).start();
+
+        if (mLauncherView != null) {
+            rootView.addView(mLauncherView, 0);
+        }
+        if (mContext != null) {
+            rootView.setBackground(mContext.getDrawable(getMockWallpaperResId()));
+            mFakeTaskView.setBackground(mContext.getDrawable(getMockAppTaskThumbnailResId()));
+            mFakeIconView.setBackground(mContext.getDrawable(getMockAppIconResId()));
+        }
     }
 
     void setTutorialType(TutorialType tutorialType) {
@@ -110,6 +121,28 @@
         return null;
     }
 
+    @DrawableRes
+    protected int getMockAppTaskThumbnailResId() {
+        return R.drawable.default_sandbox_app_task_thumbnail;
+    }
+
+    @Nullable
+    public View getMockLauncherView() {
+        InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext);
+
+        return new SandboxLauncherRenderer(mContext, dp, true).getRenderedView();
+    }
+
+    @DrawableRes
+    public int getMockAppIconResId() {
+        return R.drawable.default_sandbox_app_icon;
+    }
+
+    @DrawableRes
+    public int getMockWallpaperResId() {
+        return R.drawable.default_sandbox_wallpaper;
+    }
+
     void showFeedback(int resId) {
         hideHandCoachingAnimation();
         mFeedbackView.setText(resId);
@@ -167,10 +200,11 @@
 
         if (isComplete()) {
             hideHandCoachingAnimation();
-            mLauncherView.setVisibility(View.INVISIBLE);
         } else {
             showHandCoachingAnimation();
-            mLauncherView.setVisibility(View.VISIBLE);
+        }
+        if (mLauncherView != null) {
+            mLauncherView.setVisibility(isComplete() ? View.INVISIBLE : View.VISIBLE);
         }
     }
 
@@ -213,8 +247,7 @@
         return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
                 || mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
                 || mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
-                || mTutorialType == TutorialType.ASSISTANT_COMPLETE
-                || mTutorialType == TutorialType.SANDBOX_MODE;
+                || mTutorialType == TutorialType.ASSISTANT_COMPLETE;
     }
 
     /** Denotes the type of the tutorial. */
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 608fe72..413387e 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -31,7 +31,6 @@
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 
-import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.R;
 import com.android.quickstep.interaction.TutorialController.TutorialType;
 
@@ -42,11 +41,10 @@
 
     TutorialType mTutorialType;
     @Nullable TutorialController mTutorialController = null;
-    View mRootView;
+    RootSandboxLayout mRootView;
     @Nullable TutorialHandAnimation mHandCoachingAnimation = null;
     EdgeBackGestureHandler mEdgeBackGestureHandler;
     NavBarGestureHandler mNavBarGestureHandler;
-    private View mLauncherView;
 
     public static TutorialFragment newInstance(TutorialType tutorialType) {
         TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@@ -114,7 +112,8 @@
             @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         super.onCreateView(inflater, container, savedInstanceState);
 
-        mRootView = inflater.inflate(R.layout.gesture_tutorial_fragment, container, false);
+        mRootView = (RootSandboxLayout) inflater.inflate(
+                R.layout.gesture_tutorial_fragment, container, false);
         mRootView.setOnApplyWindowInsetsListener((view, insets) -> {
             Insets systemInsets = insets.getInsets(WindowInsets.Type.systemBars());
             mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
@@ -126,9 +125,6 @@
             mHandCoachingAnimation =
                 new TutorialHandAnimation(getContext(), mRootView, handAnimationResId);
         }
-        InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext());
-        mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView();
-        ((ViewGroup) mRootView).addView(mLauncherView, 0);
         return mRootView;
     }
 
@@ -161,7 +157,7 @@
     }
 
     void onAttachedToWindow() {
-        mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
+        mEdgeBackGestureHandler.setViewGroupParent(getRootView());
     }
 
     void onDetachedFromWindow() {
@@ -186,14 +182,10 @@
         super.onSaveInstanceState(savedInstanceState);
     }
 
-    View getRootView() {
+    RootSandboxLayout getRootView() {
         return mRootView;
     }
 
-    View getLauncherView() {
-        return mLauncherView;
-    }
-
     @Nullable TutorialHandAnimation getHandAnimation() {
         return mHandCoachingAnimation;
     }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 3230348..1b55496 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -36,6 +36,7 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -418,15 +419,21 @@
                 if (freezeTaskList) {
                     ActivityOptionsCompat.setFreezeRecentTasksList(opts);
                 }
-                ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
-                        opts, (success) -> {
-                            if (resultCallback != null && !success) {
-                                // If the call to start activity failed, then post the result
-                                // immediately, otherwise, wait for the animation start callback
-                                // from the activity options above
-                                resultCallbackHandler.post(() -> resultCallback.accept(false));
-                            }
-                        }, resultCallbackHandler);
+                UI_HELPER_EXECUTOR.execute(
+                        () -> ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(
+                                mTask.key,
+                                opts,
+                                (success) -> {
+                                    if (resultCallback != null && !success) {
+                                        // If the call to start activity failed, then post the
+                                        // result
+                                        // immediately, otherwise, wait for the animation start
+                                        // callback
+                                        // from the activity options above
+                                        resultCallbackHandler.post(
+                                                () -> resultCallback.accept(false));
+                                    }
+                                }, resultCallbackHandler));
             }
         }
     }