summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/accounts/GrantCredentialsPermissionActivity.java34
-rw-r--r--core/java/android/app/ContextImpl.java16
-rw-r--r--core/java/android/content/Context.java27
-rw-r--r--core/java/android/content/ContextWrapper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java71
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java6
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
-rw-r--r--services/core/java/com/android/server/pm/BasePermission.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java105
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java6
-rw-r--r--test-runner/api/android-test-mock-current.txt1
-rw-r--r--test-runner/src/android/test/mock/MockContext.java7
-rw-r--r--tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java6
14 files changed, 258 insertions, 42 deletions
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index af74b036a796..7e41dbe7c177 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -16,16 +16,23 @@
package android.accounts;
import android.app.Activity;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.widget.TextView;
-import android.widget.LinearLayout;
-import android.view.View;
-import android.view.LayoutInflater;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
import com.android.internal.R;
import java.io.IOException;
@@ -42,6 +49,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
private Account mAccount;
private String mAuthTokenType;
private int mUid;
+ private int mCallingUid;
private Bundle mResultBundle = null;
protected LayoutInflater mInflater;
@@ -74,6 +82,20 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
return;
}
+ try {
+ IBinder activityToken = getActivityToken();
+ mCallingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
+ } catch (RemoteException re) {
+ // Couldn't figure out caller details
+ Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
+ }
+
+ if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ return;
+ }
+
String accountTypeLabel;
try {
accountTypeLabel = getAccountLabel(mAccount);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5f3432264ca0..06d63ea14a2c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1009,6 +1009,22 @@ class ContextImpl extends Context {
}
@Override
+ public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions) {
+ warnIfCallingFromSystemProcess();
+ String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+ try {
+ intent.prepareToLeaveProcess(this);
+ ActivityManager.getService().broadcastIntent(
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
+ null, false, false, user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f821d31e3e2b..961901e2fb8f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1952,6 +1952,33 @@ public abstract class Context {
/**
* Broadcast the given intent to all interested BroadcastReceivers, allowing
+ * an array of required permissions to be enforced. This call is asynchronous; it returns
+ * immediately, and you will continue executing while the receivers are run. No results are
+ * propagated from receivers and receivers can not abort the broadcast. If you want to allow
+ * receivers to propagate results or abort the broadcast, you must send an ordered broadcast
+ * using {@link #sendOrderedBroadcast(Intent, String)}.
+ *
+ * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param user The user to send the broadcast to.
+ * @param receiverPermissions Array of names of permissions that a receiver must hold
+ * in order to receive your broadcast.
+ * If null or empty, no permissions are required.
+ *
+ * @see android.content.BroadcastReceiver
+ * @see #registerReceiver
+ * @see #sendBroadcast(Intent)
+ * @see #sendOrderedBroadcast(Intent, String)
+ * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+ * @hide
+ */
+ public abstract void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions);
+
+ /**
+ * Broadcast the given intent to all interested BroadcastReceivers, allowing
* an optional required permission to be enforced. This
* call is asynchronous; it returns immediately, and you will continue
* executing while the receivers are run. No results are propagated from
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 85acdc6b8101..3a5fccbbff94 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -449,6 +449,13 @@ public class ContextWrapper extends Context {
}
/** @hide */
+ @Override
+ public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions) {
+ mBase.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions);
+ }
+
+ /** @hide */
@SystemApi
@Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 991c3c83cbc1..467bb65ead55 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -100,6 +100,7 @@ class SaveImageInBackgroundData {
imageUri = null;
iconSize = 0;
}
+
void clearContext() {
context = null;
}
@@ -348,21 +349,23 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mPublicNotificationBuilder
.setContentTitle(r.getString(R.string.screenshot_saved_title))
.setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
+ .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent,
+ PendingIntent.FLAG_IMMUTABLE))
.setWhen(now)
.setAutoCancel(true)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setPublicVersion(mPublicNotificationBuilder.build())
- .setFlag(Notification.FLAG_NO_CLEAR, false);
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent,
+ PendingIntent.FLAG_IMMUTABLE))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
mNotificationBuilder.build());
@@ -463,7 +466,8 @@ class GlobalScreenshot {
// Inflate the screenshot layout
mDisplayMatrix = new Matrix();
mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
- mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
+ mBackgroundView = (ImageView) mScreenshotLayout.findViewById(
+ R.id.global_screenshot_background);
mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
mScreenshotSelectorView = (ScreenshotSelectorView) mScreenshotLayout.findViewById(
@@ -484,24 +488,25 @@ class GlobalScreenshot {
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
WindowManager.LayoutParams.TYPE_SCREENSHOT,
WindowManager.LayoutParams.FLAG_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
mWindowLayoutParams.setTitle("ScreenshotAnimation");
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
mDisplay = mWindowManager.getDefaultDisplay();
mDisplayMetrics = new DisplayMetrics();
mDisplay.getRealMetrics(mDisplayMetrics);
// Get the various target sizes
mNotificationIconSize =
- r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
+ r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
// Scale has to account for both sides of the bg
mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
- mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
+ mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
// determine the optimal preview size
int panelWidth = 0;
@@ -735,6 +740,7 @@ class GlobalScreenshot {
}
});
}
+
private ValueAnimator createScreenshotDropInAnimation() {
final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
/ SCREENSHOT_DROP_IN_DURATION);
@@ -775,6 +781,7 @@ class GlobalScreenshot {
mScreenshotFlash.setAlpha(0f);
mScreenshotFlash.setVisibility(View.VISIBLE);
}
+
@Override
public void onAnimationEnd(android.animation.Animator animation) {
mScreenshotFlash.setVisibility(View.GONE);
@@ -785,7 +792,7 @@ class GlobalScreenshot {
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
- - scaleInterpolator.getInterpolation(t)
+ - scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(t);
@@ -796,6 +803,7 @@ class GlobalScreenshot {
});
return anim;
}
+
private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
boolean navBarVisible) {
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
@@ -817,7 +825,8 @@ class GlobalScreenshot {
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
+ - t * (SCREENSHOT_DROP_IN_MIN_SCALE
+ - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(1f - t);
mScreenshotView.setScaleX(scaleT);
@@ -844,8 +853,10 @@ class GlobalScreenshot {
float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
final float offsetPct = SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET;
final PointF finalPos = new PointF(
- -halfScreenWidth + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
- -halfScreenHeight + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);
+ -halfScreenWidth
+ + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
+ -halfScreenHeight
+ + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);
// Animate the screenshot to the status bar
anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
@@ -854,7 +865,7 @@ class GlobalScreenshot {
public void onAnimationUpdate(ValueAnimator animation) {
float t = (Float) animation.getAnimatedValue();
float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - scaleInterpolator.getInterpolation(t)
+ - scaleInterpolator.getInterpolation(t)
* (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
@@ -874,15 +885,15 @@ class GlobalScreenshot {
// Repurpose the existing notification to notify the user of the error
Notification.Builder b = new Notification.Builder(context, NotificationChannels.ALERTS)
- .setTicker(r.getString(R.string.screenshot_failed_title))
- .setContentTitle(r.getString(R.string.screenshot_failed_title))
- .setContentText(errorMsg)
- .setSmallIcon(R.drawable.stat_notify_image_error)
- .setWhen(System.currentTimeMillis())
- .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
- .setCategory(Notification.CATEGORY_ERROR)
- .setAutoCancel(true)
- .setColor(context.getColor(
+ .setTicker(r.getString(R.string.screenshot_failed_title))
+ .setContentTitle(r.getString(R.string.screenshot_failed_title))
+ .setContentText(errorMsg)
+ .setSmallIcon(R.drawable.stat_notify_image_error)
+ .setWhen(System.currentTimeMillis())
+ .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
+ .setCategory(Notification.CATEGORY_ERROR)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
@@ -890,7 +901,7 @@ class GlobalScreenshot {
DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
if (intent != null) {
final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- context, 0, intent, 0, null, UserHandle.CURRENT);
+ context, 0, intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
b.setContentIntent(pendingIntent);
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index aaa4626d495d..6dce7eed5eba 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -25,6 +25,7 @@ import static com.android.internal.util.Preconditions.checkState;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
@@ -275,7 +276,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
checkArgument(getCallingUserId() == userId,
"Must be called by either same user or system");
- mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
+ int callingUid = Binder.getCallingUid();
+ if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index d51e1f738659..8adb7f30d857 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1138,7 +1138,7 @@ public class Vpn {
*/
public synchronized void onUserStopped() {
// Switch off networking lockdown (if it was enabled)
- setLockdown(false);
+ setVpnForcedLocked(false);
mAlwaysOn = false;
unregisterPackageChangeReceiverLocked();
diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
index 30fda1e5665e..15828537e0b1 100644
--- a/services/core/java/com/android/server/pm/BasePermission.java
+++ b/services/core/java/com/android/server/pm/BasePermission.java
@@ -35,6 +35,8 @@ final class BasePermission {
final int type;
+ private boolean mPermissionDefinitionChanged;
+
int protectionLevel;
PackageParser.Permission perm;
@@ -67,11 +69,19 @@ final class BasePermission {
+ "}";
}
+ public boolean isPermissionDefinitionChanged() {
+ return mPermissionDefinitionChanged;
+ }
+
public void setGids(int[] gids, boolean perUser) {
this.gids = gids;
this.perUser = perUser;
}
+ public void setPermissionDefinitionChanged(boolean shouldOverride) {
+ mPermissionDefinitionChanged = shouldOverride;
+ }
+
public int[] computeGids(int userId) {
if (perUser) {
final int[] userGids = new int[gids.length];
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7a98cf74bbcd..19b2c7c70cbf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11333,7 +11333,7 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
final int userId = user == null ? 0 : user.getIdentifier();
// Modify state for the given package setting
- commitPackageSettings(pkg, pkgSetting, user, scanFlags,
+ commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags,
(policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
if (pkgSetting.getInstantApp(userId)) {
mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
@@ -11703,10 +11703,73 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
+ * If permissions are upgraded to runtime, or their owner changes to the system, then any
+ * granted permissions must be revoked.
+ *
+ * @param permissionsToRevoke A list of permission names to revoke
+ * @param allPackageNames All package names
+ */
+ private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ @NonNull List<String> permissionsToRevoke,
+ @NonNull ArrayList<String> allPackageNames) {
+
+ final int[] userIds = UserManagerService.getInstance().getUserIds();
+ final int numPermissions = permissionsToRevoke.size();
+ final int numUserIds = userIds.length;
+ final int numPackages = allPackageNames.size();
+ final int callingUid = Binder.getCallingUid();
+
+ for (int permNum = 0; permNum < numPermissions; permNum++) {
+ String permName = permissionsToRevoke.get(permNum);
+
+ BasePermission bp = mSettings.mPermissions.get(permName);
+ if (bp == null || !bp.isRuntime()) {
+ continue;
+ }
+ for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
+ final int userId = userIds[userIdNum];
+ for (int packageNum = 0; packageNum < numPackages; packageNum++) {
+ final String packageName = allPackageNames.get(packageNum);
+ final int uid = getPackageUid(packageName, 0, userId);
+ if (uid < Process.FIRST_APPLICATION_UID) {
+ // do not revoke from system apps
+ continue;
+ }
+ final int permissionState = checkPermission(permName, packageName,
+ userId);
+ final int flags = getPermissionFlags(permName, packageName, userId);
+ final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED
+ | FLAG_PERMISSION_POLICY_FIXED
+ | FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+ if (permissionState == PackageManager.PERMISSION_GRANTED
+ && (flags & flagMask) == 0) {
+ EventLog.writeEvent(0x534e4554, "154505240", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ EventLog.writeEvent(0x534e4554, "168319670", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ Slog.e(TAG, "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ try {
+ revokeRuntimePermission(packageName, permName, userId, false);
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not revoke " + permName + " from "
+ + packageName, e);
+ }
+ }
+ }
+ }
+ bp.setPermissionDefinitionChanged(false);
+ }
+ }
+
+ /**
* Adds a scanned package to the system. When this method is finished, the package will
* be available for query, resolution, etc...
*/
- private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting,
+ private void commitPackageSettings(PackageParser.Package pkg, PackageParser.Package oldPkg,
+ PackageSetting pkgSetting,
UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
final String pkgName = pkg.packageName;
if (mCustomResolverComponentName != null &&
@@ -12038,6 +12101,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
}
+ // If a permission has had its defining app changed, or it has had its protection
+ // upgraded, we need to revoke apps that hold it
+ final List<String> permissionsWithChangedDefinition = new ArrayList<String>();
+
N = pkg.permissions.size();
r = null;
for (i=0; i<N; i++) {
@@ -12073,6 +12140,7 @@ public class PackageManagerService extends IPackageManager.Stub
BasePermission bp = permissionMap.get(p.info.name);
// Allow system apps to redefine non-system permissions
+ boolean ownerChanged = false;
if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
final boolean currentOwnerIsSystem = (bp.perm != null
&& isSystemApp(bp.perm.owner));
@@ -12088,6 +12156,7 @@ public class PackageManagerService extends IPackageManager.Stub
String msg = "New decl " + p.owner + " of permission "
+ p.info.name + " is system; overriding " + bp.sourcePackage;
reportSettingsProblem(Log.WARN, msg);
+ ownerChanged = true;
bp = null;
}
}
@@ -12099,6 +12168,7 @@ public class PackageManagerService extends IPackageManager.Stub
permissionMap.put(p.info.name, bp);
}
+ boolean wasNonRuntime = !bp.isRuntime();
if (bp.perm == null) {
if (bp.sourcePackage == null
|| bp.sourcePackage.equals(p.info.packageName)) {
@@ -12141,8 +12211,15 @@ public class PackageManagerService extends IPackageManager.Stub
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
}
- }
+ if (bp.isRuntime() && (ownerChanged || wasNonRuntime)) {
+ // If this is a runtime permission and the owner has changed, or this was a normal
+ // permission, then permission state should be cleaned up
+ bp.setPermissionDefinitionChanged(true);
+
+ permissionsWithChangedDefinition.add(p.info.name);
+ }
+ }
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
}
@@ -12185,6 +12262,28 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
+
+ boolean hasOldPkg = oldPkg != null;
+ boolean hasPermissionDefinitionChanges = !permissionsWithChangedDefinition.isEmpty();
+ if (hasOldPkg || hasPermissionDefinitionChanges) {
+ // We need to call revokeRuntimePermissionsIfPermissionDefinitionChanged async
+ // as permission
+ // revoke callbacks from this method might need to kill apps which need the
+ // mPackages lock on a different thread. This would dead lock.
+ //
+ // Hence create a copy of all package names and pass it into
+ // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get
+ // revoked. If a new package is added before the async code runs the permission
+ // won't be granted yet, hence new packages are no problem.
+ final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
+
+ AsyncTask.execute(() -> {
+ if (hasPermissionDefinitionChanges) {
+ revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ permissionsWithChangedDefinition, allPackageNames);
+ }
+ });
+ }
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index a04a3248b8e9..ab331fafd54e 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2133,7 +2133,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mContext, 0,
Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
- 0, null, new UserHandle(serviceUserId)));
+ PendingIntent.FLAG_IMMUTABLE, null, new UserHandle(serviceUserId)));
if (!mContext.bindServiceAsUser(intent, newConn,
Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
| Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 97021181c384..cb5f0a701615 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -235,6 +235,12 @@ public class DpmMockContext extends MockContext {
}
@Override
+ public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions) {
+ spiedContext.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions);
+ }
+
+ @Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
spiedContext.sendBroadcast(intent, receiverPermission, options);
}
diff --git a/test-runner/api/android-test-mock-current.txt b/test-runner/api/android-test-mock-current.txt
index 93bbf6c5c024..dfb2ee8d7599 100644
--- a/test-runner/api/android-test-mock-current.txt
+++ b/test-runner/api/android-test-mock-current.txt
@@ -133,6 +133,7 @@ package android.test.mock {
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.os.Bundle);
method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int);
+ method public void sendBroadcastAsUserMultiplePermissions(android.content.Intent, android.os.UserHandle, java.lang.String[]);
method public void sendBroadcastMultiplePermissions(android.content.Intent, java.lang.String[]);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 5e5ba462cfca..8cde61284b53 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -359,6 +359,13 @@ public class MockContext extends Context {
}
/** @hide */
+ @Override
+ public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
@SystemApi
@Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
index 21662407db42..25bd7c06be49 100644
--- a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
+++ b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
@@ -175,6 +175,12 @@ public class BroadcastInterceptingContext extends ContextWrapper {
}
@Override
+ public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+ String[] receiverPermissions) {
+ sendBroadcast(intent);
+ }
+
+ @Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
sendBroadcast(intent);
}