Fixing SDCard and package enabled state checks in PackageManagerHeler

Bug: 32365540
Change-Id: Iaac3e08ce55457ebbfb3633514ebc8ade6d200c5
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 8c90c2c..dc668e6 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -981,7 +981,7 @@
                                             c.markDeleted("Unrestored app removed: " + targetPkg);
                                             continue;
                                         }
-                                    } else if (pmHelper.isAppOnSdcard(targetPkg)) {
+                                    } else if (pmHelper.isAppOnSdcard(targetPkg, c.user)) {
                                         // Package is present but not available.
                                         disabledState |= ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
                                         // Add the icon on the workspace anyway.
@@ -1032,8 +1032,7 @@
                                         info.iconBitmap = LauncherIcons
                                                 .createShortcutIcon(pinnedShortcut, context);
                                         if (pmHelper.isAppSuspended(
-                                                info.getTargetComponent().getPackageName(),
-                                                info.user)) {
+                                                pinnedShortcut.getPackage(), info.user)) {
                                             info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
                                         }
                                         intent = info.intent;
@@ -1046,7 +1045,7 @@
                                     info = c.loadSimpleShortcut();
 
                                     // Shortcuts are only available on the primary profile
-                                    if (pmHelper.isAppSuspended(targetPkg)) {
+                                    if (pmHelper.isAppSuspended(targetPkg, c.user)) {
                                         disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
                                     }
 
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 44a3686..2eb5b02 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -73,7 +73,8 @@
             UserHandle user);
     public abstract void startActivityForProfile(ComponentName component, UserHandle user,
             Rect sourceBounds, Bundle opts);
-    public abstract ApplicationInfo getApplicationInfo(String packageName, UserHandle user);
+    public abstract ApplicationInfo getApplicationInfo(
+            String packageName, int flags, 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 776f593..e5517a6 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -27,6 +27,7 @@
 import android.content.pm.ShortcutInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.UserHandle;
 
 import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVL;
@@ -66,9 +67,28 @@
     }
 
     @Override
-    public ApplicationInfo getApplicationInfo(String packageName, UserHandle user) {
-        List<LauncherActivityInfo> activityList = mLauncherApps.getActivityList(packageName, user);
-        return activityList.size() > 0 ? activityList.get(0).getApplicationInfo() : null;
+    public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) {
+        final boolean isPrimaryUser = Process.myUserHandle().equals(user);
+        if (!isPrimaryUser && (flags == 0)) {
+            // We are looking for an installed app on a secondary profile. Prior to O, the only
+            // entry point for work profiles is through the LauncherActivity.
+            List<LauncherActivityInfo> activityList =
+                    mLauncherApps.getActivityList(packageName, user);
+            return activityList.size() > 0 ? activityList.get(0).getApplicationInfo() : null;
+        }
+        try {
+            ApplicationInfo info =
+                    mContext.getPackageManager().getApplicationInfo(packageName, flags);
+            // There is no way to check if the app is installed for managed profile. But for
+            // primary profile, we can still have this check.
+            if (isPrimaryUser && ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
+                return null;
+            }
+            return info;
+        } catch (PackageManager.NameNotFoundException e) {
+            // Package not found
+            return null;
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
index 377907a..c0f80d0 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
@@ -35,8 +35,9 @@
     }
 
     @Override
-    public ApplicationInfo getApplicationInfo(String packageName, UserHandle user) {
-        return mLauncherApps.getApplicationInfo(packageName, 0, user);
+    public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) {
+        ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
+        return info == null || (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 ? null : info;
     }
 
     @Override
diff --git a/src/com/android/launcher3/model/SdCardAvailableReceiver.java b/src/com/android/launcher3/model/SdCardAvailableReceiver.java
index 7c98362..278669b 100644
--- a/src/com/android/launcher3/model/SdCardAvailableReceiver.java
+++ b/src/com/android/launcher3/model/SdCardAvailableReceiver.java
@@ -63,7 +63,7 @@
 
             for (String pkg : new HashSet<>(entry.getValue())) {
                 if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
-                    if (pmHelper.isAppOnSdcard(pkg)) {
+                    if (pmHelper.isAppOnSdcard(pkg, user)) {
                         packagesUnavailable.add(pkg);
                     } else {
                         packagesRemoved.add(pkg);
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index bfa932b..7629f78 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -40,81 +40,55 @@
  */
 public class PackageManagerHelper {
 
-    private static final int FLAG_SUSPENDED = 1<<30;
-
     private final Context mContext;
     private final PackageManager mPm;
+    private final LauncherAppsCompat mLauncherApps;
 
     public PackageManagerHelper(Context context) {
         mContext = context;
         mPm = context.getPackageManager();
+        mLauncherApps = LauncherAppsCompat.getInstance(context);
     }
 
     /**
      * Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
      * guarantee that the app is on SD card.
      */
-    public boolean isAppOnSdcard(String packageName) {
-        return isAppEnabled(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+    public boolean isAppOnSdcard(String packageName, UserHandle user) {
+        ApplicationInfo info = mLauncherApps.getApplicationInfo(
+                packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, user);
+        return info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
     }
 
-    public boolean isAppEnabled(String packageName) {
-        return isAppEnabled(packageName, 0);
-    }
-
-    public boolean isAppEnabled(String packageName, int flags) {
-        try {
-            ApplicationInfo info = mPm.getApplicationInfo(packageName, flags);
-            return info != null && info.enabled;
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-    }
-
-  /**
-   * 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);
-            return info != null && isAppSuspended(info);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-    }
-
-  /**
-   * Returns whether the target app is suspended for a given user as per
-   * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
-   */
+    /**
+     * 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);
+        ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, 0, user);
         return info != null && isAppSuspended(info);
     }
 
     public boolean isSafeMode() {
-        return mPm.isSafeMode();
+        return mContext.getPackageManager().isSafeMode();
     }
 
     public Intent getAppLaunchIntent(String pkg, UserHandle user) {
-        List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(mContext)
-                .getActivityList(pkg, user);
+        List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(pkg, user);
         return activities.isEmpty() ? null :
                 AppInfo.makeLaunchIntent(mContext, activities.get(0), user);
     }
 
-  /**
-   * Returns whether an application is suspended as per
-   * {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
-   */
+    /**
+     * 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
         // or later.
         if (Utilities.ATLEAST_NOUGAT) {
-            return (info.flags & FLAG_SUSPENDED) != 0;
+            return (info.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
         } else {
             return false;
         }