[PS] Show "Uninstall" in Long Press menu for Private Space apps.

Video : https://b.corp.google.com/issues/319250810#comment18

- Add SecondaryDropTarget.performUninstall()
- Make SecondaryDropTarget.getUninstallTarget() public static.

Test: Manual
Flag: aconfig com.android.launcher3.enable_private_space TEAMFOOD
Bug: 319250810

Change-Id: If6488033a976914fdc0a50658fc0561dc1a6586a
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 0b92c28..1362586 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -34,6 +34,8 @@
 import android.view.View;
 import android.widget.Toast;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.logging.FileLog;
@@ -43,6 +45,7 @@
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
@@ -176,6 +179,10 @@
         if (uninstallDisabled) {
             return INVALID;
         }
+        if (Flags.enablePrivateSpace() && UserCache.getInstance(getContext()).getUserInfo(
+                info.user).isPrivate()) {
+            return INVALID;
+        }
 
         if (info instanceof ItemInfoWithIcon) {
             ItemInfoWithIcon iconInfo = (ItemInfoWithIcon) info;
@@ -184,7 +191,7 @@
                 return INVALID;
             }
         }
-        if (getUninstallTarget(info) == null) {
+        if (getUninstallTarget(getContext(), info) == null) {
             return INVALID;
         }
         return UNINSTALL;
@@ -193,7 +200,7 @@
     /**
      * @return the component name that should be uninstalled or null.
      */
-    private ComponentName getUninstallTarget(ItemInfo item) {
+    public static ComponentName getUninstallTarget(Context context, ItemInfo item) {
         Intent intent = null;
         UserHandle user = null;
         if (item != null &&
@@ -202,7 +209,7 @@
             user = item.user;
         }
         if (intent != null) {
-            LauncherActivityInfo info = getContext().getSystemService(LauncherApps.class)
+            LauncherActivityInfo info = context.getSystemService(LauncherApps.class)
                     .resolveActivity(intent, user);
             if (info != null
                     && (info.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
@@ -280,32 +287,41 @@
             if (FeatureFlags.ENABLE_DISMISS_PREDICTION_UNDO.get()) {
                 CharSequence announcement = getContext().getString(R.string.item_removed);
                 mDropTargetHandler
-                        .dismissPrediction(announcement, () -> {}, () -> {
-                    mStatsLogManager.logger()
-                            .withInstanceId(instanceId)
-                            .withItemInfo(info)
-                            .log(LAUNCHER_DISMISS_PREDICTION_UNDO);
-                });
+                        .dismissPrediction(announcement, () -> {
+                        }, () -> {
+                            mStatsLogManager.logger()
+                                    .withInstanceId(instanceId)
+                                    .withItemInfo(info)
+                                    .log(LAUNCHER_DISMISS_PREDICTION_UNDO);
+                        });
             }
             return null;
         }
 
-        ComponentName cn = getUninstallTarget(info);
+        return performUninstall(getContext(), getUninstallTarget(getContext(), info), info);
+    }
+
+    /**
+     * Performs uninstall and returns the target component for the {@link ItemInfo} or null if
+     * the uninstall was not performed.
+     */
+    public static ComponentName performUninstall(Context context, @Nullable ComponentName cn,
+            ItemInfo info) {
         if (cn == null) {
             // System applications cannot be installed. For now, show a toast explaining that.
             // We may give them the option of disabling apps this way.
             Toast.makeText(
-                    getContext(),
+                    context,
                     R.string.uninstall_system_app_text,
                     Toast.LENGTH_SHORT
-                ).show();
+            ).show();
             return null;
         }
         try {
-            Intent i = Intent.parseUri(getContext().getString(R.string.delete_package_intent), 0)
+            Intent i = Intent.parseUri(context.getString(R.string.delete_package_intent), 0)
                     .setData(Uri.fromParts("package", cn.getPackageName(), cn.getClassName()))
                     .putExtra(Intent.EXTRA_USER, info.user);
-            getContext().startActivity(i);
+            context.startActivity(i);
             FileLog.d(TAG, "start uninstall activity " + cn.getPackageName());
             return cn;
         } catch (URISyntaxException e) {
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index f9b7495..2a0f030 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -717,7 +717,10 @@
         LAUNCHER_PRIVATE_SPACE_INSTALL_APP_BUTTON_TAP(1605),
 
         @UiEvent(doc = "User attempted to create split screen with a widget")
-        LAUNCHER_SPLIT_WIDGET_ATTEMPT(1604)
+        LAUNCHER_SPLIT_WIDGET_ATTEMPT(1604),
+
+        @UiEvent(doc = "User tapped on private space uninstall system shortcut.")
+        LAUNCHER_PRIVATE_SPACE_UNINSTALL_SYSTEM_SHORTCUT_TAP(1608),
 
         // ADD MORE
         ;
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 3030ed4..fbbfea9 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -1,6 +1,7 @@
 package com.android.launcher3.popup;
 
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_INSTALL_SYSTEM_SHORTCUT_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNINSTALL_SYSTEM_SHORTCUT_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP;
@@ -17,17 +18,21 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.Flags;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.SecondaryDropTarget;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.PrivateProfileManager;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.InstantAppResolver;
@@ -301,16 +306,11 @@
         }
     }
 
-    public static final Factory<Launcher> DONT_SUGGEST_APP = new Factory<Launcher>() {
-        @Nullable
-        @Override
-        public SystemShortcut<Launcher> getShortcut(Launcher activity, ItemInfo itemInfo,
-                View originalView) {
-            if (!itemInfo.isPredictedItem()) {
-                return null;
-            }
-            return new DontSuggestApp(activity, itemInfo, originalView);
+    public static final Factory<Launcher> DONT_SUGGEST_APP = (activity, itemInfo, originalView) -> {
+        if (!itemInfo.isPredictedItem()) {
+            return null;
         }
+        return new DontSuggestApp(activity, itemInfo, originalView);
     };
 
     private static class DontSuggestApp extends SystemShortcut<Launcher> {
@@ -329,6 +329,51 @@
         }
     }
 
+    public static final Factory<Launcher> UNINSTALL_APP = (activity, itemInfo, originalView) -> {
+        if (!Flags.enablePrivateSpace()) {
+            return null;
+        }
+        if (!UserCache.getInstance(activity.getApplicationContext()).getUserInfo(
+                itemInfo.user).isPrivate()) {
+            // If app is not Private Space app.
+            return null;
+        }
+        ComponentName cn = SecondaryDropTarget.getUninstallTarget(activity.getApplicationContext(),
+                itemInfo);
+        if (cn == null) {
+            // If component name is null, don't show uninstall shortcut.
+            // System apps will have component name as null.
+            return null;
+        }
+        return new UninstallApp(activity, itemInfo, originalView, cn);
+    };
+
+    private static class UninstallApp extends SystemShortcut<Launcher> {
+        private static final String TAG = "UninstallApp";
+        Context mContext;
+        @NonNull
+        ComponentName mComponentName;
+
+        UninstallApp(Launcher target, ItemInfo itemInfo, View originalView,
+                @NonNull ComponentName cn) {
+            super(R.drawable.ic_uninstall_no_shadow, R.string.uninstall_drop_target_label, target,
+                    itemInfo, originalView);
+            mContext = target.getApplicationContext();
+            mComponentName = cn;
+
+        }
+
+        @Override
+        public void onClick(View view) {
+            dismissTaskMenuView(mTarget);
+            SecondaryDropTarget.performUninstall(mContext, mComponentName, mItemInfo);
+            mTarget.getStatsLogManager()
+                    .logger()
+                    .withItemInfo(mItemInfo)
+                    .log(LAUNCHER_PRIVATE_SPACE_UNINSTALL_SYSTEM_SHORTCUT_TAP);
+        }
+    }
+
     public static <T extends Context & ActivityContext> void dismissTaskMenuView(T activity) {
         AbstractFloatingView.closeOpenViews(activity, true,
             AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);