diff options
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);      }  |