Launcher3: fix app shortcuts for suspended apps

This CL fixes app shortcuts for suspended packages.

1) When DO/PO suspends an app, its pinned shortcuts are instantly grayed
out, but this is not persisted after the launcher restarts (e.g. device
reboot). We now enforce the launcher to check the suspended state when
loading the workspace, and gray out pinned shortcut icons accordingly.

2) When DO/PO suspends an app, its app shortcut popup is still
available. We now temporarily disable the popup when the app is
suspended, and persist the state across restarts.

Bug: 32365540
Test: manual, by following the steps in the bug above
Test: manual, by restarting the launcher package
Change-Id: I983d7c17fa198beca23b66459b50bd67b447bdd2
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 9ad8433..4d48fea 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.LauncherActivityInfo;
-import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -84,7 +83,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -1340,6 +1338,11 @@
                                         info = new ShortcutInfo(pinnedShortcut, context);
                                         info.iconBitmap = LauncherIcons
                                                 .createShortcutIcon(pinnedShortcut, context);
+                                        if (pmHelper.isAppSuspended(
+                                                info.getTargetComponent().getPackageName(),
+                                                info.user)) {
+                                            info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+                                        }
                                         intent = info.intent;
                                     } else {
                                         // Create a shortcut info in disabled mode for now.
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index b9142ed..44a3686 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -72,6 +73,7 @@
             UserHandle user);
     public abstract void startActivityForProfile(ComponentName component, UserHandle user,
             Rect sourceBounds, Bundle opts);
+    public abstract ApplicationInfo getApplicationInfo(String packageName, UserHandle user);
     public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user);
     public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
     public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index 3cb721c..776f593 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
@@ -65,6 +66,12 @@
     }
 
     @Override
+    public ApplicationInfo getApplicationInfo(String packageName, UserHandle user) {
+        List<LauncherActivityInfo> activityList = mLauncherApps.getActivityList(packageName, user);
+        return activityList.size() > 0 ? activityList.get(0).getApplicationInfo() : null;
+    }
+
+    @Override
     public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
         mLauncherApps.startAppDetailsActivity(component, user, null, null);
     }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
index 0610726..377907a 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.compat;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.os.UserHandle;
@@ -34,6 +35,11 @@
     }
 
     @Override
+    public ApplicationInfo getApplicationInfo(String packageName, UserHandle user) {
+        return mLauncherApps.getApplicationInfo(packageName, 0, user);
+    }
+
+    @Override
     public List<ShortcutConfigActivityInfo> getCustomShortcutActivityList() {
         List<ShortcutConfigActivityInfo> result = new ArrayList<>();
 
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
index 9413913..df7f695 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
@@ -65,7 +65,8 @@
     }
 
     public static boolean supportsShortcuts(ItemInfo info) {
-        return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+        return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+                && !info.isDisabled();
     }
 
     public boolean wasLastCallSuccess() {
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index e89fc0c..bfa932b 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -71,6 +71,10 @@
         }
     }
 
+  /**
+   * Returns whether a package is suspended for the current user as per
+   * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
+   */
     public boolean isAppSuspended(String packageName) {
         try {
             ApplicationInfo info = mPm.getApplicationInfo(packageName, 0);
@@ -80,6 +84,16 @@
         }
     }
 
+  /**
+   * Returns whether the target app is suspended for a given user as per
+   * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
+   */
+    public boolean isAppSuspended(String packageName, UserHandle user) {
+        ApplicationInfo info =
+                LauncherAppsCompat.getInstance(mContext).getApplicationInfo(packageName, user);
+        return info != null && isAppSuspended(info);
+    }
+
     public boolean isSafeMode() {
         return mPm.isSafeMode();
     }
@@ -91,6 +105,10 @@
                 AppInfo.makeLaunchIntent(mContext, activities.get(0), user);
     }
 
+  /**
+   * Returns whether an application is suspended as per
+   * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
+   */
     public static boolean isAppSuspended(ApplicationInfo info) {
         // The value of FLAG_SUSPENDED was reused by a hidden constant
         // ApplicationInfo.FLAG_PRIVILEGED prior to N, so only check for suspended flag on N