summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/system-current.txt64
-rw-r--r--core/java/android/app/ActivityManager.java1
-rw-r--r--core/java/android/app/AppOpsManager.java30
-rw-r--r--core/java/android/content/Intent.java100
-rw-r--r--core/java/android/content/pm/PackageManager.java8
-rw-r--r--core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl29
-rw-r--r--core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.aidl19
-rw-r--r--core/java/android/content/pm/permission/RuntimePermissionPresentationInfo.java110
-rw-r--r--core/java/android/content/pm/permission/RuntimePermissionPresenter.java330
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/RemoteCallback.java2
-rw-r--r--core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java146
-rw-r--r--core/java/android/widget/AppSecurityPermissions.java4
-rw-r--r--core/res/AndroidManifest.xml32
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
16 files changed, 771 insertions, 109 deletions
diff --git a/Android.mk b/Android.mk
index 1c5b08b64035..1cde699bcc06 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,6 +151,7 @@ LOCAL_SRC_FILES += \
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 ecc978d0122d..fd046e49bd70 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46,6 +46,7 @@ package android {
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 @@ package android {
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 @@ package android {
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 @@ package android.app {
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 @@ package android.app {
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 @@ package android.content {
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 @@ package android.content {
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 @@ package android.content {
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 @@ package android.content {
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 @@ package android.content.pm {
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 @@ package android.content.pm {
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 {
}
+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 @@ package android.os {
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 @@ package android.os {
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.os.storage {
}
+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 @@ package android.test.mock {
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 7edc6b761d33..d4400171ea89 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3110,6 +3110,7 @@ public class ActivityManager {
*
* @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 64586a6d8415..783c37de1552 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1256,7 +1256,16 @@ public class AppOpsManager {
}
}
- /** @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 @@ public class AppOpsManager {
}
}
+ /**
+ * 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 8d29dacf0ba2..47abd2bea87f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1561,6 +1561,7 @@ public class Intent implements Parcelable, Cloneable {
* {@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 @@ public class Intent implements Parcelable, Cloneable {
*
* @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 @@ public class Intent implements Parcelable, Cloneable {
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_PERMISSIONS =
"android.intent.action.MANAGE_PERMISSIONS";
@@ -1686,6 +1689,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_REVIEW_PERMISSIONS =
"android.intent.action.REVIEW_PERMISSIONS";
@@ -1698,6 +1702,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @hide
*/
+ @SystemApi
public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
/**
@@ -1717,102 +1722,10 @@ public class Intent implements Parcelable, Cloneable {
*
* @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 @@ public class Intent implements Parcelable, Cloneable {
*
* @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 cf3e893d7d7a..b04cbc58b166 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2367,6 +2367,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_USER_SET = 1 << 0;
/**
@@ -2376,6 +2377,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_USER_FIXED = 1 << 1;
/**
@@ -2385,6 +2387,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_POLICY_FIXED = 1 << 2;
/**
@@ -2397,6 +2400,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 1 << 3;
/**
@@ -2405,6 +2409,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_SYSTEM_FIXED = 1 << 4;
/**
@@ -2415,6 +2420,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 1 << 5;
/**
@@ -2423,6 +2429,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @SystemApi
public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 1 << 6;
/**
@@ -3124,6 +3131,7 @@ public abstract class PackageManager {
*
* @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 000000000000..8766508a5c89
--- /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 000000000000..f96a32f68bd8
--- /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 000000000000..352e8ad106b8
--- /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 000000000000..2e39926422fe
--- /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 d0029e192d31..7e1fc1539d72 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 @@ public class Build {
*
* @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 89e30a96f65d..7dbcb9507185 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -18,10 +18,12 @@ package android.os;
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 000000000000..405be1a2520c
--- /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 a12b15ef0129..1a1680a16f41 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 @@ public class AppSecurityPermissions {
private final CharSequence mNewPermPrefix;
private String mPackageName;
+ /** @hide */
static class MyPermissionGroupInfo extends PermissionGroupInfo {
CharSequence mLabel;
@@ -104,6 +106,7 @@ public class AppSecurityPermissions {
}
}
+ /** @hide */
private static class MyPermissionInfo extends PermissionInfo {
CharSequence mLabel;
@@ -128,6 +131,7 @@ public class AppSecurityPermissions {
}
}
+ /** @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 0ef72cd7b371..acf967548d21 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 468d79cbd9cd..1e74f810afc8 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 @@ public final class ActivityManagerService extends ActivityManagerNative
|| 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)