summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/Android.bp1
-rw-r--r--packages/SystemUI/res/layout/media_session_view.xml4
-rw-r--r--packages/SystemUI/res/layout/media_smartspace_recommendations.xml7
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml12
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java72
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java9
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;
}
}