Merge "[Search][Layout] Fix blank space when predictions are disabled" into sc-dev
diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml
index c61610a..1ee726e 100644
--- a/quickstep/res/layout/overview_clear_all_button.xml
+++ b/quickstep/res/layout/overview_clear_all_button.xml
@@ -21,5 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/recents_clear_all"
-    android:textColor="?attr/workspaceTextColor"
+    android:textColor="?android:attr/textColorPrimary"
     android:textSize="14sp" />
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index 394e880..d7bcd9e 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -19,8 +19,7 @@
         android:id="@+id/split_placeholder"
         android:layout_width="match_parent"
         android:layout_height="@dimen/split_placeholder_size"
-        android:background="@android:color/white"
-        android:alpha=".8"
+        android:background="@android:color/darker_gray"
         android:visibility="gone" />
 
     <com.android.quickstep.views.LauncherRecentsView
@@ -30,7 +29,6 @@
         android:accessibilityPaneTitle="@string/accessibility_recent_apps"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:theme="@style/HomeScreenElementTheme"
         android:visibility="invisible" />
 
     <include
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 085db6d..e9ded8a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -92,6 +92,7 @@
     private final TaskbarStateHandler mTaskbarStateHandler = new TaskbarStateHandler(this);
     // Will be updated when dragging from taskbar.
     private @Nullable DragOptions mNextWorkspaceDragOptions = null;
+    private SplitPlaceholderView mSplitPlaceholderView;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -215,12 +216,12 @@
 
         SysUINavigationMode.INSTANCE.get(this).updateMode();
         mActionsView = findViewById(R.id.overview_actions_view);
-        SplitPlaceholderView splitPlaceholderView = findViewById(R.id.split_placeholder);
+        mSplitPlaceholderView = findViewById(R.id.split_placeholder);
         RecentsView overviewPanel = (RecentsView) getOverviewPanel();
-        splitPlaceholderView.init(
+        mSplitPlaceholderView.init(
                 new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this))
         );
-        overviewPanel.init(mActionsView, splitPlaceholderView);
+        overviewPanel.init(mActionsView, mSplitPlaceholderView);
         mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
 
         mAppTransitionManager = new QuickstepTransitionManager(this);
@@ -256,6 +257,10 @@
         return (T) mActionsView;
     }
 
+    public SplitPlaceholderView getSplitPlaceholderView() {
+        return mSplitPlaceholderView;
+    }
+
     @Override
     protected void closeOpenViews(boolean animate) {
         super.closeOpenViews(animate);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index d36af09..a3a1fef 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -116,6 +116,11 @@
                 config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
         setter.setFloat(scrim, SCRIM_MULTIPLIER, 1f,
                 config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
+        if (toState.areElementsVisible(mLauncher, LauncherState.SPLIT_PLACHOLDER_VIEW)) {
+            scrim.updateStableScrimmedView(mLauncher.getSplitPlaceholderView());
+        } else {
+            scrim.updateStableScrimmedView(mLauncher.getOverviewPanel());
+        }
 
         setter.setFloat(
                 mRecentsView, getTaskModalnessProperty(),
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 6929b5d..9097c8b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -113,7 +113,7 @@
                         ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
 
         float splitPlaceholderAlpha = state.areElementsVisible(mLauncher, SPLIT_PLACHOLDER_VIEW) ?
-                1 : 0;
+                0.7f : 0;
         propertySetter.setFloat(mRecentsView.getSplitPlaceholder(), ALPHA_FLOAT,
                 splitPlaceholderAlpha, LINEAR);
     }
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 0f2d778..2285d74 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -19,9 +19,12 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
 
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
+import android.app.Activity;
+import android.app.ActivityOptions;
 import android.app.prediction.AppTarget;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -37,11 +40,13 @@
 import android.graphics.RectF;
 import android.net.Uri;
 import android.util.Log;
+import android.view.View;
 
 import androidx.annotation.UiThread;
 import androidx.annotation.WorkerThread;
 import androidx.core.content.FileProvider;
 
+import com.android.internal.app.ChooserActivity;
 import com.android.launcher3.BuildConfig;
 import com.android.quickstep.SystemUiProxy;
 import com.android.systemui.shared.recents.model.Task;
@@ -126,6 +131,22 @@
     }
 
     /**
+     * Launch the activity to share image with shared element transition.
+     */
+    @UiThread
+    public static void startShareActivity(Context context, Supplier<Bitmap> bitmapSupplier,
+            Rect crop, Intent intent, String tag, View sharedElement) {
+        if (bitmapSupplier.get() == null) {
+            Log.e(tag, "No snapshot available, not starting share.");
+            return;
+        }
+
+        UI_HELPER_EXECUTOR.execute(() -> persistBitmapAndStartActivity(context,
+                bitmapSupplier.get(), crop, intent, ImageActionUtils::getShareIntentForImageUri,
+                tag, sharedElement));
+    }
+
+    /**
      * Starts activity based on given intent created from image uri.
      */
     @WorkerThread
@@ -142,6 +163,30 @@
     }
 
     /**
+     * Starts activity based on given intent created from image uri with shared element transition.
+     */
+    @WorkerThread
+    public static void persistBitmapAndStartActivity(Context context, Bitmap bitmap, Rect crop,
+            Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag,
+            View scaledImage) {
+        Intent[] intents = uriToIntentMap.apply(getImageUri(bitmap, crop, context, tag), intent);
+
+        // Work around b/159412574
+        if (intents.length == 1) {
+            MAIN_EXECUTOR.execute(() -> context.startActivity(intents[0],
+                    ActivityOptions.makeSceneTransitionAnimation((Activity) context, scaledImage,
+                            ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle()));
+
+        } else {
+            MAIN_EXECUTOR.execute(() -> context.startActivities(intents,
+                    ActivityOptions.makeSceneTransitionAnimation((Activity) context, scaledImage,
+                            ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle()));
+        }
+    }
+
+
+
+    /**
      * Converts image bitmap to Uri by temporarily saving bitmap to cache, and creating Uri pointing
      * to that location. Used to be able to share an image with another app.
      *
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index 1544f00..6d6e802 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -26,6 +26,7 @@
 import android.content.SharedPreferences;
 
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.hybridhotseat.HotseatPredictionController;
@@ -63,7 +64,8 @@
             });
         }
 
-        if (!hasReachedMaxCount(HOTSEAT_DISCOVERY_TIP_COUNT)) {
+        if (!Utilities.IS_RUNNING_IN_TEST_HARNESS
+                && !hasReachedMaxCount(HOTSEAT_DISCOVERY_TIP_COUNT)) {
             stateManager.addStateListener(new StateListener<LauncherState>() {
                 boolean mFromAllApps = false;
 
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index b62a029..3c171fe 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -559,6 +559,7 @@
                 .getDimension(R.dimen.recents_empty_message_text_size));
         mEmptyMessagePaint.setTypeface(Typeface.create(Themes.getDefaultBodyFont(context),
                 Typeface.NORMAL));
+        mEmptyMessagePaint.setAntiAlias(true);
         mEmptyMessagePadding = getResources()
                 .getDimensionPixelSize(R.dimen.recents_empty_message_text_padding);
         setWillNotDraw(false);
diff --git a/res/xml/size_limits_80x104.xml b/res/xml/size_limits_80x104.xml
index e11bc5e..f375549 100644
--- a/res/xml/size_limits_80x104.xml
+++ b/res/xml/size_limits_80x104.xml
@@ -36,11 +36,11 @@
             launcher:a="0"
             launcher:b="16dp"/>
         <workspaceBottomPadding
-            launcher:a="0.50"
+            launcher:a="0.56"
             launcher:b="0"
             launcher:c="16dp"/>
         <hotseatBottomPadding
-            launcher:a="0.50"
+            launcher:a="0.44"
             launcher:b="0"
             launcher:c="16dp"/>
     </device-padding>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ecaff7a..df5f953 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -60,6 +60,10 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.content.ActivityNotFoundException;
@@ -373,6 +377,44 @@
                     .build());
         }
 
+        if (Utilities.IS_DEBUG_DEVICE && FeatureFlags.NOTIFY_CRASHES.get()) {
+            final String notificationChannelId = "com.android.launcher3.Debug";
+            final String notificationChannelName = "Debug";
+            final String notificationTag = "Debug";
+            final int notificationId = 0;
+
+            NotificationManager notificationManager = getSystemService(NotificationManager.class);
+            notificationManager.createNotificationChannel(new NotificationChannel(
+                    notificationChannelId, notificationChannelName,
+                    NotificationManager.IMPORTANCE_HIGH));
+
+            Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> {
+                String stackTrace = Log.getStackTraceString(throwable);
+
+                Intent shareIntent = new Intent(Intent.ACTION_SEND);
+                shareIntent.setType("text/plain");
+                shareIntent.putExtra(Intent.EXTRA_TEXT, stackTrace);
+                shareIntent = Intent.createChooser(shareIntent, null);
+                PendingIntent sharePendingIntent = PendingIntent.getActivity(
+                        this, 0, shareIntent, PendingIntent.FLAG_UPDATE_CURRENT
+                );
+
+                Notification notification = new Notification.Builder(this, notificationChannelId)
+                        .setSmallIcon(android.R.drawable.ic_menu_close_clear_cancel)
+                        .setContentTitle("Launcher crash detected!")
+                        .setStyle(new Notification.BigTextStyle().bigText(stackTrace))
+                        .addAction(android.R.drawable.ic_menu_share, "Share", sharePendingIntent)
+                        .build();
+                notificationManager.notify(notificationTag, notificationId, notification);
+
+                Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler =
+                        Thread.getDefaultUncaughtExceptionHandler();
+                if (defaultUncaughtExceptionHandler != null) {
+                    defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
+                }
+            });
+        }
+
         super.onCreate(savedInstanceState);
 
         LauncherAppState app = LauncherAppState.getInstance(this);
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index c7f0133..f5fbe2b 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -218,6 +218,9 @@
     public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag(
             "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
 
+    public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
+            "Sends a notification whenever launcher encounters an uncaught exception.");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/graphics/OverviewScrim.java b/src/com/android/launcher3/graphics/OverviewScrim.java
index 7d52744..7aadb96 100644
--- a/src/com/android/launcher3/graphics/OverviewScrim.java
+++ b/src/com/android/launcher3/graphics/OverviewScrim.java
@@ -66,6 +66,13 @@
         mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
     }
 
+    /**
+     * @param view The view we want the scrim to be behind
+     */
+    public void updateStableScrimmedView(View view) {
+        mStableScrimmedView = view;
+    }
+
     public void updateCurrentScrimmedView(ViewGroup root) {
         // Find the lowest view that is at or above the view we want to show the scrim behind.
         mCurrentScrimmedView = mStableScrimmedView;
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 19dfe15..dd5611e 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -24,7 +24,6 @@
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_SIDE;
 
 import android.content.res.Resources;
 import android.graphics.PointF;
@@ -45,7 +44,7 @@
 import com.android.launcher3.util.OverScroller;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class LandscapePagedViewHandler implements PagedOrientationHandler {
@@ -308,15 +307,10 @@
 
     @Override
     public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
-        List<SplitPositionOption> options = new ArrayList<>(2);
-        // Add left/right options where left => position top, right => position bottom
-        options.add(new SplitPositionOption(
+        // Add "left" side of phone which is actually the top
+        return Collections.singletonList(new SplitPositionOption(
                 R.drawable.ic_split_screen, R.string.split_screen_position_left,
                 STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
-        options.add(new SplitPositionOption(
-                R.drawable.ic_split_screen, R.string.split_screen_position_right,
-                STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_SIDE));
-        return options;
     }
 
     @Override
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 29be627..2ca0340 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -306,16 +306,17 @@
 
     @Override
     public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
-        List<SplitPositionOption> options = new ArrayList<>(2);
+        List<SplitPositionOption> options = new ArrayList<>(1);
         // TODO: Add in correct icons
-        if (dp.isLandscape) { // or seascape
+        if (dp.isSeascape()) { // or seascape
             // Add left/right options
             options.add(new SplitPositionOption(
+                    R.drawable.ic_split_screen, R.string.split_screen_position_right,
+                    STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+        } else if (dp.isLandscape) {
+            options.add(new SplitPositionOption(
                     R.drawable.ic_split_screen, R.string.split_screen_position_left,
                     STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
-            options.add(new SplitPositionOption(
-                    R.drawable.ic_split_screen, R.string.split_screen_position_right,
-                    STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_SIDE));
         } else {
             // Only add top option
             options.add(new SplitPositionOption(
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index b5252f7..bd6e31b 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -20,7 +20,6 @@
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_SIDE;
 
 import android.content.res.Resources;
 import android.graphics.PointF;
@@ -33,7 +32,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
@@ -96,15 +95,10 @@
 
     @Override
     public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
-        List<SplitPositionOption> options = new ArrayList<>(2);
-        // Add left/right options where left => position bottom, right => position top
-        options.add(new SplitPositionOption(
-                R.drawable.ic_split_screen, R.string.split_screen_position_left,
-                STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_SIDE));
-        options.add(new SplitPositionOption(
+        // Add "right" option which is actually the top
+        return Collections.singletonList(new SplitPositionOption(
                 R.drawable.ic_split_screen, R.string.split_screen_position_right,
                 STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
-        return options;
     }
 
     /* ---------- The following are only used by TaskViewTouchHandler. ---------- */