OSDN Git Service

docs: M Runtime Permissions overview.
authorAndrew Solovay <asolovay@google.com>
Wed, 13 May 2015 01:01:13 +0000 (18:01 -0700)
committerAndrew Solovay <asolovay@google.com>
Tue, 26 May 2015 19:53:26 +0000 (12:53 -0700)
Based on the Google Doc which has gone through tech review. See
first comment for doc stage location.

NOTE: Because the M Preview reference docs are not going to be live on
DAC (they'll be downloadable in a zip archive, I believe), we can't
put in live hyperlinks to new-for-M classes/fields/ methods. Those
have to just be in <code> font with no link. This is consistent across
all the preview docs, and will of course change when these docs are
converted for the MNC release.

bug: 21411602
bug: 21411604

Change-Id: I1163abc1dc884cf27b0e94d266f3979f131db2ab

docs/html/preview/features/images/app-permissions-screen.png [new file with mode: 0644]
docs/html/preview/features/images/app-permissions-screen@2x.png [new file with mode: 0644]
docs/html/preview/features/runtime-permissions.jd
docs/image_sources/preview/features/app-permissions-screen-orig.png [new file with mode: 0644]

diff --git a/docs/html/preview/features/images/app-permissions-screen.png b/docs/html/preview/features/images/app-permissions-screen.png
new file mode 100644 (file)
index 0000000..679b7ad
Binary files /dev/null and b/docs/html/preview/features/images/app-permissions-screen.png differ
diff --git a/docs/html/preview/features/images/app-permissions-screen@2x.png b/docs/html/preview/features/images/app-permissions-screen@2x.png
new file mode 100644 (file)
index 0000000..e3eb13f
Binary files /dev/null and b/docs/html/preview/features/images/app-permissions-screen@2x.png differ
index 4a01010..f9646a8 100644 (file)
@@ -1,15 +1,52 @@
-page.title=Android M Preview Runtime Permissions
+page.title=Runtime Permissions
 
 @jd:body
 
 
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>Quickview</h2>
+    <ul>
+      <li>If your app targets the M Preview SDK, it prompts users to grant
+        permissions at runtime, instead of install time.</li>
+      <li>Users can revoke permissions at any time from the app Settings
+        screen.</li>
+      <li>Your app needs to check that it has the permissions it needs every
+        time it runs.</li>
+    </ul>
+
+    <h2>In this document</h2>
+    <ol>
+      <li><a href="#overview">Overview</a></li>
+      <li><a href="#coding">Coding for Runtime Permissions</a></li>
+      <li><a href="#testing">Testing Runtime Permissions</a></li>
+      <li><a href="#best-practices">Best Practices</a></li>
+    </ol>
+
+<!--
+  <h2>Related Samples</h2>
+  <ol>
+    <li></li>
+  </ol>
+-->
+
+<!--
+  <h2>See also</h2>
+  <ol>
+    <li></li>
+  </ol>
+-->
+  </div> <!-- qv -->
+</div> <!-- qv-wrapper -->
+
+
 <p>
-  The M Developer Preview introduces a new app permissions model which makes it
-  less frustrating for users to install and upgrade apps. If an app running on
-  M supports the new permissions model, the user does not have to grant any
-  permissions when they install or upgrade the app. Instead, the app requests
-  permissions as they are needed, and the system shows a dialog to the user
-  asking for the permission.
+  The M Developer Preview introduces a new app permissions model which
+  streamlines the process for users to install and upgrade apps. If an app
+  running on the M Preview supports the new permissions model, the user does not have to
+  grant any permissions when they install or upgrade the app. Instead, the app
+  requests permissions as it needs them, and the system shows a dialog to the
+  user asking for the permission.
 </p>
 
 <p>
@@ -18,70 +55,122 @@ page.title=Android M Preview Runtime Permissions
   model on those devices.
 </p>
 
-<h2>
+<h2 id="overview">
   Overview
 </h2>
 
 <p>
-  If an app's target SDK version is the M developer preview, that indicates
-  that the app uses the new permissions model:
+  With the M Developer Preview, the platform introduces a new app permissions
+  model. Here's a summary of the key components of this new model:
 </p>
 
 <ul>
-  <li>Permissions are divided into <em>permission groups</em>, based on their
-  functionality. For example, all permissions relating to the camera and photo
-  roll are grouped in the Camera permission group,
-  [link]android.permission-group.CAMERA[/link].
+  <li>
+    <strong>Declaring Permissions:</strong> The app declares all the
+    permissions it needs in the manifest, as in earlier Android platforms.
   </li>
 
-  <li>The app declares all the permissions it needs in the manifest, as in
-  earlier Android platforms.
+  <li>
+    <strong>Permission Groups:</strong> Permissions are divided into
+    <em>permission groups</em>, based on their functionality. For example, the
+    <code>CONTACTS</code> permission group contains permissions to read and
+    write the user's contacts and profile information.
   </li>
 
-  <li>When the user installs or updates the app, the app is granted just those
-  permissions it requests that fall under <a href=
-  "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL">
-    <code>PROTECTION_NORMAL</code></a>, as well as signature and system permissions, as
-    described below. The user is <em>not</em> prompted to grant any permissions
-    at this time.
+  <li>
+    <p><strong>Limited Permissions Granted at Install Time:</strong> When the
+    user installs or updates the app, the system grants the app all
+    permissions that the app requests that fall under {@link
+    android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}.
+    For example, alarm clock and internet permissions fall under {@link
+    android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}, so
+    they are automatically granted at install time.
+    </p>
+
+    <p>The system may also grant the app signature and system permissions, as
+    described in <a href="#system-apps">System apps and signature
+    permissions</a>. The user is <em>not</em> prompted to grant any permissions
+    at install time.</p>
   </li>
 
-  <li>When the app needs to perform any action that requires a permission, it
-  first checks whether it has that permission already. If it does not, it
-  requests to be granted that permission.
+  <li>
+    <strong>User Grants Permissions at Run-Time:</strong> When the app requests
+    a permission, the system shows a dialog to the user, then calls the app's
+    callback function to notify it whether the permission was granted. If a
+    user grants a permission, the app is given all permissions in that
+    permission's functional area that were declared in the app manifest.
   </li>
 
-  <li>When the app requests a permission, the system shows a dialog box to the
-  user, then calls the app's callback function to notify it whether the
-  permission was granted. If a user grants a permission, the app is given all
-  permissions in that permission's functional area that were declared in the
-  app manifest.
+</ul>
+
+<p>
+  This permission model changes the way your app behaves for features that
+  require permissions. Here's a summary of the development practices you should
+  follow to adjust to this model:
+</p>
+
+<ul>
+
+  <li>
+    <strong>Always Check for Permissions:</strong> When the app needs to
+    perform any action that requires a permission, it should first check
+    whether it has that permission already. If it does not, it requests to be
+    granted that permission.
   </li>
 
-  <li>If the app is not granted an appropriate permission, it should handle the
-  failure cleanly. For example, if the permission is just needed for an added
-  feature, the app can disable that feature. If the permission is essential for
-  the app to function, the app might disable all its functionality and inform
-  the user that they need to grant that permission.
+  <li>
+    <strong>Handle Lack of Permissions Gracefully:</strong> If the app is not
+    granted an appropriate permission, it should handle the failure cleanly.
+    For example, if the permission is just needed for an added feature, the app
+    can disable that feature. If the permission is essential for the app to
+    function, the app might disable all its functionality and inform the user
+    that they need to grant that permission.
   </li>
 
-  <li>Users can always go to the app's <b>Settings</b> screen and turn on or
-  off any of the app's permissions.
-  <!-- insert screenshot of settings screen-->
-  If a user turns off an app's permissions, the app is
-  <em>not</em> notified.
+  <div class="figure" style="width:220px">
+    <img src="images/app-permissions-screen.png" srcset=
+    "images/app-permissions-screen@2x.png 2x" alt="" width="220" height=
+    "375">
+    <p class="img-caption">
+      <strong>Figure 2.</strong> Permission screen in the app's Settings.
+    </p>
+  </div>
+
+  <li>
+    <strong>Permissions are Revocable:</strong> Users can revoke an app's
+    permissions at any time. If a user turns off an app's permissions, the app
+    is <em>not</em> notified. Once again, your app should verify that it has
+    needed permissions before performing any restricted actions.
   </li>
 </ul>
 
-<h3>
-  System Apps and Signature Permissions
+<p class="note">
+  <strong>Note:</strong> If an app targets the M Developer Preview, it
+  <em>must</em> use the new permissions model.
+</p>
+
+<p>
+  As of the launch of the M Developer Preview, not all Google apps fully
+  implement the new permissions model. Google is updating these apps over
+  the course of the M Developer Preview to properly respect Permissions toggle
+  settings.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> If your app has its own API surface, do not proxy
+  permissions without first ensuring the caller has the requisite permissions
+  to access that data.
+</p>
+
+<h3 id="system-apps">
+  System apps and signature permissions
 </h3>
 
 <p>
-  Ordinarily, an app is just granted the <a href=
-  "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL">
-  <code>PROTECTION_NORMAL</code></a> permissions when it is installed. However,
-  under some circumstances the app is granted more permissions:
+  Ordinarily, when the user installs an app, the system only grants the app the
+  {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL
+  PROTECTION_NORMAL}. However, under some circumstances the system grants the
+  app more permissions:
 </p>
 
 <ul>
@@ -89,37 +178,130 @@ page.title=Android M Preview Runtime Permissions
   the permissions listed in its manifest.
   </li>
 
-  <li>Apps are granted all permissions listed in the manifest that fall under
-  <a href=
-  "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_SIGNATURE">
-    PROTECTION_SIGNATURE</a>, if the app's signature matches the signature of
-    the app that declares the permissions.
+  <li>If the app requests permissions in the manifest that fall under {@link
+  android.content.pm.PermissionInfo#PROTECTION_SIGNATURE PROTECTION_SIGNATURE},
+  and the app is signed with the same certificate as the app that declared
+  those permissions, the system grants the requesting app those permissions on
+  installation.
   </li>
 </ul>
 
 <p>
   In both cases, the user can still revoke permissions at any time by going to
-  the app's <b>Settings</b> screen, so the app should continue to check for
-  permissions at run time and request them if necessary.
+  the system's <strong>Settings</strong> screen and choosing <strong>Apps
+  &gt;</strong> <i>app_name</i> <strong>&gt; Permissions</strong>. The app
+  should continue to check for permissions at run time and request them if
+  necessary.
 </p>
 
-<h3>
-  Forwards and Backwards Compatibility
+<h3 id="compatibility">
+  Forwards and backwards compatibility
 </h3>
 
 <p>
-  If an app does not target the M developer preview, it continues to use the
-  old permissions model even on M devices. When the app is installed, the
-  system asks the user to grant all permissions listed in the app's manifest.
+  If an app does not target the M Developer Preview, the app continues to use
+  the old permissions model even on M Preview devices. When the user installs
+  the app, the system asks the user to grant all permissions listed in the
+  app's manifest.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> On devices running the M Developer Preview, a user can
+  turn off permissions for any app (including legacy apps) from the app's
+  Settings screen. If a user turns off permissions for a legacy app, the system
+  silently disables the appropriate functionality. When the app attempts to
+  perform an operation that requires that permission, the operation will not
+  necessarily cause an exception. Instead, it might return an empty data set,
+  signal an error, or otherwise exhibit unexpected behavior. For example, if you
+  query a calendar without permission, the method returns an empty data set.
+</p>
+
+<p>
+  If you install an app using the new permissions model on a device that is not
+  running the M Preview,
+  the system treats it the same as any other app: the system asks
+  the user to grant all declared permissions at install time.
 </p>
 
+<p class="note">
+  <strong>Note:</strong> For the preview release, you must set the minimum SDK
+  version to the M Preview SDK to compile with the preview SDK. This means you
+  will not be able to test such apps on older platforms during the developer
+  preview.
+</p>
+
+<h3 id="perms-vs-intents">Permissions versus intents</h3>
+
 <p>
-  If an app using the new permissions model is run on a pre-M device, the
-  system treats it the same as any other app. Once again, the system asks the
-  user to grant all declared permissions at install time.
+  In many cases, you can choose between two ways for your app to perform a
+  task. You can have your app ask for permission to perform the operation
+  itself. Alternatively, you can have the app use an intent to have another app
+  perform the task.
 </p>
 
-<h2 id="">Coding for Runtime Permissions</h2>
+<p>
+  For example, suppose your app needs to be able to take pictures with the
+  device camera. Your app can request the
+  <code>android.permission.CAMERA</code> permission, which allows your app to
+  access the camera directly. Your app would then use the camera APIs
+  to control the camera and take a picture. This approach gives your app full
+  control over the photography process, and lets you incorporate the camera UI
+  into your app.
+</p>
+
+<p>
+  However, if you don't need such control, you can just use an {@link
+  android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} intent
+  to request an image. When you start the intent, the user is prompted to
+  choose a camera app (if there isn't already a default camera app), and that
+  app takes the picture. The camera app returns the picture to your app's {@link
+  android.app.Activity#onActivityResult onActivityResult()} method.
+</p>
+
+<p>
+  Similarly, if you need to make a phone call, access the user's contacts, and
+  so on, you can do that by creating an appropriate intent, or you can request
+  the permission and access the appropriate objects directly. There are
+  advantages and disadvantages to each approach.
+</p>
+
+<p>
+  If you use permissions:
+</p>
+
+<ul>
+  <li>Your app has full control over the user experience when you perform the
+  operation. However, such broad control adds to the complexity of your task,
+  since you need to design an appropriate UI.
+  </li>
+
+  <li>The user is prompted to give permission once, the first time you perform
+  the operation. After that, your app can perform the operation without
+  requiring additional interaction from the user. However, if the user doesn't
+  grant the permission (or revokes it later on), your app becomes unable to
+  perform the operation at all.
+  </li>
+</ul>
+
+<p>
+  If you use an intent:
+</p>
+
+<ul>
+  <li>You do not have to design the UI for the operation. The app that handles
+  the intent provides the UI. However, this means you have
+  no control over the user experience. The user could be interacting with an
+  app you've never seen.
+  </li>
+
+  <li>If the user does not have a default app for the operation, the system
+  prompts the user to choose an app. If the user does not designate a default
+  handler, they may have to go
+  through an extra dialog every time they perform the operation.
+  </li>
+</ul>
+
+<h2 id="coding">Coding for Runtime Permissions</h2>
 
 <p>
   If your app targets the new M Developer Preview, you must use the new
@@ -129,44 +311,47 @@ page.title=Android M Preview Runtime Permissions
   have them.
 </p>
 
-<h3>
-  Enabling the New Permissions Model
+<h3 id="enabling">
+  Enabling the new permissions model
 </h3>
 
 <p>
   To enable the new M Developer Preview permissions model, set the app's
-  <a href=
-  "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target">
-  targetSdkVersion</a> attribute to "M". Doing this enables all the new
-  permissions features.
+  <code>targetSdkVersion</code> attribute to <code>"MNC"</code>, and
+  <code>compileSdkVersion</code> to <code>"android-MNC"</code>. Doing so
+  enables all the new permissions features.
 </p>
 
-<!-- TODO: Insert manifest snippet -->
+<p>
+  For the preview release, you must set <code>minSdkVersion</code> to
+  <code>"MNC"</code> to compile with the preview SDK.
+</p>
 
-<h3>
-  Designating a Permission for M Only
+<h3 id="m-only-perm">
+  Designating a permission for the M Preview only
 </h3>
 
 <p>
-  You can use the new <code>&lt;uses-permission-sdk-m&gt;</code> element in the
-  app manifest to indicate that a permission is only needed on the M platform.
-  If you declare a permission this way, then whenever the app is installed on
-  an older device, the user is not prompted to grant the permission and the
-  permission is not granted to the app. This allows you to add new permissions
+  You can use the new <code>&lt;uses-permission-sdk-m&gt;</code> element in the app manifest
+  to indicate that a permission is only needed on the M Developer Preview. If
+  you declare a permission this way, then whenever the app is installed on an
+  older device, the system does not prompt the user or grant the
+  permission to the app. By using the <code>&lt;uses-permission-sdk-m&gt;</code>
+  element, you can add new permissions
   to updated versions of your app without forcing users to grant permissions
   when they install the update.
 </p>
 
 <p>
-  If the app is running on a device with the M developer preview,
+  If the app is running on a device with the M Developer Preview,
   <code>&lt;uses-permission-sdk-m&gt;</code> behaves the same as
-  <code>&lt;uses-permission&gt;</code>. The user is not prompted to grant any
-  permissions when the app is installed, and the app requests permissions as
-  they are needed.
+  <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
+  The system does not prompt the user to grant any permissions when they install
+  the app, and the app requests permissions as they are needed.
 </p>
 
 <h3 id="prompting">
-  Prompting for Permissions on the M Preview
+  Prompting for permissions
 </h3>
 
 <p>
@@ -178,73 +363,348 @@ page.title=Android M Preview Runtime Permissions
 </p>
 
 <p>
-  An app should follow this workflow to request permissions on an Android M
-  device. The device can check what platform it's running on by checking the
-  value of {@link android.os.Build.VERSION#SDK_INT Build.VERSION.SDK_INT}. If
-  the device is running the M Developer Preview, {@link
-  android.os.Build.VERSION#SDK_INT SDK_INT} is 23.
-  <!-- TODO: Confirm this number -->
+  If your app runs on a device that has SDK 22 or lower, the app uses the old
+  permissions model. When the user installs the app, they are prompted to grant
+  all the permissions your app requests in its manifest, except for those
+  permissions which are labeled with <code>&lt;uses-permission-sdk-m&gt;</code>.
 </p>
-<ol>
-  <li>When the user tries to do something that requires a permission, the app
-  checks to see if it currently has permission to perform this operation. To do
-  this, the app calls
-   <a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(<em>permission_name</em>)</code></a> . The
-  app should do this even if it knows the user has already granted that
-  permission, since the user can revoke an app's permissions at any time. For
-  example, if a user wants to use an app to take a picture, the app calls
-  <a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(Manifest.permission.CAMERA)</code></a>.
-  </li>
 
-<!-- TODO: Full list of permissions (or link to that list),
-  and how they break down by functional area]-->
+<h4 id="check-platform">Check what platform the app is running on</h4>
 
-  <li>If the permission is not already granted to the app, the app calls
-  <a href=
-  "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-    <code>requestPermissions()</code></a> to request the
-    appropriate permission or permissions. This method functions
-    asynchronously.
-    <!-- TODO: insert code snippet showing permission check and request -->
-  </li>
+<p>
+  This permissions model is only supported on devices running the M Developer
+  Preview. Before calling any of these methods, the app should verify
+  what platform it's running on
+  by checking the value of {@link android.os.Build.VERSION#CODENAME
+  Build.VERSION.CODENAME}. If the device is running the M Developer Preview,
+  {@link android.os.Build.VERSION#CODENAME CODENAME} is <code>"MNC"</code>.
+</p>
 
-  <li>The system presents a dialog box to the user.
-  <!-- TODO: insert screenshot of permissions dialog box -->
-    When the user responds, the system calls <a href=
-    "https://android-preview.googleplex.com/reference/android/app/Activity.html#onRequestPermissionsResult(int,%20java.lang.String[],%20int[])">
-    <code>Activity.onRequestPermissionsResult()</code></a> with the
-    results; your app needs to override that method. The callback is passed the
-    same request code you passed to <a href=
-    "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-    <code>requestPermissions()</code></a>.
-    <!-- TODO: Insert code snippet of callback method -->
-  </li>
+<h4 id="check-for-permission">Check if the app has the needed permission</h4>
+
+<p>When the user tries to do something that requires a permission, the app
+  checks to see if it currently has permission to perform this operation. To do
+  this, the app calls
+  <code>Context.checkSelfPermission(<i>permission_name</i>)</code>. The app
+  should perform this check even if it knows the user has already granted that
+  permission,
+  since the user can revoke an app's permissions at any time. For example, if a
+  user wants to use an app to take a picture, the app calls
+  <code>Context.checkSelfPermission(Manifest.permission.CAMERA)</code>.</p>
+
+<p class="table-caption" id="permission-groups">
+  <strong>Table 1.</strong> Permissions and permission groups.</p>
+<table>
+  <tr>
+    <th scope="col">Permission Group</th>
+    <th scope="col">Permissions</th>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.CALENDAR</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.READ_CALENDAR</code>
+        </li>
+      </ul>
+      <ul>
+        <li>
+          <code>android.permission.WRITE_CALENDAR</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.CAMERA</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.CAMERA</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.CONTACTS</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.READ_CONTACTS</code>
+        </li>
+        <li>
+          <code>android.permission.WRITE_CONTACTS</code>
+        </li>
+        <li>
+          <code>android.permission.READ_PROFILE</code>
+        </li>
+        <li>
+          <code>android.permission.WRITE_PROFILE</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.LOCATION</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.ACCESS_FINE_LOCATION</code>
+        </li>
+        <li>
+          <code>android.permission.ACCESS_COARSE_LOCATION</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.MICROPHONE</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.RECORD_AUDIO</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.PHONE</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.READ_PHONE_STATE</code>
+        </li>
+        <li>
+          <code>android.permission.CALL_PHONE</code>
+        </li>
+        <li>
+          <code>android.permission.READ_CALL_LOG</code>
+        </li>
+        <li>
+          <code>android.permission.WRITE_CALL_LOG</code>
+        </li>
+        <li>
+          <code>com.android.voicemail.permission.ADD_VOICEMAIL</code>
+        </li>
+        <li>
+          <code>android.permission.USE_SIP</code>
+        </li>
+        <li>
+          <code>android.permission.PROCESS_OUTGOING_CALLS</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.SENSORS</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.BODY_SENSORS</code>
+        </li>
+      </ul>
+      <ul>
+        <li>
+          <code>android.permission.USE_FINGERPRINT</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>android.permission-group.SMS</code></td>
+    <td>
+      <ul>
+        <li>
+          <code>android.permission.SEND_SMS</code>
+        </li>
+        <li>
+          <code>android.permission.RECEIVE_SMS</code>
+        </li>
+        <li>
+          <code>android.permission.READ_SMS</code>
+        </li>
+        <li>
+          <code>android.permission.RECEIVE_WAP_PUSH</code>
+        </li>
+        <li>
+          <code>android.permission.RECEIVE_MMS</code>
+        </li>
+        <li>
+          <code>android.permission.READ_CELL_BROADCASTS</code>
+        </li>
+      </ul>
+    </td>
+  </tr>
+
+</table>
+
+<h4 id="request-permissions">Request permissions if necessary</h4>
+
+<p>If the app doesn't already have the permission it needs, the app calls the
+  <code>Activity.requestPermissions(String[], int)</code> method to
+  request the appropriate permission or permissions. The app passes the
+  permission or permissions it wants, and also an integer "request code".
+  This method functions asynchronously: it returns right away, and after
+  the user responds to the dialog box, the system calls the app's callback
+  method with the results, passing the same "request code" that the app passed
+  to <code>requestPermissions()</code>.</p>
+
+  <p>The following code code checks if the app has permission to read the
+    user's contacts, and requests the permission if necessary:</p>
+
+<pre>
+if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
+        != PackageManager.PERMISSION_GRANTED) {
+    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
+            MY_PERMISSIONS_REQUEST_READ_CONTACTS);
+
+    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
+    // app-defined int constant
+
+    return;
+}
+</pre>
+
+<h4 id="handle-response">Handle the permissions request response</h4>
+
+<p>
+  When an app requests permissions, the system presents a dialog box to the
+  user. When the user responds, the system invokes your app's
+  <code>Activity.onRequestPermissionsResult(int, String[], int[])</code>
+  passing it the user response. Your app needs to override that method. The
+  callback is passed the same request code you passed to
+  <code>requestPermissions()</code>. For example, if an app requests
+  <code>READ_CONTACTS</code> access it might have the following callback
+  method:
+</p>
 
-  <li>If the user grants a permission, the app is given all permissions
-  in that functional area that are listed in the app manifest.
-  If the request is denied, you should take appropriate action. For
-  example, you might disable any menu actions that depend on this permission.
+<pre>
+&#64;Override
+public void onRequestPermissionsResult(int requestCode,
+        String permissions[], int[] grantResults) {
+    switch (requestCode) {
+        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
+            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+
+                // permission was granted, yay! do the
+                // calendar task you need to do.
+
+            } else {
+
+                // permission denied, boo! Disable the
+                // functionality that depends on this permission.
+            }
+            return;
+        }
+
+        // other 'switch' lines to check for other
+        // permissions this app might request
+    }
+}
+</pre>
+
+  <p>If the user grants a permission, the system gives the app all permissions
+  that the app manifest lists for that functional area. If the user denies the
+  request, you should take appropriate action. For example, you might disable
+  any menu actions that depend on this permission.
   </li>
-</ul>
+</p>
 
 <p>
   When the system asks the user to grant a permission, the user has the option
   of telling the system not to ask for that permission again. In that case,
-  when an app asks for that permission with <a href=
-    "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-    <code>requestPermissions()</code></a>, the
-  system immediately denies the request. For this reason, your app cannot
-  assume that any direct interaction with the user has taken place.
+  when an app uses <code>requestPermissions()</code> to ask for that permission,
+  the system immediately denies the request. In this case, the system calls
+  your <code>onRequestPermissionsResult()</code> the same way it would if the
+  user had explicitly rejected your request again. For this reason, your app
+  cannot assume that any direct interaction with the user has taken place.
 </p>
 
+<h2 id="testing">Testing Runtime Permissions</h2>
+
+
 <p>
-  If your app runs on a device that has SDK 22 or lower, the app uses the old
-  permissions model. When the user installs the app, they are prompted to grant
-  all the permissions your app requests in its manifest, except for those
-  permissions which are labeled with <code>&lt;uses-permission-sdk-m&gt;</code>.
+  If your app targets the M Developer Preview, you must test that it
+  handles permissions properly. You cannot assume that your app has any
+  particular permissions when it runs. When the app is first launched, it is
+  likely to have no permissions, and the user can revoke or restore permissions
+  at any time.
+</p>
+
+<p>
+  You should test your app to make sure it behaves properly under all
+  permission situations. With the M Preview SDK, we have provided new
+  <a href="{@docRoot}tools/help/adb.html">Android
+  Debug Bridge (adb)</a> commands to enable you to test your app with whatever
+  permissions settings you need to try.
+</p>
+
+<h3>
+  New adb commands and options
+</h3>
+
+<p>
+  The M Preview SDK Platform-tools provides several new commands to let you test
+  how your app handles permissions.
+</p>
+
+<h4>
+  Install with permissions
+</h4>
+
+<p>
+  You can use the <a href="{@docRoot}tools/help/adb.html#move"><code>adb
+  install</code></a> command's new <code>-g</code> option, which installs the
+  app and grants all permissions listed in its manifest:
 </p>
 
-<h2 id="">Best Practices</h2>
+<pre class="no-pretty-print">
+$ adb install -g &lt;path_to_apk&gt;
+</pre>
+
+<h4>
+  Grant and revoke permissions
+</h4>
+
+<p>
+  You can use new ADB <a href="{@docRoot}tools/help/adb.html#pm">package manager
+  (pm)</a> commands to grant and revoke permissions to an installed app.
+  This functionality can be useful for automated testing.
+</p>
+
+<p>
+  To grant a permission, use the package manager's <code>grant</code> command:
+</p>
+
+<pre class="no-pretty-print">
+$ adb pm grant &lt;package_name&gt; &lt;permission_name&gt;
+</pre>
+
+<p>
+  For example, to grant the com.example.myapp package permission to record
+  audio, use this command:
+</p>
+
+<pre class="no-pretty-print">
+$ adb pm grant com.example.myapp android.permission.RECORD_AUDIO
+</pre>
+
+<p>
+  To revoke a permission, use the package manager's <code>revoke</code> command:
+</p>
+
+<pre class="no-pretty-print">
+$ adb pm revoke &lt;package_name&gt; &lt;permission_name&gt;
+</pre>
+
+<h2 id="best-practices">Best Practices</h2>
 
 <p>
   The new permissions model gives users a smoother experience, and makes it
@@ -253,12 +713,32 @@ page.title=Android M Preview Runtime Permissions
   the new model.
 </p>
 
-<h3>
-  Don't Overwhelm the User
+
+<h3 id="bp-what-you-need">Only ask for permissions you need</h3>
+
+<p>
+  Every time you ask for a permission, you force the user to make a decision.
+  If the user turns down the request, that reduces your app's functionality.
+  You should minimize the number of times you make these requests.
+</p>
+
+<p>
+  For example, quite often your app can get needed functionality by using an
+  <a href="{@docRoot}guide/components/intents-filters.html">intent</a> instead
+  of asking for permissions. If your app needs to take pictures with the
+  phone's camera, your app can use a {@link
+  android.provider.MediaStore#ACTION_IMAGE_CAPTURE
+  MediaStore.ACTION_IMAGE_CAPTURE} intent. When your app executes the intent, the
+  system prompts the user to choose an already-installed camera app to take the
+  picture.
+</p>
+
+<h3 id="bp-dont-overwhelm">
+  Don't overwhelm the user
 </h3>
 
 <p>
-  If you confront the user with a lot of permissions requests at once, you may
+  If you confront the user with a lot of requests for permissions at once, you may
   overwhelm the user and cause them to quit your app. Instead, you should ask
   for permissions as you need them.
 </p>
@@ -266,35 +746,30 @@ page.title=Android M Preview Runtime Permissions
 <p>
   In some cases, one or more permissions might be absolutely essential to your
   app. In that case, it might make sense to ask for all the permissions as soon
-  as the app launches.
-  <!-- TODO: insert screenshot of dialog box asking for several permissions -->
-  For example, if you make a photography app, the app would
-  need access to the device camera. When the user launches the app for the
-  first time, they won't be surprised to be asked to give permission to use the
-  camera. But if the same app also had a feature to share photos with the
+  as the app launches. For example, if you make a photography app, the app
+  would need access to the device camera. When the user launches the app for
+  the first time, they won't be surprised to be asked for permission to use
+  the camera. But if the same app also had a feature to share photos with the
   user's contacts, you probably should <em>not</em> ask for that permission at
   first launch. Instead, wait until the user tries to use the "sharing" feature
   and ask for the permission then.
 </p>
 
 <p>
-  If your app provides a tutorial, it may make sense to request app's essential
+  If your app provides a tutorial, it may make sense to request the app's essential
   permissions at the end of the tutorial sequence.
 </p>
 
-<h3>
-  Explain Why You Need Permissions
+<h3 id="bp-explain">
+  Explain why you need permissions
 </h3>
 
 <p>
-  The permissions screen shown by the system when you call <a href=
-  "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-  <code>requestPermissions()</code></a> says what permission your app wants,
-  but doesn't say why you want it. In some cases, the user may find that
-  puzzling. It's a good idea to explain to the user why your app wants the
-  permissions before you call <a href=
-  "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-  <code>requestPermissions()</code></a>.
+  The permissions dialog shown by the system when you call
+  <code>requestPermissions()</code> says what permission your app wants, but
+  doesn't say why. In some cases, the user may find that puzzling.
+  It's a good idea to explain to the user why your app wants the permissions
+  before calling <code>requestPermissions()</code>.
 </p>
 
 <p>
@@ -303,50 +778,17 @@ page.title=Android M Preview Runtime Permissions
   contain location information, and would be puzzled why their photography app
   wanted to know the location. So in this case, it's a good idea for the app to
   tell the user about this feature <em>before</em> calling
-  <a href=
-  "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-  <code>requestPermissions()</code></a>.
+  <code>requestPermissions()</code>.
 </p>
 
 <p>
-  As noted, one way to do this is to incorporate these requests into an app
-  tutorial. The tutorial can show each of the app's features in turn, and as it
-  does this, it can explain what permissions are needed. For example, the
-  photography app's tutorial demonstrate its "share photos with your contacts"
-  feature, then tell the user that they'll need to give permission for the app
-  to see the user's contacts, and <em>then</em> call <a href=
-  "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
-  <code>requestPermissions()</code></a>
-  to get that access. Of course, some users will want to skip the tutorial, so
-  you'll still need to check for and request permissions during the app's
-  normal operation.
-</p>
-
-<h3>
-  Opt Out If Necessary
-</h3>
-
-<p>
-  Until you are ready to use the new permissions model, you can opt out simply
-  by setting your app's <a href=
-  "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target">
-  targetSdkVersion</a> to 22 or less. If you do this, the system will use the
-  old permissions model. When the user downloads the app, they will be prompted
-  to grant all the permissions listed in the manifest.
-</p>
-
-<p>
-  With the M Developer Preview, users can turn off permissions for <em>any</em>
-  app from the app's Settings page, regardless of what SDK version the app
-  targets. For this reason, it's a good idea to follow the steps described in
-  <a href="#prompting">"Prompting for Permissions on the M Preview"</a> even if
-  your app doesn't fully support the new permissions model.
-</p>
-
-<p class="note">
-  <strong>Note:</strong> If a user turns off permissions for a legacy app, the system
-  silently disables the appropriate functionality. When the app attempts to
-  perform an operation that requires that permission, the operation will not
-  necessarily cause an exception. Instead, it might return an empty data set or
-  otherwise signal an error.
+  One way to do this is to incorporate these requests into an app tutorial. The
+  tutorial can show each of the app's features in turn, and as it does this, it
+  can explain what permissions are needed. For example, the photography app's
+  tutorial can demonstrate its "share photos with your contacts" feature, then
+  tell the user that they need to give permission for the app to see the user's
+  contacts. The app can then call <code>requestPermissions()</code> to ask the
+  user for that access. Of course, not every user is going to follow the
+  tutorial, so you still need to check for and request permissions during the
+  app's normal operation.
 </p>
diff --git a/docs/image_sources/preview/features/app-permissions-screen-orig.png b/docs/image_sources/preview/features/app-permissions-screen-orig.png
new file mode 100644 (file)
index 0000000..1868c7a
Binary files /dev/null and b/docs/image_sources/preview/features/app-permissions-screen-orig.png differ