OSDN Git Service

Expose hidden API to check whether a given package is state protected
authorBenjamin Franz <bfranz@google.com>
Thu, 22 Mar 2018 10:11:29 +0000 (10:11 +0000)
committerBenjamin Franz <bfranz@google.com>
Thu, 22 Mar 2018 18:10:06 +0000 (18:10 +0000)
Bug: 75997475
Test: manual
Change-Id: I5e0da781af6d148aed2247175e8ee5d9f244ebe1

core/java/android/app/ApplicationPackageManager.java
core/java/android/content/pm/IPackageManager.aidl
core/java/android/content/pm/PackageManager.java
services/core/java/com/android/server/pm/PackageManagerService.java

index 21fb18a..80ed0ea 100644 (file)
@@ -2810,4 +2810,13 @@ public class ApplicationPackageManager extends PackageManager {
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public boolean isPackageStateProtected(String packageName, int userId) {
+        try {
+            return mPM.isPackageStateProtected(packageName, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
index 36a74a4..d87c13c 100644 (file)
@@ -662,4 +662,6 @@ interface IPackageManager {
     boolean hasUidSigningCertificate(int uid, in byte[] signingCertificate, int flags);
 
     String getSystemTextClassifierPackageName();
+
+    boolean isPackageStateProtected(String packageName, int userId);
 }
index bd7961f..53bfeb9 100644 (file)
@@ -6032,4 +6032,16 @@ public abstract class PackageManager {
         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");
+    }
+
 }
index 052f239..bde2ec0 100644 (file)
@@ -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;
@@ -117,6 +118,7 @@ import android.Manifest;
 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;
@@ -24212,6 +24214,23 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
             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 {