Merge "Add more hidden API uses to light greylist" into pi-dev
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index fb8ded1..f38c80c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2855,4 +2855,13 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public boolean isPackageStateProtected(String packageName, int userId) {
+        try {
+            return mPM.isPackageStateProtected(packageName, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9a19133..d43d80f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -674,4 +674,6 @@
     boolean hasUidSigningCertificate(int uid, in byte[] signingCertificate, int flags);
 
     String getSystemTextClassifierPackageName();
+
+    boolean isPackageStateProtected(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4d8773c..114c485 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -6140,4 +6140,16 @@
         throw new UnsupportedOperationException(
                 "getSystemTextClassifierPackageName not implemented in subclass");
     }
+
+    /**
+     * @return whether a given package's state is protected, e.g. package cannot be disabled,
+     *         suspended, hidden or force stopped.
+     *
+     * @hide
+     */
+    public boolean isPackageStateProtected(String packageName, int userId) {
+        throw new UnsupportedOperationException(
+            "isPackageStateProtected not implemented in subclass");
+    }
+
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c965aec..950d8df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import static android.Manifest.permission.DELETE_PACKAGES;
+import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
 import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
 import static android.Manifest.permission.INSTALL_PACKAGES;
 import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
@@ -115,6 +116,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
@@ -24315,6 +24317,23 @@
             return mSettings.getHarmfulAppWarningLPr(packageName, userId);
         }
     }
+
+    @Override
+    public boolean isPackageStateProtected(@NonNull String packageName, @UserIdInt int userId) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingAppId = UserHandle.getAppId(callingUid);
+
+        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
+                false /*requireFullPermission*/, true /*checkShell*/, "isPackageStateProtected");
+
+        if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID
+                && checkUidPermission(MANAGE_DEVICE_ADMINS, callingUid) != PERMISSION_GRANTED) {
+            throw new SecurityException("Caller must have the "
+                    + MANAGE_DEVICE_ADMINS + " permission.");
+        }
+
+        return mProtectedPackages.isPackageStateProtected(userId, packageName);
+    }
 }
 
 interface PackageSender {