Enforce REQUEST_DELETE_PACKAGES for PackageInstaller.uninstall()
Fixes: 64576642
Test: Uninstalled apps
Change-Id: Ia7f3c047bb9c725228ca45e4c34e51a2d9177120
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index dd729a3..bad452c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1728,6 +1728,9 @@
* <p>
* Output: If {@link #EXTRA_RETURN_RESULT}, returns whether the install
* succeeded.
+ * <p>
+ * Requires {@link android.Manifest.permission#REQUEST_DELETE_PACKAGES}
+ * since {@link Build.VERSION_CODES#P}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 5673361..86288396 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -444,6 +444,9 @@
* @param packageName The package to uninstall.
* @param statusReceiver Where to deliver the result.
*/
+ @RequiresPermission(anyOf = {
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.REQUEST_DELETE_PACKAGES})
public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
uninstall(packageName, 0 /*flags*/, statusReceiver);
}
@@ -476,6 +479,9 @@
* @param versionedPackage The versioned package to uninstall.
* @param statusReceiver Where to deliver the result.
*/
+ @RequiresPermission(anyOf = {
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.REQUEST_DELETE_PACKAGES})
public void uninstall(@NonNull VersionedPackage versionedPackage,
@NonNull IntentSender statusReceiver) {
uninstall(versionedPackage, 0 /*flags*/, statusReceiver);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fd17dcb..1b56c28 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2776,8 +2776,9 @@
android:protectionLevel="signature|appop" />
<!-- Allows an application to request deleting packages. Apps
- targeting APIs greater than 25 must hold this permission in
- order to use {@link android.content.Intent#ACTION_UNINSTALL_PACKAGE}.
+ targeting APIs {@link android.os.Build.VERSION_CODES#P} or greater must hold this
+ permission in order to use {@link android.content.Intent#ACTION_UNINSTALL_PACKAGE} or
+ {@link android.content.pm.PackageInstaller#uninstall}.
<p>Protection level: normal
-->
<permission android:name="android.permission.REQUEST_DELETE_PACKAGES"
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 09f9cb8..be9b2f3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -32,6 +32,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
@@ -45,6 +46,7 @@
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -724,6 +726,12 @@
Binder.restoreCallingIdentity(ident);
}
} else {
+ ApplicationInfo appInfo = mPm.getApplicationInfo(callerPackageName, 0, userId);
+ if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES,
+ null);
+ }
+
// Take a short detour to confirm with user
final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null));