diff options
16 files changed, 255 insertions, 58 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 2be44bc..ce83caa 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -204,6 +204,10 @@ public final class Pm { return runGrantRevokePermission(false); } + if ("reset-permissions".equals(op)) { + return runResetPermissions(); + } + if ("set-permission-enforced".equals(op)) { return runSetPermissionEnforced(); } @@ -1636,6 +1640,24 @@ public final class Pm { } } + private int runResetPermissions() { + try { + mPm.resetRuntimePermissions(); + return 0; + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(PM_NOT_RUNNING_ERR); + return 1; + } catch (IllegalArgumentException e) { + System.err.println("Bad argument: " + e.toString()); + showUsage(); + return 1; + } catch (SecurityException e) { + System.err.println("Operation not allowed: " + e.toString()); + return 1; + } + } + private int runSetPermissionEnforced() { final String permission = nextArg(); if (permission == null) { @@ -1911,6 +1933,7 @@ public final class Pm { System.err.println(" pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm grant [--user USER_ID] PACKAGE PERMISSION"); System.err.println(" pm revoke [--user USER_ID] PACKAGE PERMISSION"); + System.err.println(" pm reset-permissions"); System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]"); System.err.println(" pm get-install-location"); System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); @@ -1988,6 +2011,8 @@ public final class Pm { System.err.println(" manifest, be runtime permissions (protection level dangerous),"); System.err.println(" and the app targeting SDK greater than Lollipop MR1."); System.err.println(""); + System.err.println("pm reset-permissions: revert all runtime permissions to their default state."); + System.err.println(""); System.err.println("pm get-install-location: returns the current install location."); System.err.println(" 0 [auto]: Let system decide the best location"); System.err.println(" 1 [internal]: Install on internal device storage"); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c9853df..cea6e99 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -102,6 +102,8 @@ interface IPackageManager { void revokeRuntimePermission(String packageName, String permissionName, int userId); + void resetRuntimePermissions(); + int getPermissionFlags(String permissionName, String packageName, int userId); void updatePermissionFlags(String permissionName, String packageName, int flagMask, diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 75289f7..33cc962 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1062,6 +1062,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * capturing a high-resolution JPEG image will automatically trigger a * precapture sequence before the high-resolution capture, including * potentially firing a pre-capture flash.</p> + * <p>Using the precapture trigger and the auto-focus trigger {@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger} + * simultaneously is allowed. However, since these triggers often require cooperation between + * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a + * focus sweep), the camera device may delay acting on a later trigger until the previous + * trigger has been fully handled. This may lead to longer intervals between the trigger and + * changes to {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} indicating the start of the precapture sequence, for + * example.</p> + * <p>If both the precapture and the auto-focus trigger are activated on the same request, then + * the camera device will complete them in the optimal order for that device.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li> @@ -1075,6 +1084,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * * @see CaptureRequest#CONTROL_AE_LOCK * @see CaptureResult#CONTROL_AE_STATE + * @see CaptureRequest#CONTROL_AF_TRIGGER * @see CaptureRequest#CONTROL_CAPTURE_INTENT * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE @@ -1179,6 +1189,12 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * START for multiple captures in a row means restarting the AF operation over * and over again.</p> * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p> + * <p>Using the autofocus trigger and the precapture trigger {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} + * simultaneously is allowed. However, since these triggers often require cooperation between + * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a + * focus sweep), the camera device may delay acting on a later trigger until the previous + * trigger has been fully handled. This may lead to longer intervals between the trigger and + * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li> @@ -1187,6 +1203,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * </ul></p> * <p>This key is available on all devices.</p> * + * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER * @see CaptureResult#CONTROL_AF_STATE * @see #CONTROL_AF_TRIGGER_IDLE * @see #CONTROL_AF_TRIGGER_START diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 1d31109..9dee045 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -779,6 +779,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * capturing a high-resolution JPEG image will automatically trigger a * precapture sequence before the high-resolution capture, including * potentially firing a pre-capture flash.</p> + * <p>Using the precapture trigger and the auto-focus trigger {@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger} + * simultaneously is allowed. However, since these triggers often require cooperation between + * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a + * focus sweep), the camera device may delay acting on a later trigger until the previous + * trigger has been fully handled. This may lead to longer intervals between the trigger and + * changes to {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} indicating the start of the precapture sequence, for + * example.</p> + * <p>If both the precapture and the auto-focus trigger are activated on the same request, then + * the camera device will complete them in the optimal order for that device.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li> @@ -792,6 +801,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * * @see CaptureRequest#CONTROL_AE_LOCK * @see CaptureResult#CONTROL_AE_STATE + * @see CaptureRequest#CONTROL_AF_TRIGGER * @see CaptureRequest#CONTROL_CAPTURE_INTENT * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE @@ -1139,6 +1149,12 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * START for multiple captures in a row means restarting the AF operation over * and over again.</p> * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p> + * <p>Using the autofocus trigger and the precapture trigger {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} + * simultaneously is allowed. However, since these triggers often require cooperation between + * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a + * focus sweep), the camera device may delay acting on a later trigger until the previous + * trigger has been fully handled. This may lead to longer intervals between the trigger and + * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p> * <p><b>Possible values:</b> * <ul> * <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li> @@ -1147,6 +1163,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </ul></p> * <p>This key is available on all devices.</p> * + * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER * @see CaptureResult#CONTROL_AF_STATE * @see #CONTROL_AF_TRIGGER_IDLE * @see #CONTROL_AF_TRIGGER_START diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 0309d24..d424546 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -369,7 +369,9 @@ public abstract class NotificationListenerService extends Service { /** * Inform the notification manager that these notifications have been viewed by the - * user. + * user. This should only be called when there is sufficient confidence that the user is + * looking at the notifications, such as when the notifications appear on the screen due to + * an explicit user interaction. * @param keys Notifications to mark as seen. */ public final void setNotificationsShown(String[] keys) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index b3def33..23da6d2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8701,14 +8701,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Adds the children of a given View for accessibility. Since some Views are - * not important for accessibility the children for accessibility are not - * necessarily direct children of the view, rather they are the first level of - * descendants important for accessibility. + * Adds the children of this View relevant for accessibility to the given list + * as output. Since some Views are not important for accessibility the added + * child views are not necessarily direct children of this view, rather they are + * the first level of descendants important for accessibility. * - * @param children The list of children for accessibility. + * @param outChildren The output list that will receive children for accessibility. */ - public void addChildrenForAccessibility(ArrayList<View> children) { + public void addChildrenForAccessibility(ArrayList<View> outChildren) { } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 2e2ba88..b53d93c 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1919,7 +1919,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } @Override - public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) { + public void addChildrenForAccessibility(ArrayList<View> outChildren) { if (getAccessibilityNodeProvider() != null) { return; } @@ -1930,9 +1930,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager View child = children.getChildAt(i); if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { if (child.includeForAccessibility()) { - childrenForAccessibility.add(child); + outChildren.add(child); } else { - child.addChildrenForAccessibility(childrenForAccessibility); + child.addChildrenForAccessibility(outChildren); } } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 2cbfae2..bada791 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1034,11 +1034,11 @@ android:priority="1000" /> <!-- Allows access to the list of accounts in the Accounts Service. - <p>Protection level: dangerous + <p>Protection level: normal --> <permission android:name="android.permission.GET_ACCOUNTS" android:permissionGroup="android.permission-group.CONTACTS" - android:protectionLevel="dangerous" + android:protectionLevel="normal" android:description="@string/permdesc_getAccounts" android:label="@string/permlab_getAccounts" /> diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h index 5e9b213..c98932c 100644 --- a/libs/hwui/Outline.h +++ b/libs/hwui/Outline.h @@ -19,6 +19,7 @@ #include <SkPath.h> #include "Rect.h" +#include "utils/MathUtils.h" namespace android { namespace uirenderer { @@ -85,6 +86,11 @@ public: return mShouldClip && (mType == kOutlineType_RoundRect); } + bool willRoundRectClip() const { + // only round rect outlines can be used for clipping + return willClip() && MathUtils::isPositive(mRadius); + } + bool getAsRoundRect(Rect* outRect, float* outRadius) const { if (mType == kOutlineType_RoundRect) { outRect->set(mBounds); diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 81cf2df..11abd70 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -169,7 +169,7 @@ public: bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer // Round rect clipping forces layer for functors - || CC_UNLIKELY(getOutline().willClip()) + || CC_UNLIKELY(getOutline().willRoundRectClip()) || CC_UNLIKELY(getRevealClip().willClip()) // Complex matrices forces layer, due to stencil clipping diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 860a6b7..3678cf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -2931,6 +2931,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mZenModeController != null) { mZenModeController.setUserId(mCurrentUserId); } + if (mSecurityController != null) { + mSecurityController.onUserSwitched(mCurrentUserId); + } } private void resetUserSetupObserver() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 962000a..b505d9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -64,6 +64,7 @@ public class SecurityControllerImpl implements SecurityController { private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>(); private int mCurrentUserId; + private int mVpnUserId; public SecurityControllerImpl(Context context) { mContext = context; @@ -78,7 +79,7 @@ public class SecurityControllerImpl implements SecurityController { // TODO: re-register network callback on user change. mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); - mCurrentUserId = ActivityManager.getCurrentUser(); + onUserSwitched(ActivityManager.getCurrentUser()); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -123,9 +124,9 @@ public class SecurityControllerImpl implements SecurityController { @Override public String getPrimaryVpnName() { - VpnConfig cfg = mCurrentVpns.get(mCurrentUserId); + VpnConfig cfg = mCurrentVpns.get(mVpnUserId); if (cfg != null) { - return getNameForVpnConfig(cfg, new UserHandle(mCurrentUserId)); + return getNameForVpnConfig(cfg, new UserHandle(mVpnUserId)); } else { return null; } @@ -133,8 +134,8 @@ public class SecurityControllerImpl implements SecurityController { @Override public String getProfileVpnName() { - for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) { - if (profile.id == mCurrentUserId) { + for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) { + if (profile.id == mVpnUserId) { continue; } VpnConfig cfg = mCurrentVpns.get(profile.id); @@ -147,7 +148,7 @@ public class SecurityControllerImpl implements SecurityController { @Override public boolean isVpnEnabled() { - for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) { + for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) { if (mCurrentVpns.get(profile.id) != null) { return true; } @@ -172,6 +173,12 @@ public class SecurityControllerImpl implements SecurityController { @Override public void onUserSwitched(int newUserId) { mCurrentUserId = newUserId; + if (mUserManager.getUserInfo(newUserId).isRestricted()) { + // VPN for a restricted profile is routed through its owner user + mVpnUserId = UserHandle.USER_OWNER; + } else { + mVpnUserId = mCurrentUserId; + } fireCallbacks(); } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 3ea384c..b9993b1 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -17,11 +17,13 @@ package com.android.server.pm; import android.Manifest; +import android.app.DownloadManager; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal.PackagesProvider; import android.content.pm.PackageParser; +import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Build; @@ -228,6 +230,7 @@ final class DefaultPermissionGrantPolicy { for (int i = 0; i < installerCount; i++) { PackageParser.Package installPackage = installerPackages.get(i); grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId); + grantRuntimePermissionsLPw(installPackage, STORAGE_PERMISSIONS, userId); } // Verifiers @@ -239,6 +242,7 @@ final class DefaultPermissionGrantPolicy { for (int i = 0; i < verifierCount; i++) { PackageParser.Package verifierPackage = verifierPackages.get(i); grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId); + grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, userId); } // SetupWizard @@ -273,6 +277,30 @@ final class DefaultPermissionGrantPolicy { && doesPackageSupportRuntimePermissions(cameraPackage)) { grantRuntimePermissionsLPw(cameraPackage, CAMERA_PERMISSIONS, userId); grantRuntimePermissionsLPw(cameraPackage, MICROPHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(cameraPackage, STORAGE_PERMISSIONS, userId); + } + + // Media provider + PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackageLPr( + MediaStore.AUTHORITY, userId); + if (mediaStorePackage != null) { + grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, userId); + } + + // Downloads provider + PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackageLPr( + "downloads", userId); + if (downloadsPackage != null) { + grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, userId); + } + + // Downloads UI + Intent downloadsUiIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS); + PackageParser.Package downloadsUiPackage = getDefaultSystemHandlerActvityPackageLPr( + downloadsUiIntent, userId); + if (downloadsUiPackage != null + && doesPackageSupportRuntimePermissions(downloadsUiPackage)) { + grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, userId); } // Messaging @@ -452,6 +480,15 @@ final class DefaultPermissionGrantPolicy { return null; } + private PackageParser.Package getDefaultProviderAuthorityPackageLPr( + String authority, int userId) { + ProviderInfo provider = mService.resolveContentProvider(authority, 0, userId); + if (provider != null) { + return getSystemPackageLPr(provider.packageName); + } + return null; + } + private PackageParser.Package getSystemPackageLPr(String packageName) { PackageParser.Package pkg = mService.mPackages.get(packageName); if (pkg != null && pkg.isSystemApp()) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 40ff3f4..1fd68b8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3340,6 +3340,27 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public void resetRuntimePermissions() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, + "revokeRuntimePermission"); + + int callingUid = Binder.getCallingUid(); + if (callingUid != Process.SYSTEM_UID && callingUid != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "resetRuntimePermissions"); + } + + synchronized (mPackages) { + updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL); + for (int userId : UserManagerService.getInstance().getUserIds()) { + mDefaultPermissionPolicy.grantDefaultPermissions(userId); + } + } + } + + @Override public int getPermissionFlags(String name, String packageName, int userId) { if (!sUserManager.exists(userId)) { return 0; @@ -14190,6 +14211,7 @@ public class PackageManagerService extends IPackageManager.Stub { boolean checkin = false; String packageName = null; + ArraySet<String> permissionNames = null; int opti = 0; while (opti < args.length) { @@ -14213,6 +14235,7 @@ public class PackageManagerService extends IPackageManager.Stub { pw.println(" k[eysets]: print known keysets"); pw.println(" r[esolvers]: dump intent resolvers"); pw.println(" perm[issions]: dump permissions"); + pw.println(" permission [name ...]: dump declaration and use of given permission"); pw.println(" pref[erred]: print preferred package settings"); pw.println(" preferred-xml [--full]: print preferred package settings as xml"); pw.println(" prov[iders]: dump content providers"); @@ -14254,6 +14277,18 @@ public class PackageManagerService extends IPackageManager.Stub { dumpState.setDump(DumpState.DUMP_RESOLVERS); } else if ("perm".equals(cmd) || "permissions".equals(cmd)) { dumpState.setDump(DumpState.DUMP_PERMISSIONS); + } else if ("permission".equals(cmd)) { + if (opti >= args.length) { + pw.println("Error: permission requires permission name"); + return; + } + permissionNames = new ArraySet<>(); + while (opti < args.length) { + permissionNames.add(args[opti]); + opti++; + } + dumpState.setDump(DumpState.DUMP_PERMISSIONS + | DumpState.DUMP_PACKAGES | DumpState.DUMP_SHARED_USERS); } else if ("pref".equals(cmd) || "preferred".equals(cmd)) { dumpState.setDump(DumpState.DUMP_PREFERRED); } else if ("preferred-xml".equals(cmd)) { @@ -14536,8 +14571,8 @@ public class PackageManagerService extends IPackageManager.Stub { } if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) { - mSettings.dumpPermissionsLPr(pw, packageName, dumpState); - if (packageName == null) { + mSettings.dumpPermissionsLPr(pw, packageName, permissionNames, dumpState); + if (packageName == null && permissionNames == null) { for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) { if (iperm == 0) { if (dumpState.onTitlePrinted()) @@ -14597,11 +14632,11 @@ public class PackageManagerService extends IPackageManager.Stub { } if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) { - mSettings.dumpPackagesLPr(pw, packageName, dumpState, checkin); + mSettings.dumpPackagesLPr(pw, packageName, permissionNames, dumpState, checkin); } if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) { - mSettings.dumpSharedUsersLPr(pw, packageName, dumpState, checkin); + mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin); } if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) { diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java index 04beafd..57ef284 100644 --- a/services/core/java/com/android/server/pm/PermissionsState.java +++ b/services/core/java/com/android/server/pm/PermissionsState.java @@ -219,6 +219,22 @@ public final class PermissionsState { } /** + * Returns whether the state has any known request for the given permission name, + * whether or not it has been granted. + */ + public boolean hasRequestedPermission(ArraySet<String> names) { + if (mPermissions == null) { + return false; + } + for (int i=names.size()-1; i>=0; i--) { + if (mPermissions.get(names.valueAt(i)) != null) { + return true; + } + } + return false; + } + + /** * Gets all permissions for a given device user id regardless if they * are install time or runtime permissions. * @@ -446,7 +462,7 @@ public final class PermissionsState { } } - return permissionStates; + return permissionStates; } private int grantPermission(BasePermission permission, int userId) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index dcd7799..c547749 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3881,8 +3881,9 @@ final class Settings { ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE", }; - void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, PackageSetting ps, - SimpleDateFormat sdf, Date date, List<UserInfo> users) { + void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, + ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf, + Date date, List<UserInfo> users) { if (checkinTag != null) { pw.print(checkinTag); pw.print(","); @@ -3953,10 +3954,13 @@ final class Settings { } pw.print(prefix); pw.print(" pkg="); pw.println(ps.pkg); pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString); - pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString); - pw.print(prefix); pw.print(" legacyNativeLibraryDir="); pw.println(ps.legacyNativeLibraryPathString); - pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString); - pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString); + if (permissionNames == null) { + pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString); + pw.print(prefix); pw.print(" legacyNativeLibraryDir="); + pw.println(ps.legacyNativeLibraryPathString); + pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString); + pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString); + } pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode); if (ps.pkg != null) { pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion); @@ -3969,8 +3973,10 @@ final class Settings { pw.println(ps.pkg.applicationInfo.toString()); pw.print(prefix); pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags, FLAG_DUMP_SPEC); pw.println(); - pw.print(prefix); pw.print(" priavateFlags="); printFlags(pw, - ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println(); + if (ps.pkg.applicationInfo.privateFlags != 0) { + pw.print(prefix); pw.print(" privateFlags="); printFlags(pw, + ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println(); + } pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); pw.print(prefix); pw.print(" supportsScreens=["); boolean first = true; @@ -4063,9 +4069,9 @@ final class Settings { pw.print(prefix); pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC); pw.println(); - if (ps.sharedUser == null) { + if (ps.sharedUser == null || permissionNames != null) { PermissionsState permissionsState = ps.getPermissionsState(); - dumpInstallPermissionsLPr(pw, prefix + " ", permissionsState); + dumpInstallPermissionsLPr(pw, prefix + " ", permissionNames, permissionsState); } for (UserInfo user : users) { @@ -4089,28 +4095,31 @@ final class Settings { if (ps.sharedUser == null) { PermissionsState permissionsState = ps.getPermissionsState(); dumpGidsLPr(pw, prefix + " ", permissionsState.computeGids(user.id)); - dumpRuntimePermissionsLPr(pw, prefix + " ", permissionsState + dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissionsState .getRuntimePermissionStates(user.id)); } - ArraySet<String> cmp = ps.getDisabledComponents(user.id); - if (cmp != null && cmp.size() > 0) { - pw.print(prefix); pw.println(" disabledComponents:"); - for (String s : cmp) { - pw.print(prefix); pw.print(" "); pw.println(s); + if (permissionNames == null) { + ArraySet<String> cmp = ps.getDisabledComponents(user.id); + if (cmp != null && cmp.size() > 0) { + pw.print(prefix); pw.println(" disabledComponents:"); + for (String s : cmp) { + pw.print(prefix); pw.print(" "); pw.println(s); + } } - } - cmp = ps.getEnabledComponents(user.id); - if (cmp != null && cmp.size() > 0) { - pw.print(prefix); pw.println(" enabledComponents:"); - for (String s : cmp) { - pw.print(prefix); pw.print(" "); pw.println(s); + cmp = ps.getEnabledComponents(user.id); + if (cmp != null && cmp.size() > 0) { + pw.print(prefix); pw.println(" enabledComponents:"); + for (String s : cmp) { + pw.print(prefix); pw.print(" "); pw.println(s); + } } } } } - void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState, boolean checkin) { + void dumpPackagesLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames, + DumpState dumpState, boolean checkin) { final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); final Date date = new Date(); boolean printedSomething = false; @@ -4120,6 +4129,10 @@ final class Settings { && !packageName.equals(ps.name)) { continue; } + if (permissionNames != null + && !ps.getPermissionsState().hasRequestedPermission(permissionNames)) { + continue; + } if (!checkin && packageName != null) { dumpState.setSharedUser(ps.sharedUser); @@ -4131,11 +4144,11 @@ final class Settings { pw.println("Packages:"); printedSomething = true; } - dumpPackageLPr(pw, " ", checkin ? "pkg" : null, ps, sdf, date, users); + dumpPackageLPr(pw, " ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users); } printedSomething = false; - if (!checkin && mRenamedPackages.size() > 0) { + if (!checkin && mRenamedPackages.size() > 0 && permissionNames == null) { for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) { if (packageName != null && !packageName.equals(e.getKey()) && !packageName.equals(e.getValue())) { @@ -4159,7 +4172,7 @@ final class Settings { } printedSomething = false; - if (mDisabledSysPackages.size() > 0) { + if (mDisabledSysPackages.size() > 0 && permissionNames == null) { for (final PackageSetting ps : mDisabledSysPackages.values()) { if (packageName != null && !packageName.equals(ps.realName) && !packageName.equals(ps.name)) { @@ -4171,17 +4184,22 @@ final class Settings { pw.println("Hidden system packages:"); printedSomething = true; } - dumpPackageLPr(pw, " ", checkin ? "dis" : null, ps, sdf, date, users); + dumpPackageLPr(pw, " ", checkin ? "dis" : null, permissionNames, ps, sdf, date, + users); } } } - void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) { + void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames, + DumpState dumpState) { boolean printedSomething = false; for (BasePermission p : mPermissions.values()) { if (packageName != null && !packageName.equals(p.sourcePackage)) { continue; } + if (permissionNames != null && !permissionNames.contains(p.name)) { + continue; + } if (!printedSomething) { if (dumpState.onTitlePrinted()) pw.println(); @@ -4211,13 +4229,17 @@ final class Settings { } } - void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState, - boolean checkin) { + void dumpSharedUsersLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames, + DumpState dumpState, boolean checkin) { boolean printedSomething = false; for (SharedUserSetting su : mSharedUsers.values()) { if (packageName != null && su != dumpState.getSharedUser()) { continue; } + if (permissionNames != null + && !su.getPermissionsState().hasRequestedPermission(permissionNames)) { + continue; + } if (!checkin) { if (!printedSomething) { if (dumpState.onTitlePrinted()) @@ -4235,7 +4257,7 @@ final class Settings { pw.print(prefix); pw.print("userId="); pw.println(su.userId); PermissionsState permissionsState = su.getPermissionsState(); - dumpInstallPermissionsLPr(pw, prefix, permissionsState); + dumpInstallPermissionsLPr(pw, prefix, permissionNames, permissionsState); for (int userId : UserManagerService.getInstance().getUserIds()) { final int[] gids = permissionsState.computeGids(userId); @@ -4244,7 +4266,7 @@ final class Settings { if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) { pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": "); dumpGidsLPr(pw, prefix + " ", gids); - dumpRuntimePermissionsLPr(pw, prefix + " ", permissions); + dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissions); } } } else { @@ -4289,11 +4311,15 @@ final class Settings { } } - void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, + void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames, List<PermissionState> permissionStates) { if (!permissionStates.isEmpty()) { pw.print(prefix); pw.println("runtime permissions:"); for (PermissionState permissionState : permissionStates) { + if (permissionNames != null + && !permissionNames.contains(permissionState.getName())) { + continue; + } pw.print(prefix); pw.print(" "); pw.print(permissionState.getName()); pw.print(", granted="); pw.print(permissionState.isGranted()); pw.print(", flags=0x"); pw.println(Integer.toHexString( @@ -4302,12 +4328,16 @@ final class Settings { } } - void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, + void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames, PermissionsState permissionsState) { List<PermissionState> permissionStates = permissionsState.getInstallPermissionStates(); if (!permissionStates.isEmpty()) { pw.print(prefix); pw.println("install permissions:"); for (PermissionState permissionState : permissionStates) { + if (permissionNames != null + && !permissionNames.contains(permissionState.getName())) { + continue; + } pw.print(prefix); pw.print(" "); pw.print(permissionState.getName()); pw.print(", granted="); pw.print(permissionState.isGranted()); pw.print(", flags=0x"); pw.println(Integer.toHexString( |