diff options
13 files changed, 185 insertions, 99 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index d8b077b32420..ad9aa6cdd3d9 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -108,6 +108,7 @@ cc_defaults { shared_libs: [ "android.hardware.graphics.common-V3-ndk", "android.hardware.graphics.common@1.2", + "android.hardware.graphics.composer3-V1-ndk", "liblog", "libcutils", "libutils", diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml index b67b7bc3b92e..665edac65afc 100644 --- a/packages/SystemUI/res/layout/media_session_view.xml +++ b/packages/SystemUI/res/layout/media_session_view.xml @@ -63,8 +63,8 @@ <!-- App icon --> <com.android.internal.widget.CachingIconView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" + android:layout_width="@dimen/qs_media_app_icon_size" + android:layout_height="@dimen/qs_media_app_icon_size" android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginTop="@dimen/qs_media_padding" app:layout_constraintStart_toStartOf="parent" diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index 6611c59651fc..5510f24870bb 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -36,7 +36,12 @@ <com.android.internal.widget.CachingIconView android:id="@+id/recommendation_card_icon" - style="@style/MediaPlayer.Recommendation.AppIcon" /> + android:layout_width="@dimen/qs_media_app_icon_size" + android:layout_height="@dimen/qs_media_app_icon_size" + android:layout_marginStart="@dimen/qs_media_padding" + android:layout_marginTop="@dimen/qs_media_padding" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> <FrameLayout android:id="@+id/media_cover1_container" diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index f2ddf9e645b6..ae5b8d8ae451 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -288,9 +288,6 @@ <!-- Enable the default volume level warning dialog --> <bool name="enable_safety_warning">true</bool> - <!-- Whether to show operator name in the status bar --> - <bool name="config_showOperatorNameInStatusBar">false</bool> - <!-- Whether to show the full screen user switcher. --> <bool name="config_enableFullscreenUserSwitcher">false</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a0115e8865fc..4a8fd1b00dde 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -970,6 +970,7 @@ <dimen name="qs_seamless_icon_size">12dp</dimen> <dimen name="qs_media_disabled_seekbar_height">1dp</dimen> <dimen name="qs_media_enabled_seekbar_height">2dp</dimen> + <dimen name="qs_media_app_icon_size">24dp</dimen> <dimen name="qs_media_session_enabled_seekbar_vertical_padding">15dp</dimen> <dimen name="qs_media_session_disabled_seekbar_vertical_padding">16dp</dimen> @@ -985,7 +986,6 @@ <dimen name="qs_media_rec_album_size">88dp</dimen> <dimen name="qs_media_rec_album_side_margin">16dp</dimen> <dimen name="qs_media_rec_album_bottom_margin">8dp</dimen> - <dimen name="qs_media_rec_icon_size">24dp</dimen> <!-- Media tap-to-transfer chip for sender device --> <dimen name="media_ttt_chip_outer_padding">16dp</dimen> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 827631b7eb53..c93c0652a070 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -655,18 +655,6 @@ <style name="MediaPlayer.Recommendation"/> - <style name="MediaPlayer.Recommendation.AppIcon"> - <item name="android:background">@drawable/qs_media_icon_background</item> - <item name="android:backgroundTint">@color/media_player_solid_button_bg</item> - <item name="android:layout_width">@dimen/qs_media_rec_icon_size</item> - <item name="android:layout_height">@dimen/qs_media_rec_icon_size</item> - <item name="layout_constraintTop_toTopOf">parent</item> - <item name="layout_constraintStart_toStartOf">parent</item> - <item name="android:layout_marginTop">@dimen/qs_media_padding</item> - <item name="android:layout_marginStart">@dimen/qs_media_padding</item> - <item name="android:src">@drawable/ic_headset</item> - </style> - <style name="MediaPlayer.Recommendation.AlbumContainer"> <item name="android:layout_width">@dimen/qs_media_rec_album_size</item> <item name="android:layout_height">@dimen/qs_media_rec_album_size</item> diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 0024a460136e..83220cab7149 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -147,10 +147,12 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi setLightSensorEnabled(true); break; case DOZE: - case DOZE_AOD_PAUSED: setLightSensorEnabled(false); resetBrightnessToDefault(); break; + case DOZE_AOD_PAUSED: + setLightSensorEnabled(false); + break; case FINISH: onDestroy(); break; diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 915c3f294a59..48a63ed0a2d6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -980,7 +980,6 @@ public class MediaControlPanel { PackageManager packageManager = mContext.getPackageManager(); // Set up media source app's logo. Drawable icon = packageManager.getApplicationIcon(applicationInfo); - icon.setColorFilter(getGrayscaleFilter()); ImageView headerLogoImageView = mRecommendationViewHolder.getCardIcon(); headerLogoImageView.setImageDrawable(icon); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 7d96240d0b36..69beaf56519f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.res.ColorStateList; import android.hardware.biometrics.BiometricSourceType; import android.os.Handler; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; @@ -164,58 +165,66 @@ public class KeyguardBouncer { // In split system user mode, we never unlock system user. return; } - ensureView(); - mIsScrimmed = isScrimmed; - // On the keyguard, we want to show the bouncer when the user drags up, but it's - // not correct to end the falsing session. We still need to verify if those touches - // are valid. - // Later, at the end of the animation, when the bouncer is at the top of the screen, - // onFullyShown() will be called and FalsingManager will stop recording touches. - if (isScrimmed) { - setExpansion(EXPANSION_VISIBLE); - } + try { + Trace.beginSection("KeyguardBouncer#show"); - if (resetSecuritySelection) { - // showPrimarySecurityScreen() updates the current security method. This is needed in - // case we are already showing and the current security method changed. - showPrimarySecurityScreen(); - } + ensureView(); + mIsScrimmed = isScrimmed; - if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) { - return; - } + // On the keyguard, we want to show the bouncer when the user drags up, but it's + // not correct to end the falsing session. We still need to verify if those touches + // are valid. + // Later, at the end of the animation, when the bouncer is at the top of the screen, + // onFullyShown() will be called and FalsingManager will stop recording touches. + if (isScrimmed) { + setExpansion(EXPANSION_VISIBLE); + } + + if (resetSecuritySelection) { + // showPrimarySecurityScreen() updates the current security method. This is needed + // in case we are already showing and the current security method changed. + showPrimarySecurityScreen(); + } + + if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) { + return; + } - final int activeUserId = KeyguardUpdateMonitor.getCurrentUser(); - final boolean isSystemUser = + final int activeUserId = KeyguardUpdateMonitor.getCurrentUser(); + final boolean isSystemUser = UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM; - final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId; + final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId; - // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is - // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer. - if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) { - return; - } + // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) + // is set, this will dismiss the whole Keyguard. Otherwise, show the bouncer. + if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) { + return; + } - // This condition may indicate an error on Android, so log it. - if (!allowDismissKeyguard) { - Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId); - } + // This condition may indicate an error on Android, so log it. + if (!allowDismissKeyguard) { + Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + + keyguardUserId); + } - mShowingSoon = true; + mShowingSoon = true; - // Split up the work over multiple frames. - DejankUtils.removeCallbacks(mResetRunnable); - if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer() + // Split up the work over multiple frames. + DejankUtils.removeCallbacks(mResetRunnable); + if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer() && !mKeyguardUpdateMonitor.userNeedsStrongAuth() && !mKeyguardBypassController.getBypassEnabled()) { - mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); - } else { - DejankUtils.postAfterTraversal(mShowRunnable); - } + mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); + } else { + DejankUtils.postAfterTraversal(mShowRunnable); + } - mCallback.onBouncerVisiblityChanged(true /* shown */); - dispatchStartingToShow(); + mCallback.onBouncerVisiblityChanged(true /* shown */); + dispatchStartingToShow(); + } finally { + Trace.endSection(); + } } public boolean isScrimmed() { @@ -317,6 +326,7 @@ public class KeyguardBouncer { } public void hide(boolean destroyView) { + Trace.beginSection("KeyguardBouncer#hide"); if (isShowing()) { SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN); @@ -338,6 +348,7 @@ public class KeyguardBouncer { // be slow because of AM lock contention during unlocking. We can delay it a bit. mHandler.postDelayed(mRemoveViewRunnable, 50); } + Trace.endSection(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 7b13b53946a4..dd166dd3610e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -164,7 +164,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onVisibilityChanged(boolean isVisible) { if (!isVisible) { - cancelPostAuthActions(); mCentralSurfaces.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN); } if (mAlternateAuthInterceptor != null) { @@ -502,42 +501,52 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message) { if (mShowing) { - cancelPendingWakeupAction(); - // If we're dozing, this needs to be delayed until after we wake up - unless we're - // wake-and-unlocking, because there dozing will last until the end of the transition. - if (mDozing && !isWakeAndUnlocking()) { - mPendingWakeupAction = new DismissWithActionRequest( - r, cancelAction, afterKeyguardGone, message); - return; - } + try { + Trace.beginSection("StatusBarKeyguardViewManager#dismissWithAction"); + cancelPendingWakeupAction(); + // If we're dozing, this needs to be delayed until after we wake up - unless we're + // wake-and-unlocking, because there dozing will last until the end of the + // transition. + if (mDozing && !isWakeAndUnlocking()) { + mPendingWakeupAction = new DismissWithActionRequest( + r, cancelAction, afterKeyguardGone, message); + return; + } - mAfterKeyguardGoneAction = r; - mKeyguardGoneCancelAction = cancelAction; - mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); + mAfterKeyguardGoneAction = r; + mKeyguardGoneCancelAction = cancelAction; + mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); + + // If there is an an alternate auth interceptor (like the UDFPS), show that one + // instead of the bouncer. + if (shouldShowAltAuth()) { + if (!afterKeyguardGone) { + mBouncer.setDismissAction(mAfterKeyguardGoneAction, + mKeyguardGoneCancelAction); + mAfterKeyguardGoneAction = null; + mKeyguardGoneCancelAction = null; + } + + updateAlternateAuthShowing( + mAlternateAuthInterceptor.showAlternateAuthBouncer()); + return; + } - // If there is an an alternate auth interceptor (like the UDFPS), show that one instead - // of the bouncer. - if (shouldShowAltAuth()) { - if (!afterKeyguardGone) { - mBouncer.setDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); + if (afterKeyguardGone) { + // we'll handle the dismiss action after keyguard is gone, so just show the + // bouncer + mBouncer.show(false /* resetSecuritySelection */); + } else { + // after authentication success, run dismiss action with the option to defer + // hiding the keyguard based on the return value of the OnDismissAction + mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, + mKeyguardGoneCancelAction); + // bouncer will handle the dismiss action, so we no longer need to track it here mAfterKeyguardGoneAction = null; mKeyguardGoneCancelAction = null; } - - updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer()); - return; - } - - if (afterKeyguardGone) { - // we'll handle the dismiss action after keyguard is gone, so just show the bouncer - mBouncer.show(false /* resetSecuritySelection */); - } else { - // after authentication success, run dismiss action with the option to defer - // hiding the keyguard based on the return value of the OnDismissAction - mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); - // bouncer will handle the dismiss action, so we no longer need to track it here - mAfterKeyguardGoneAction = null; - mKeyguardGoneCancelAction = null; + } finally { + Trace.endSection(); } } updateStates(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 4736587e6955..2e7b88d5fd38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -506,7 +506,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void transitionToAodPaused_resetsToDefaultBrightness_lightSensorDisabled() { + public void transitionToAodPaused_lightSensorDisabled() { // GIVEN AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -516,9 +516,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED); waitForSensorManager(); - // THEN brightness is reset and light sensor is unregistered - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); - // THEN new light events don't update brightness since the light sensor was unregistered mSensor.sendSensorEvent(1); assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index d6ab78bd27ea..7b0659332412 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -17,6 +17,11 @@ package com.android.server.pm; import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import android.accounts.IAccountManager; import android.annotation.NonNull; @@ -92,6 +97,7 @@ import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.IntArray; import android.util.PrintWriterPrinter; @@ -150,6 +156,17 @@ class PackageManagerShellCommand extends ShellCommand { "--multi-package" ); private static final Set<String> UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet(); + private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>(); + private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST; + static { + SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET); + SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED); + SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT); + SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED); + SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested", + FLAG_PERMISSION_REVOKE_WHEN_REQUESTED); + SUPPORTED_PERMISSION_FLAGS_LIST = new ArrayList<>(SUPPORTED_PERMISSION_FLAGS.keySet()); + } final IPackageManager mInterface; final LegacyPermissionManagerInternal mLegacyPermissionManager; @@ -276,6 +293,10 @@ class PackageManagerShellCommand extends ShellCommand { return runGrantRevokePermission(false); case "reset-permissions": return runResetPermissions(); + case "set-permission-flags": + return setOrClearPermissionFlags(true); + case "clear-permission-flags": + return setOrClearPermissionFlags(false); case "set-permission-enforced": return runSetPermissionEnforced(); case "get-privapp-permissions": @@ -2500,6 +2521,50 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int setOrClearPermissionFlags(boolean setFlags) { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + String perm = getNextArg(); + if (perm == null) { + getErrPrintWriter().println("Error: no permission specified"); + return 1; + } + + int flagMask = 0; + String flagName = getNextArg(); + if (flagName == null) { + getErrPrintWriter().println("Error: no permission flags specified"); + return 1; + } + while (flagName != null) { + if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) { + getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of " + + SUPPORTED_PERMISSION_FLAGS_LIST); + return 1; + } + flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName); + flagName = getNextArg(); + } + + final UserHandle translatedUser = UserHandle.of(translateUserId(userId, + UserHandle.USER_NULL, "runGrantRevokePermission")); + int flagSet = setFlags ? flagMask : 0; + mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser); + return 0; + } + private int runSetPermissionEnforced() throws RemoteException { final String permission = getNextArg(); if (permission == null) { @@ -3997,6 +4062,13 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" must be declared as used in the app's manifest, be runtime permissions"); pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); pw.println(""); + pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" These commands either set or clear permission flags on apps. The permissions"); + pw.println(" must be declared as used in the app's manifest, be runtime permissions"); + pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); + pw.println(" The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST); + pw.println(""); pw.println(" reset-permissions"); pw.println(" Revert all runtime permissions to their default state."); pw.println(""); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index d11ea532f140..186eccc80f8a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -223,6 +223,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.ACCESS_MEDIA_LOCATION); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_ADVERTISE); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN); @@ -764,8 +767,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; - // REVIEW_REQUIRED can only be set by non-system apps for for POST_NOTIFICATIONS - if (!POST_NOTIFICATIONS.equals(permName)) { + // REVIEW_REQUIRED can only be set by non-system apps for POST_NOTIFICATIONS, or by the + // shell or root UID. + if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID + && callingUid != Process.ROOT_UID) { flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; } } |