summaryrefslogtreecommitdiffstats
path: root/core/java/android/app/Activity.java
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2015-02-26 14:44:43 -0800
committerSvetoslav <svetoslavganov@google.com>2015-03-23 18:50:35 -0700
commitc6d1c345f41cf817bf2c07c97b97107d94296064 (patch)
tree4bb0bac510ae49524f25a71e3f9e73f5f78cf36f /core/java/android/app/Activity.java
parent3910eb551c7736015708c627dcabaa75c66d9ec3 (diff)
downloadframeworks_base-c6d1c345f41cf817bf2c07c97b97107d94296064.zip
frameworks_base-c6d1c345f41cf817bf2c07c97b97107d94296064.tar.gz
frameworks_base-c6d1c345f41cf817bf2c07c97b97107d94296064.tar.bz2
Runtime permissions: per user permission tracking.
Before all permissions were granted at install time at once, so the user was persented with an all or nothing choice. In the new runtime permissions model all dangarous permissions (nomal are always granted and signature one are granted if signatures match) are not granted at install time and the app can request them as necessary at runtime. Before, all granted permission to an app were identical for all users as granting is performed at install time. However, the new runtime model allows the same app running under two different users to have different runtime permission grants. This change refactors the permissions book keeping in the package manager to enable per user permission tracking. The change also adds the app facing APIs for requesting runtime permissions. Change-Id: Icbf2fc2ced15c42ca206c335996206bd1a4a4be5
Diffstat (limited to 'core/java/android/app/Activity.java')
-rw-r--r--core/java/android/app/Activity.java123
1 files changed, 121 insertions, 2 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7fcbe35..b5817df 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3726,6 +3726,95 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Requests permissions to be granted to this application. These permissions
+ * must be requested in your manifest, they should not be granted to your app,
+ * and they should have protection level {@link android.content.pm.PermissionInfo
+ * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by
+ * the platform or a third-party app.
+ * <p>
+ * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
+ * are granted at install time if requested in the manifest. Signature permissions
+ * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
+ * install time if requested in the manifest and the signature of your app matches
+ * the signature of the app declaring the permissions.
+ * </p>
+ * <p>
+ * If your app does not have the requested permissions the user will be presented
+ * with UI for accepting them. After the user has accepted or rejected the
+ * requested permissions you will receive a callback on {@link
+ * #onRequestPermissionsResult(int, String[], int[])} reporting whether the
+ * permissions were granted or not.
+ * </p>
+ * <p>
+ * Note that requesting a permission does not guarantee it will be granted and
+ * your app should be able to run without having this permission.
+ * </p>
+ * <p>
+ * This method may start an activity allowing the user to choose which permissions
+ * to grant and which to reject. Hence, you should be prepared that your activity
+ * may be paused and resumed. Further, granting some permissions may require
+ * a restart of you application. In such a case, the system will recreate the
+ * activity stack before delivering the result to {@link
+ * #onRequestPermissionsResult(int, String[], int[])}.
+ * </p>
+ * <p>
+ * When checking whether you have a permission you should use {@link
+ * #checkSelfPermission(String)}.
+ * </p>
+ * <p>
+ * A sample permissions request looks like this:
+ * </p>
+ * <code><pre><p>
+ * private void showContacts() {
+ * if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
+ * != PackageManager.PERMISSION_GRANTED) {
+ * requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
+ * PERMISSIONS_REQUEST_READ_CONTACTS);
+ * } else {
+ * doShowContacts();
+ * }
+ * }
+ *
+ * {@literal @}Override
+ * public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ * int[] grantResults) {
+ * if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS
+ * && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ * showContacts();
+ * }
+ * }
+ * </code></pre></p>
+ *
+ * @param permissions The requested permissions.
+ * @param requestCode Application specific request code to match with a result
+ * reported to {@link #onRequestPermissionsResult(int, String[], int[])}.
+ *
+ * @see #onRequestPermissionsResult(int, String[], int[])
+ * @see #checkSelfPermission(String)
+ */
+ public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
+ Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
+ startActivityForResult(intent, requestCode);
+ }
+
+ /**
+ * Callback for the result from requesting permissions. This method
+ * is invoked for every call on {@link #requestPermissions(String[], int)}.
+ *
+ * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
+ * @param permissions The requested permissions. Never null.
+ * @param grantResults The grant results for the corresponding permissions
+ * which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
+ * or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
+ *
+ * @see #requestPermissions(String[], int)
+ */
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ /* callback - no nothing */
+ }
+
+ /**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
@@ -6269,11 +6358,19 @@ public class Activity extends ContextThemeWrapper
+ ", resCode=" + resultCode + ", data=" + data);
mFragments.noteStateNotSaved();
if (who == null) {
- onActivityResult(requestCode, resultCode, data);
+ if (isRequestPermissionResult(data)) {
+ dispatchRequestPermissionsResult(requestCode, data);
+ } else {
+ onActivityResult(requestCode, resultCode, data);
+ }
} else {
Fragment frag = mFragments.findFragmentByWho(who);
if (frag != null) {
- frag.onActivityResult(requestCode, resultCode, data);
+ if (isRequestPermissionResult(data)) {
+ dispatchRequestPermissionsResultToFragment(requestCode, data, frag);
+ } else {
+ frag.onActivityResult(requestCode, resultCode, data);
+ }
}
}
}
@@ -6343,4 +6440,26 @@ public class Activity extends ContextThemeWrapper
*/
public void onTranslucentConversionComplete(boolean drawComplete);
}
+
+ private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
+ String[] permissions = data.getStringArrayExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
+ final int[] grantResults = data.getIntArrayExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS);
+ onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
+ private void dispatchRequestPermissionsResultToFragment(int requestCode, Intent data,
+ Fragment fragement) {
+ String[] permissions = data.getStringArrayExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
+ final int[] grantResults = data.getIntArrayExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS);
+ fragement.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
+ private static boolean isRequestPermissionResult(Intent intent) {
+ return intent != null
+ && PackageManager.ACTION_REQUEST_PERMISSIONS.equals(intent.getAction());
+ }
}