Cleanup of the PackageInstaller API - Frameworks

The PackageInstaller app manages side-loading apps as well
as permission management. It should be updatable, hence
should rely on system APIs to talk to the platform. This
is the first step of defining an API boundary.

Change-Id: I9814eafd0b22ae03b4b847a7007cdbf14c9e5466
diff --git a/Android.mk b/Android.mk
index 1c5b08b..1cde699 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,6 +151,7 @@
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
 	core/java/android/content/pm/IShortcutService.aidl \
+	core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	../av/camera/aidl/android/hardware/ICameraService.aidl \
 	../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
diff --git a/api/system-current.txt b/api/system-current.txt
index ecc978d..fd046e4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46,6 +46,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
     field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
@@ -109,6 +110,7 @@
     field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
     field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
     field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
+    field public static final java.lang.String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
     field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
     field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC";
     field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
@@ -118,14 +120,17 @@
     field public static final java.lang.String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
     field public static final java.lang.String INTENT_FILTER_VERIFICATION_AGENT = "android.permission.INTENT_FILTER_VERIFICATION_AGENT";
     field public static final java.lang.String INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
+    field public static final java.lang.String INTERACT_ACROSS_USERS_FULL = "android.permission.INTERACT_ACROSS_USERS_FULL";
     field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
     field public static final java.lang.String INTERNET = "android.permission.INTERNET";
     field public static final java.lang.String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
+    field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
     field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
+    field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
     field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
@@ -3824,6 +3829,7 @@
     method public static boolean isRunningInTestHarness();
     method public static boolean isUserAMonkey();
     method public void killBackgroundProcesses(java.lang.String);
+    method public void killUid(int, java.lang.String);
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
     method public deprecated void restartPackage(java.lang.String);
@@ -4130,6 +4136,7 @@
     method public int noteProxyOp(java.lang.String, java.lang.String);
     method public int noteProxyOpNoThrow(java.lang.String, java.lang.String);
     method public static java.lang.String permissionToOp(java.lang.String);
+    method public void setUidMode(java.lang.String, int, int);
     method public int startOp(java.lang.String, int, java.lang.String);
     method public int startOpNoThrow(java.lang.String, int, java.lang.String);
     method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
@@ -8895,8 +8902,11 @@
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
+    field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
+    field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
+    field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
     field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -8940,6 +8950,7 @@
     field public static final java.lang.String ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
     field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
     field public static final java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+    field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
     field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
     field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
     field public static final java.lang.String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
@@ -9046,6 +9057,7 @@
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+    field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
     field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
@@ -9056,12 +9068,14 @@
     field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
+    field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
     field public static final java.lang.String EXTRA_REPLACEMENT_EXTRAS = "android.intent.extra.REPLACEMENT_EXTRAS";
     field public static final java.lang.String EXTRA_REPLACING = "android.intent.extra.REPLACING";
     field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
     field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent";
     field public static final java.lang.String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list";
+    field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
     field public static final java.lang.String EXTRA_RESULT_RECEIVER = "android.intent.extra.RESULT_RECEIVER";
     field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
     field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
@@ -10079,6 +10093,7 @@
     method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
     method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
     method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method public abstract java.lang.String getInstallerPackageName(java.lang.String);
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
@@ -10230,6 +10245,13 @@
     field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
     field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
+    field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
+    field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
+    field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
+    field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
+    field public static final int FLAG_PERMISSION_SYSTEM_FIXED = 16; // 0x10
+    field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
+    field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
     field public static final int GET_ACTIVITIES = 1; // 0x1
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field public static final deprecated int GET_DISABLED_COMPONENTS = 512; // 0x200
@@ -10526,6 +10548,20 @@
 
 }
 
+package android.content.pm.permission {
+
+  public final class RuntimePermissionPresentationInfo implements android.os.Parcelable {
+    ctor public RuntimePermissionPresentationInfo(java.lang.CharSequence, boolean, boolean);
+    method public int describeContents();
+    method public java.lang.CharSequence getLabel();
+    method public boolean isGranted();
+    method public boolean isStandard();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.permission.RuntimePermissionPresentationInfo> CREATOR;
+  }
+
+}
+
 package android.content.res {
 
   public class AssetFileDescriptor implements java.io.Closeable android.os.Parcelable {
@@ -30770,6 +30806,7 @@
     field public static final java.lang.String ID;
     field public static final java.lang.String MANUFACTURER;
     field public static final java.lang.String MODEL;
+    field public static final boolean PERMISSIONS_REVIEW_REQUIRED;
     field public static final java.lang.String PRODUCT;
     field public static final deprecated java.lang.String RADIO;
     field public static final java.lang.String SERIAL;
@@ -31649,6 +31686,19 @@
     method public abstract void onProgress(int);
   }
 
+  public final class RemoteCallback implements android.os.Parcelable {
+    ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener);
+    ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener, android.os.Handler);
+    method public int describeContents();
+    method public void sendResult(android.os.Bundle);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.RemoteCallback> CREATOR;
+  }
+
+  public static abstract interface RemoteCallback.OnResultListener {
+    method public abstract void onResult(android.os.Bundle);
+  }
+
   public class RemoteCallbackList {
     ctor public RemoteCallbackList();
     method public int beginBroadcast();
@@ -32125,6 +32175,19 @@
 
 }
 
+package android.permissionpresenterservice {
+
+  public abstract class RuntimePermissionPresenterService extends android.app.Service {
+    ctor public RuntimePermissionPresenterService();
+    method public final void attachBaseContext(android.content.Context);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract java.util.List<android.content.pm.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
+    method public abstract java.util.List<android.content.pm.ApplicationInfo> onGetAppsUsingPermissions(boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.permissionpresenterservice.RuntimePermissionPresenterService";
+  }
+
+}
+
 package android.preference {
 
   public class CheckBoxPreference extends android.preference.TwoStatePreference {
@@ -41034,6 +41097,7 @@
     method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
     method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
     method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method public java.lang.String getInstallerPackageName(java.lang.String);
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7edc6b7..d440017 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3110,6 +3110,7 @@
      *
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.KILL_UID)
     public void killUid(int uid, String reason) {
         try {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 64586a6..783c37d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1256,7 +1256,16 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Sets given app op in the specified mode for app ops in the UID.
+     * This applies to all apps currently in the UID or installed in
+     * this UID in the future.
+     *
+     * @param code The app op.
+     * @param uid The UID for which to set the app.
+     * @param mode The app op mode to set.
+     * @hide
+     */
     public void setUidMode(int code, int uid, int mode) {
         try {
             mService.setUidMode(code, uid, mode);
@@ -1265,6 +1274,25 @@
         }
     }
 
+    /**
+     * Sets given app op in the specified mode for app ops in the UID.
+     * This applies to all apps currently in the UID or installed in
+     * this UID in the future.
+     *
+     * @param appOp The app op.
+     * @param uid The UID for which to set the app.
+     * @param mode The app op mode to set.
+     * @hide
+     */
+    @SystemApi
+    public void setUidMode(String appOp, int uid, int mode) {
+        try {
+            mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public void setUserRestriction(int code, boolean restricted, IBinder token) {
         setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8d29dac..47abd2b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1561,6 +1561,7 @@
      * {@link} #ACTION_VIEW} to indicate the uid of the package that initiated the install
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_ORIGINATING_UID
             = "android.intent.extra.ORIGINATING_UID";
 
@@ -1634,6 +1635,7 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_APP_PERMISSIONS =
             "android.intent.action.MANAGE_APP_PERMISSIONS";
@@ -1649,6 +1651,7 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_PERMISSIONS =
             "android.intent.action.MANAGE_PERMISSIONS";
@@ -1686,6 +1689,7 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_REVIEW_PERMISSIONS =
             "android.intent.action.REVIEW_PERMISSIONS";
@@ -1698,6 +1702,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
 
     /**
@@ -1717,102 +1722,10 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
 
     /**
-     * Broadcast action that requests current permission granted information.  It will respond
-     * to the request by sending a broadcast with action defined by
-     * {@link #EXTRA_GET_PERMISSIONS_RESPONSE_INTENT}. The response will contain
-     * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}, as well as
-     * {@link #EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT}, with contents described below or
-     * a null upon failure.
-     *
-     * <p>If {@link #EXTRA_PACKAGE_NAME} is included then the number of permissions granted, the
-     * number of permissions requested and the number of granted additional permissions
-     * by that package will be calculated and included as the first
-     * and second elements respectively of an int[] in the response as
-     * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}.  The response will also deliver the list
-     * of localized permission group names that are granted in
-     * {@link #EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT}.
-     *
-     * <p>If {@link #EXTRA_PACKAGE_NAME} is not included then the number of apps granted any runtime
-     * permissions and the total number of apps requesting runtime permissions will be the first
-     * and second elements respectively of an int[] in the response as
-     * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}.
-     *
-     * @hide
-     */
-    public static final String ACTION_GET_PERMISSIONS_COUNT
-            = "android.intent.action.GET_PERMISSIONS_COUNT";
-
-    /**
-     * Broadcast action that requests list of all apps that have runtime permissions.  It will
-     * respond to the request by sending a broadcast with action defined by
-     * {@link #EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT}. The response will contain
-     * {@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT}, as well as
-     * {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT}, with contents described below or
-     * a null upon failure.
-     *
-     * <p>{@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT} will contain a list of package names of
-     * apps that have runtime permissions. {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT}
-     * will contain the list of app labels corresponding ot the apps in the first list.
-     *
-     * @hide
-     */
-    public static final String ACTION_GET_PERMISSIONS_PACKAGES
-            = "android.intent.action.GET_PERMISSIONS_PACKAGES";
-
-    /**
-     * Extra included in response to {@link #ACTION_GET_PERMISSIONS_COUNT}.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_COUNT_RESULT
-            = "android.intent.extra.GET_PERMISSIONS_COUNT_RESULT";
-
-    /**
-     * List of CharSequence of localized permission group labels.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT
-            = "android.intent.extra.GET_PERMISSIONS_GROUP_LIST_RESULT";
-
-    /**
-     * String list of apps that have one or more runtime permissions.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_APP_LIST_RESULT
-            = "android.intent.extra.GET_PERMISSIONS_APP_LIST_RESULT";
-
-    /**
-     * String list of app labels for apps that have one or more runtime permissions.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT
-            = "android.intent.extra.GET_PERMISSIONS_APP_LABEL_LIST_RESULT";
-
-    /**
-     * Boolean list describing if the app is a system app for apps that have one or more runtime
-     * permissions.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT
-            = "android.intent.extra.GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT";
-
-    /**
-     * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_COUNT} broadcasts.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_RESPONSE_INTENT
-            = "android.intent.extra.GET_PERMISSIONS_RESONSE_INTENT";
-
-    /**
-     * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_PACKAGES} broadcasts.
-     * @hide
-     */
-    public static final String EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT
-            = "android.intent.extra.GET_PERMISSIONS_PACKAGES_RESONSE_INTENT";
-
-    /**
      * Activity action: Launch UI to manage which apps have a given permission.
      * <p>
      * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access
@@ -1826,6 +1739,7 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_PERMISSION_APPS =
             "android.intent.action.MANAGE_PERMISSION_APPS";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cf3e893..b04cbc5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2367,6 +2367,7 @@
     *
     * @hide
     */
+    @SystemApi
     public static final int FLAG_PERMISSION_USER_SET = 1 << 0;
 
     /**
@@ -2376,6 +2377,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_USER_FIXED =  1 << 1;
 
     /**
@@ -2385,6 +2387,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_POLICY_FIXED =  1 << 2;
 
     /**
@@ -2397,6 +2400,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE =  1 << 3;
 
     /**
@@ -2405,6 +2409,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_SYSTEM_FIXED =  1 << 4;
 
     /**
@@ -2415,6 +2420,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT =  1 << 5;
 
     /**
@@ -2423,6 +2429,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int FLAG_PERMISSION_REVIEW_REQUIRED =  1 << 6;
 
     /**
@@ -3124,6 +3131,7 @@
      *
      * @hide
      */
+    @SystemApi
     public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
             @UserIdInt int userId);
 
diff --git a/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
new file mode 100644
index 0000000..8766508
--- /dev/null
+++ b/core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+import android.os.RemoteCallback;
+
+/**
+ * Interface for communication with the permission presenter service.
+ *
+ * @hide
+ */
+oneway interface IRuntimePermissionPresenter {
+    void getAppPermissions(String packageName, in RemoteCallback callback);
+    void getAppsUsingPermissions(boolean system, in RemoteCallback callback);
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.aidl b/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.aidl
new file mode 100644
index 0000000..f96a32f
--- /dev/null
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+parcelable RuntimePermissionPresentationInfo;
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.java b/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.java
new file mode 100644
index 0000000..352e8ad
--- /dev/null
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains information about how a runtime permission
+ * is to be presented in the UI. A single runtime permission
+ * presented to the user may correspond to multiple platform defined
+ * permissions, e.g. the location permission may control both the
+ * coarse and fine platform permissions.
+ *
+ * @hide
+ */
+@SystemApi
+public final class RuntimePermissionPresentationInfo implements Parcelable {
+    private static final int FLAG_GRANTED = 1 << 0;
+    private static final int FLAG_STANDARD = 1 << 1;
+
+    private final CharSequence mLabel;
+    private final int mFlags;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param label The permission label.
+     * @param granted Whether the permission is granted.
+     * @param standard Whether this is a platform-defined permission.
+     */
+    public RuntimePermissionPresentationInfo(CharSequence label,
+            boolean granted, boolean standard) {
+        mLabel = label;
+        int flags = 0;
+        if (granted) {
+            flags |= FLAG_GRANTED;
+        }
+        if (standard) {
+            flags |= FLAG_STANDARD;
+        }
+        mFlags = flags;
+    }
+
+    private RuntimePermissionPresentationInfo(Parcel parcel) {
+        mLabel = parcel.readCharSequence();
+        mFlags = parcel.readInt();
+    }
+
+    /**
+     * @return Whether the permission is granted.
+     */
+    public boolean isGranted() {
+        return (mFlags & FLAG_GRANTED) != 0;
+    }
+
+    /**
+     * @return Whether the permission is platform-defined.
+     */
+    public boolean isStandard() {
+        return (mFlags & FLAG_STANDARD) != 0;
+    }
+
+    /**
+     * Gets the permission label.
+     *
+     * @return The label.
+     */
+    public @NonNull CharSequence getLabel() {
+        return mLabel;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeCharSequence(mLabel);
+        parcel.writeInt(mFlags);
+    }
+
+    public static final Creator<RuntimePermissionPresentationInfo> CREATOR =
+            new Creator<RuntimePermissionPresentationInfo>() {
+        public RuntimePermissionPresentationInfo createFromParcel(Parcel source) {
+            return new RuntimePermissionPresentationInfo(source);
+        }
+
+        public RuntimePermissionPresentationInfo[] newArray(int size) {
+            return new RuntimePermissionPresentationInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
new file mode 100644
index 0000000..2e39926
--- /dev/null
+++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.permissionpresenterservice.RuntimePermissionPresenterService;
+import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class provides information about runtime permissions for a specific
+ * app or all apps. This information is dedicated for presentation purposes
+ * and does not necessarily reflect the individual permissions requested/
+ * granted to an app as the platform may be grouping permissions to improve
+ * presentation and help the user make an informed choice. For example, all
+ * runtime permissions in the same permission group may be presented as a
+ * single permission in the UI.
+ *
+ * @hide
+ */
+public final class RuntimePermissionPresenter {
+    private static final String TAG = "RuntimePermPresenter";
+
+    /**
+     * The key for retrieving the result from the returned bundle.
+     *
+     * @hide
+     */
+    public static final String KEY_RESULT =
+            "android.content.pm.permission.RuntimePermissionPresenter.key.result";
+
+    /**
+     * Listener for delivering a result.
+     */
+    public static abstract class OnResultCallback {
+        /**
+         * The result for {@link #getAppPermissions(String, OnResultCallback, Handler)}.
+         * @param permissions The permissions list.
+         */
+        public void onGetAppPermissions(@NonNull
+                List<RuntimePermissionPresentationInfo> permissions) {
+            /* do nothing - stub */
+        }
+
+        /**
+         * The result for {@link #getAppsUsingPermissions(boolean, List)}.
+         * @param system Whether to return only the system apps or only the non-system ones.
+         * @param apps The apps using runtime permissions.
+         */
+        public void getAppsUsingPermissions(boolean system, @NonNull List<ApplicationInfo> apps) {
+            /* do nothing - stub */
+        }
+    }
+
+    private static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static RuntimePermissionPresenter sInstance;
+
+    private final RemoteService mRemoteService;
+
+    /**
+     * Gets the singleton runtime permission presenter.
+     *
+     * @param context Context for accessing resources.
+     * @return The singleton instance.
+     */
+    public static RuntimePermissionPresenter getInstance(@NonNull Context context) {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                sInstance = new RuntimePermissionPresenter(context.getApplicationContext());
+            }
+            return sInstance;
+        }
+    }
+
+    private RuntimePermissionPresenter(Context context) {
+        mRemoteService = new RemoteService(context);
+    }
+
+    /**
+     * Gets the runtime permissions for an app.
+     *
+     * @param packageName The package for which to query.
+     * @param callback Callback to receive the result.
+     * @param handler Handler on which to invoke the callback.
+     */
+    public void getAppPermissions(@NonNull String packageName,
+            @NonNull OnResultCallback callback, @Nullable Handler handler) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = packageName;
+        args.arg2 = callback;
+        args.arg3 = handler;
+        Message message = mRemoteService.obtainMessage(
+                RemoteService.MSG_GET_APP_PERMISSIONS, args);
+        mRemoteService.processMessage(message);
+    }
+
+    /**
+     * Gets the system apps that use runtime permissions. System apps are ones
+     * that are considered system for presentation purposes instead of ones
+     * that are preinstalled on the system image. System apps are ones that
+     * are on the system image, haven't been updated (a.k.a factory apps)
+     * that do not have a launcher icon.
+     *
+     * @param system If true only system apps are returned otherwise only
+     *        non-system ones are returned.
+     * @param callback Callback to receive the result.
+     * @param handler Handler on which to invoke the callback.
+     */
+    public void getAppsUsingPermissions(boolean system, @NonNull OnResultCallback callback,
+            @Nullable Handler handler) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = callback;
+        args.arg2 = handler;
+        args.argi1 = system ? 1 : 0;
+        Message message = mRemoteService.obtainMessage(
+                RemoteService.MSG_GET_APPS_USING_PERMISSIONS, args);
+        mRemoteService.processMessage(message);
+    }
+
+    private static final class RemoteService
+            extends Handler implements ServiceConnection {
+        private static final long UNBIND_TIMEOUT_MILLIS = 10000;
+
+        public static final int MSG_GET_APP_PERMISSIONS = 1;
+        public static final int MSG_GET_APPS_USING_PERMISSIONS = 2;
+        public static final int MSG_UNBIND = 3;
+
+        private final Object mLock = new Object();
+
+        private final Context mContext;
+
+        @GuardedBy("mLock")
+        private final List<Message> mPendingWork = new ArrayList<>();
+
+        @GuardedBy("mLock")
+        private IRuntimePermissionPresenter mRemoteInstance;
+
+        @GuardedBy("mLock")
+        private boolean mBound;
+
+        public RemoteService(Context context) {
+            super(context.getMainLooper(), null, false);
+            mContext = context;
+        }
+
+        public void processMessage(Message message) {
+            synchronized (mLock) {
+                if (!mBound) {
+                    Intent intent = new Intent(
+                            RuntimePermissionPresenterService.SERVICE_INTERFACE);
+                    intent.setPackage(mContext.getPackageManager()
+                            .getPermissionControllerPackageName());
+                    mBound = mContext.bindService(intent, this,
+                            Context.BIND_AUTO_CREATE);
+                }
+                mPendingWork.add(message);
+                scheduleNextMessageIfNeededLocked();
+            }
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized (mLock) {
+                mRemoteInstance = IRuntimePermissionPresenter.Stub.asInterface(service);
+                scheduleNextMessageIfNeededLocked();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            synchronized (mLock) {
+                mRemoteInstance = null;
+            }
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_GET_APP_PERMISSIONS: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final String packageName = (String) args.arg1;
+                    final OnResultCallback callback = (OnResultCallback) args.arg2;
+                    final Handler handler = (Handler) args.arg3;
+                    args.recycle();
+                    final IRuntimePermissionPresenter remoteInstance;
+                    synchronized (mLock) {
+                        remoteInstance = mRemoteInstance;
+                    }
+                    if (remoteInstance == null) {
+                        return;
+                    }
+                    try {
+                        remoteInstance.getAppPermissions(packageName,
+                                new RemoteCallback(new RemoteCallback.OnResultListener() {
+                            @Override
+                            public void onResult(Bundle result) {
+                                final List<RuntimePermissionPresentationInfo> reportedPermissions;
+                                List<RuntimePermissionPresentationInfo> permissions = null;
+                                if (result != null) {
+                                    permissions = result.getParcelableArrayList(KEY_RESULT);
+                                }
+                                if (permissions == null) {
+                                    permissions = Collections.emptyList();
+                                }
+                                reportedPermissions = permissions;
+                                if (handler != null) {
+                                    handler.post(new Runnable() {
+                                        @Override
+                                        public void run() {
+                                            callback.onGetAppPermissions(reportedPermissions);
+                                        }
+                                    });
+                                } else {
+                                    callback.onGetAppPermissions(reportedPermissions);
+                                }
+                            }
+                        }, this));
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Error getting app permissions", re);
+                    }
+                    scheduleUnbind();
+                } break;
+
+                case MSG_GET_APPS_USING_PERMISSIONS: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final OnResultCallback callback = (OnResultCallback) args.arg1;
+                    final Handler handler = (Handler) args.arg2;
+                    final boolean system = args.argi1 == 1;
+                    args.recycle();
+                    final IRuntimePermissionPresenter remoteInstance;
+                    synchronized (mLock) {
+                        remoteInstance = mRemoteInstance;
+                    }
+                    if (remoteInstance == null) {
+                        return;
+                    }
+                    try {
+                        remoteInstance.getAppsUsingPermissions(system, new RemoteCallback(
+                                new RemoteCallback.OnResultListener() {
+                            @Override
+                            public void onResult(Bundle result) {
+                                final List<ApplicationInfo> reportedApps;
+                                List<ApplicationInfo> apps = null;
+                                if (result != null) {
+                                    apps = result.getParcelableArrayList(KEY_RESULT);
+                                }
+                                if (apps == null) {
+                                    apps = Collections.emptyList();
+                                }
+                                reportedApps = apps;
+                                if (handler != null) {
+                                    handler.post(new Runnable() {
+                                        @Override
+                                        public void run() {
+                                            callback.getAppsUsingPermissions(system, reportedApps);
+                                        }
+                                    });
+                                } else {
+                                    callback.getAppsUsingPermissions(system, reportedApps);
+                                }
+                            }
+                        }, this));
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Error getting apps using permissions", re);
+                    }
+                    scheduleUnbind();
+                } break;
+
+                case MSG_UNBIND: {
+                    synchronized (mLock) {
+                        if (mBound) {
+                            mContext.unbindService(this);
+                            mBound = false;
+                        }
+                        mRemoteInstance = null;
+                    }
+                } break;
+            }
+
+            synchronized (mLock) {
+                scheduleNextMessageIfNeededLocked();
+            }
+        }
+
+        private void scheduleNextMessageIfNeededLocked() {
+            if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) {
+                Message nextMessage = mPendingWork.remove(0);
+                sendMessage(nextMessage);
+            }
+        }
+
+        private void scheduleUnbind() {
+            removeMessages(MSG_UNBIND);
+            sendEmptyMessageDelayed(MSG_UNBIND, UNBIND_TIMEOUT_MILLIS);
+        }
+    }
+}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index d0029e1..7e1fc15 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.SystemApi;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -802,6 +803,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final boolean PERMISSIONS_REVIEW_REQUIRED =
             SystemProperties.getInt("ro.permission_review_required", 0) == 1;
 
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index 89e30a9..7dbcb95 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -18,10 +18,12 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 
 /**
  * @hide
  */
+@SystemApi
 public final class RemoteCallback implements Parcelable {
 
     public interface OnResultListener {
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
new file mode 100644
index 0000000..405be1a
--- /dev/null
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permissionpresenterservice;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.permission.IRuntimePermissionPresenter;
+import android.content.pm.permission.RuntimePermissionPresentationInfo;
+import android.content.pm.permission.RuntimePermissionPresenter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallback;
+import com.android.internal.os.SomeArgs;
+
+import java.util.List;
+
+/**
+ * This service presents information regarding runtime permissions that is
+ * used for presenting them in the UI. Runtime permissions are presented as
+ * a single permission in the UI but may be composed of several individual
+ * permissions.
+ *
+ * @see RuntimePermissionPresenter
+ * @see RuntimePermissionPresentationInfo
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class RuntimePermissionPresenterService extends Service {
+
+    /**
+     * The {@link Intent} action that must be declared as handled by a service
+     * in its manifest for the system to recognize it as a runtime permission
+     * presenter service.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.permissionpresenterservice.RuntimePermissionPresenterService";
+
+    // No need for locking - always set first and never modified
+    private Handler mHandler;
+
+    @Override
+    public final void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        mHandler = new MyHandler(base.getMainLooper());
+    }
+
+    /**
+     * Gets the runtime permissions for an app.
+     *
+     * @param packageName The package for which to query.
+     */
+    public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName);
+
+    /**
+     * Gets the apps that use runtime permissions.
+     *
+     * @param system Whether to return only the system apps or only the non-system ones.
+     * @return The app list.
+     */
+    public abstract List<ApplicationInfo> onGetAppsUsingPermissions(boolean system);
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        return new IRuntimePermissionPresenter.Stub() {
+            @Override
+            public void getAppPermissions(String packageName, RemoteCallback callback) {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = packageName;
+                args.arg2 = callback;
+                mHandler.obtainMessage(MyHandler.MSG_GET_APP_PERMISSIONS,
+                        args).sendToTarget();
+            }
+
+            @Override
+            public void getAppsUsingPermissions(boolean system, RemoteCallback callback) {
+                mHandler.obtainMessage(MyHandler.MSG_GET_APPS_USING_PERMISSIONS,
+                        system ? 1 : 0, 0, callback).sendToTarget();
+            }
+        };
+    }
+
+    private final class MyHandler extends Handler {
+        public static final int MSG_GET_APP_PERMISSIONS = 1;
+        public static final int MSG_GET_APPS_USING_PERMISSIONS = 2;
+
+        public MyHandler(Looper looper) {
+            super(looper, null, false);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_GET_APP_PERMISSIONS: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    String packageName = (String) args.arg1;
+                    RemoteCallback callback = (RemoteCallback) args.arg2;
+                    args.recycle();
+                    List<RuntimePermissionPresentationInfo> permissions =
+                            onGetAppPermissions(packageName);
+                    if (permissions != null && !permissions.isEmpty()) {
+                        Bundle result = new Bundle();
+                        result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT,
+                                permissions);
+                        callback.sendResult(result);
+                    } else {
+                        callback.sendResult(null);
+                    }
+                } break;
+
+                case MSG_GET_APPS_USING_PERMISSIONS: {
+                    RemoteCallback callback = (RemoteCallback) msg.obj;
+                    final boolean system = msg.arg1 == 1;
+                    List<ApplicationInfo> apps = onGetAppsUsingPermissions(system);
+                    if (apps != null && !apps.isEmpty()) {
+                        Bundle result = new Bundle();
+                        result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, apps);
+                        callback.sendResult(result);
+                    } else {
+                        callback.sendResult(null);
+                    }
+                } break;
+            }
+        }
+    }
+}
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index a12b15e..1a1680a 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -16,6 +16,7 @@
 */
 package android.widget;
 
+import android.annotation.SystemApi;
 import android.os.UserHandle;
 import com.android.internal.R;
 
@@ -80,6 +81,7 @@
     private final CharSequence mNewPermPrefix;
     private String mPackageName;
 
+    /** @hide */
     static class MyPermissionGroupInfo extends PermissionGroupInfo {
         CharSequence mLabel;
 
@@ -104,6 +106,7 @@
         }
     }
 
+    /** @hide */
     private static class MyPermissionInfo extends PermissionInfo {
         CharSequence mLabel;
 
@@ -128,6 +131,7 @@
         }
     }
 
+    /** @hide */
     public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
         MyPermissionGroupInfo mGroup;
         MyPermissionInfo mPerm;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0ef72cd7..acf9675 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1587,9 +1587,10 @@
     <permission android:name="android.permission.INTERACT_ACROSS_USERS"
         android:protectionLevel="signature|privileged|development" />
 
-    <!-- @hide Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
+    <!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
          that removes restrictions on where broadcasts can be sent and allows other
-         types of interactions. -->
+         types of interactions
+         @hide -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
         android:protectionLevel="signature|installer" />
 
@@ -2082,11 +2083,12 @@
         android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to update application operation statistics. Not for
-         use by third party apps. @hide -->
+         use by third party apps.
+         @hide -->
     <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
         android:protectionLevel="signature|privileged|installer" />
 
-    <!-- Allows an application to update the user app op restrictions.
+    <!-- @SystemApi Allows an application to update the user app op restrictions.
          Not for use by third party apps.
          @hide -->
     <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
@@ -2232,7 +2234,13 @@
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
         android:protectionLevel="signature" />
 
-    <!-- Must be required by a TextService (eg SpellCheckerService)
+    <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
+         that only the system can bind to it.
+         @hide -->
+    <permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
+        android:protectionLevel="signature" />
+
+    <!-- Must be required by a TextService (e.g. SpellCheckerService)
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
@@ -2413,21 +2421,19 @@
     <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows an application to grant specific permissions.
+    <!-- @SystemApi Allows an application to grant specific permissions.
          @hide -->
     <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
         android:protectionLevel="signature|installer|verifier" />
 
-    <!-- Allows an app that has this permission and the permissions to install packages
+    <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
          to request certain runtime permissions to be granted at installation.
-         @hide
-         @SystemApi -->
+         @hide -->
     <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
         android:protectionLevel="signature|installer|verifier" />
 
-    <!-- Allows an application to revoke specific permissions.
-        @hide
-        @SystemApi -->
+    <!-- @SystemApi Allows an application to revoke specific permissions.
+        @hide -->
     <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
          android:protectionLevel="signature|installer|verifier" />
 
@@ -2963,7 +2969,7 @@
     <permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
                 android:protectionLevel="signature" />
 
-    <!-- Allows applications to kill UIDs.
+    <!-- @SystemApi Allows applications to kill UIDs.
         <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.KILL_UID"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 468d79c..1e74f81 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17175,8 +17175,6 @@
                     || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
                     || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
                     || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
-                    || Intent.ACTION_GET_PERMISSIONS_COUNT.equals(action)
-                    || Intent.ACTION_GET_PERMISSIONS_PACKAGES.equals(action)
                     || Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)
                     || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                     || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)