Merge "docs: M Preview - App Linking" into mnc-preview-docs
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 94e6469..5d59130 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -326,6 +326,15 @@
- from: /shareables/training/BitmapFun.zip
to: /downloads/samples/DisplayingBitmaps.zip
+- from: /shareables/auto/AndroidAuto-audio-apps.pdf
+ to: http://google.com/design/spec-auto/audio-apps/design-principles.html
+
+- from: /shareables/auto/AndroidAuto-messaging-apps.pdf
+ to: http://google.com/design/spec-auto/messaging-apps/voice-based-messaging.html
+
+- from: /shareables/auto/AndroidAuto-custom-colors.pdf
+ to: http://google.com/design/spec-auto/colors-branding/color-themes.html
+
- from: /shareables/...
to: http://commondatastorage.googleapis.com/androiddevelopers/shareables/...
@@ -399,5 +408,5 @@
to: /training/building-wearables.html
# ---------- DISTRIBUTE ------------------
-- from /distribute/tools/promote/badge-files.html
+- from: /distribute/tools/promote/badge-files.html
to: /distribute/tools/promote/badges.html
diff --git a/docs/html/design/auto/index.jd b/docs/html/design/auto/index.jd
index 06f8592..49bd221 100644
--- a/docs/html/design/auto/index.jd
+++ b/docs/html/design/auto/index.jd
@@ -14,13 +14,13 @@
<h2><strong>UI Guidelines</strong></h2>
<ul>
<li><a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">
- <strong>Auto Audio Apps (PDF)</strong></a>
+ <strong>Auto Audio Apps</strong></a>
</li>
<li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
- <strong>Auto Messaging Apps (PDF)</strong></a>
+ <strong>Auto Messaging Apps</strong></a>
</li>
<li><a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">
- <strong>Auto Color Customization (PDF)</strong></a>
+ <strong>Auto Color Customization</strong></a>
</li>
</ul>
</div>
diff --git a/docs/html/distribute/essentials/quality/auto.jd b/docs/html/distribute/essentials/quality/auto.jd
index db0f20a..ae9aac5 100644
--- a/docs/html/distribute/essentials/quality/auto.jd
+++ b/docs/html/distribute/essentials/quality/auto.jd
@@ -37,18 +37,33 @@
</p>
<p>
- Great auto experiences are predictive and predictable. Apps that support Android Auto
+ Great auto experiences are predictive and predictable. Apps that support Android Auto
should show timely information to the driver only when it is relevant, and use
simple, predictable patterns for common tasks.
</p>
+<p>
+ It's important that you test your auto app for the criteria listed on this page prior to
+ submitting to Google Play for review. There are two ways to test your app:
+</p>
+
+<ol>
+ <li> Use the Android Auto simulator to validate each checklist item. The simulator allows you to
+ sideload your app for testing. For more information on the simulator, see
+ <a href="{@docRoot}training/auto/start/index.html#test-it">Run and Test Auto Apps</a>.</li>
+ <li>Test your app in a vehicle by uploading your app to the alpha/beta channel on Google Play.
+ Apps will not work on Auto in vehicles unless they are installed from the Play Store.
+ For more information, see <a
+ href="{@docRoot}distribute/googleplay/developer-console.html#alpha-beta">Alpha and Beta Testing</a>.
+ </li>
+</ol>
+
<p class="caution">
<strong>Important:</strong> The criteria listed in this page apply to your app's user interface
and behavior when running on devices connected to an Android Auto screen. Apps must meet these
criteria to qualify as an Android Auto app on Google Play.
</p>
-
<div class="headerLine">
<h2 id="core">
Core App Quality
@@ -103,8 +118,8 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- App does not display on the Auto screen animated elements such as animated graphics, games, video, or
- progress bars.
+ App does not display on the Auto screen animated elements such as animated graphics,
+ video, or progress bars.
</p>
</td>
</tr>
@@ -141,7 +156,9 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- App does not include any features that distract the driver.
+ App does not include games or other features outside of the intended app types supported
+ by Auto.
+ (<a href="{@docRoot}training/auto/start/index.html">Learn How</a>)
</p>
</td>
</tr>
@@ -152,8 +169,9 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- App never presents any form of visual information (notifications, toasts, video, images,
- advertising, etc.) on the phone screen while the app is active in Android Auto.
+ App never activates the phone screen to present any form of visual information (notifications,
+ toasts, video, images, advertising, etc.) on the phone screen while the app is active in Android
+ Auto.
</p>
</td>
</tr>
@@ -161,7 +179,7 @@
<tr>
- <td rowspan="3" id="layout">
+ <td rowspan="1" id="layout">
Layout
</td>
@@ -175,29 +193,6 @@
</td>
</tr>
-
-<tr>
- <td id="AU-FT">
- AU-FT
- </td>
- <td>
- <p style="margin-bottom:.5em;">
- App displays all strings using the default Roboto fonts in two approved sizes.
- </p>
- </td>
-</tr>
-
-<tr>
- <td id="AU-ST">
- AU-ST
- </td>
- <td>
- <p style="margin-bottom:.5em;">
- App does not display any individual string longer than 120 characters.
- </p>
- </td>
-</tr>
-
<tr>
<td rowspan="4" id="contrast">
Visual Contrast
@@ -209,7 +204,7 @@
<td>
<p style="margin-bottom:.5em;">
App supports day mode, which renders dark text and controls on a light background.
- (<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Learn How</a>)
+ (<a href="//google.com/design/spec-auto/colors-branding/day-night-colors.html">Learn How</a>)
</p>
</td>
</tr>
@@ -221,7 +216,7 @@
<td>
<p style="margin-bottom:.5em;">
App supports night mode, which renders light text and controls on a dark background.
- (<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Learn How</a>)
+ (<a href="//google.com/design/spec-auto/colors-branding/day-night-colors.html">Learn How</a>)
</p>
</td>
</tr>
@@ -234,7 +229,7 @@
<p style="margin-bottom:.5em;">
App provides white icon sets that the system colorizes to provide automatic
contrast compensation.
- (<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Learn How</a>)
+ (<a href="//google.com/design/spec-auto/colors-branding/color-themes.html">Learn How</a>)
</p>
</td>
</tr>
@@ -246,7 +241,7 @@
<td>
<p style="margin-bottom:.5em;">
App provides colors that the system can optimize for easy in-vehicle readability.
- (<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Learn How</a>)
+ (<a href="//google.com/design/spec-auto/colors-branding/color-themes.html">Learn How</a>)
</p>
</td>
</tr>
@@ -261,7 +256,8 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- App must support voice commands.
+ App must support voice commands in audio apps.
+ (<a href="{@docRoot}training/auto/audio/index.html#support_voice">Learn How</a>)
</p>
</td>
</tr>
@@ -317,7 +313,7 @@
</tr>
<tr>
- <td rowspan="5" id="general">
+ <td rowspan="6" id="general">
General
</td>
@@ -326,7 +322,18 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- App loads in no more than 10 seconds.
+ App launches in no more than 10 seconds.
+ </p>
+ </td>
+</tr>
+
+<tr>
+ <td id="AU-LC">
+ AU-LC
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ App loads content in no more than 10 seconds.
</p>
</td>
</tr>
@@ -361,6 +368,7 @@
<td>
<p style="margin-bottom:.5em;">
No tasks in the app take more than six steps to complete.
+ (<a href="//google.com/design/spec-auto/system-overview/drawer.html#drawer-drawer-content-patterns">Learn How</a>)
</p>
</td>
</tr>
@@ -371,44 +379,30 @@
</td>
<td>
<p style="margin-bottom:.5em;">
- Any app button which is non-functional or disabled must be grayed out.
+ Interactive elements that are intentionally grayed-out must be non-functional.
</p>
</td>
</tr>
<tr>
- <td rowspan="2" id="media">
+ <td rowspan="1" id="media">
Media
</td>
- <td id="AU-PA">
- AU-PA
+ <td id="AU-MT">
+ AU-MT
</td>
<td>
<p style="margin-bottom:.5em;">
- App has no more than four primary actions plus one optional action overflow toggle (or five if
- no action overflow is used).
- (<a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">Learn How</a>)
+ Media apps do not autoplay or take over media focus when launched.
+ (<a href="{@docRoot}training/auto/audio/index.html#playback-commands">Learn How</a>)
</p>
</td>
</tr>
<tr>
- <td id="AU-SA">
- AU-SA
- </td>
- <td>
- <p style="margin-bottom:.5em;">
- App has no more than four optional secondary actions plus one action overflow toggle.
- (<a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">Learn How</a>)
- </p>
- </td>
-</tr>
-
-
-<tr>
<td rowspan="2" id="notifications">
Notifications
</td>
@@ -439,6 +433,70 @@
</td>
</tr>
+<tr>
+ <td rowspan="5" id="messages">
+ Messaging
+ </td>
+
+ <td id="AU-MI">
+ AU-MI
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ App is able to successfully receive incoming messages.
+ (<a href="{@docRoot}training/auto/messaging/index.html">Learn How</a>)
+ </p>
+ </td>
+</tr>
+
+<tr>
+ <td id="AU-MG">
+ AU-MG
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ Messages are properly grouped and displayed in the correct order.
+ (<a href="{@docRoot}training/auto/messaging/index.html#build_conversation">Learn How</a>)
+ </p>
+ </td>
+</tr>
+
+<tr>
+ <td id="AU-MR">
+ AU-MR
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ User is able to successfully reply to a message.
+ (<a href="{@docRoot}training/auto/messaging/index.html">Learn How</a>)
+ </p>
+ </td>
+</tr>
+
+<tr>
+ <td id="AU-MS">
+ AU-MS
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ Apps use short-form messaging app design patterns. Traditional long-form messaging apps, such
+ as apps for email, are not permitted.
+ </p>
+ </td>
+</tr>
+
+<tr>
+ <td id="AU-MP">
+ AU-MP
+ </td>
+ <td>
+ <p style="margin-bottom:.5em;">
+ Apps are peer-to-peer messaging services and not notification service apps such as weather,
+ stocks, and sport scores apps.
+ </p>
+ </td>
+</tr>
+
</table>
<!--
@@ -457,14 +515,18 @@
</div>
<p style="margin-top:30px;">
- <strong>After I submit my app, how will find out if my app does not meet all
+ <strong>After submitting my app, how will I find out if my app does not meet all
the requirements for Android Auto?</strong>
</p>
-<p>If you are planning to develop apps for Auto, you are encouraged to begin enabling and testing
- your apps now. However, Auto-enabled apps cannot be published at this time. Join the
- <a href="http://g.co/AndroidAutoDev" class="external-link">Auto
- Developers Google+ community</a> for updates on when you will be able to submit
- your Auto-enabled apps.</p>
+<p>
+ If your app does not meet the usability requirements described on this page, the Play Store team
+ will contact you through the email address specified in the <a href=
+ "https://play.google.com/apps/publish/">Google Play Developer Console</a> account associated with
+ the app.
+</p>
+<p class="note">
+ <strong>Note:</strong> For information about how to publish your Auto app in Google Play, see <a
+ href="{@docRoot}distribute/googleplay/auto.html">Distributing to Android Auto</a>.
</p>
@@ -474,11 +536,11 @@
tablets?</strong>
</p>
<p>
- No. When Google begins the approval process, your auto app will undergo a driver safety
+ No. When Google begins the approval process, your Auto app will undergo a driver safety
review, and will not be
available for distribution until the app is approved. Because this is the same APK as
for phones and tablets, your Play Store updates for those devices will not be available until the
- Auto approval process is complete.
+ Auto app approval process is complete.
</p>
<p class="caution">
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 5ab4b89..d1639aa 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -14,8 +14,7 @@
<span class="less" style="display:none">show less</span></a></h2>
<ol id="toc44" class="hide-nested">
- <li><a href="#backup">Auto Backup for Apps</a></li>
- <li><a href="#notifications">Notifications</a></li>
+ <li><a href="#backup">Automatic App Data Backup</a></li>
<li><a href="#authentication">Authentication</a>
<ul>
<li><a href="#fingerprint-authentication">Fingerprint Authentication</a></li>
@@ -24,14 +23,27 @@
</li>
<li><a href="#direct-share">Direct Share</a></li>
<li><a href="#voice-interactions">Voice Interactions</a></li>
+ <li><a href="#assist">Assist API</a></li>
+ <li><a href="#notifications">Notifications</a></li>
<li><a href="#bluetooth-stylus">Bluetooth Stylus Support</a></li>
- <li><a href="#audio">New Audio Features</a></li>
- <li><a href="#afw">New Android for Work Features</a></li>
+ <li><a href="#ble-scanning">Improved Bluetooth Low Energy Scanning</a></li>
+ <li><a href="#hotspot">Hotspot 2.0 Release 1 Support</a></li>
+ <li><a href="#4K-display">4K Display Mode</a></li>
+ <li><a href="#behavior-themeable-colorstatelists">Themeable ColorStateLists</a></li>
+ <li><a href="#audio">Audio Features</a></li>
+ <li><a href="#video">Video Features</a></li>
+ <li><a href="#camera">Camera Features</a>
+ <ul>
+ <li><a href="#flashlight">Flashlight API</a></li>
+ <li><a href="#reprocessing">Camera Reprocessing</a></li>
+ </ul>
+ </li>
+ <li><a href="#afw">Android for Work Features</a></li>
</ol>
<h2>API Differences</h2>
<ol>
-<li><a href="">API level 22 to M »</a> </li>
+<li><a href="{@docRoot}preview/download.html">API level 22 to M Preview »</a> </li>
</ol>
</div>
@@ -55,40 +67,24 @@
href="{@docRoot}">developer.android.com</a>. These API elements are
formatted in {@code code style} in this document (without hyperlinks). For the
preliminary API documentation for these elements, download the <a
-href="http://storage.googleapis.com/androiddevelopers/preview/m-developer-preview-reference.zip">
-preview reference</a>.</p>
+href="{@docRoot}preview/download.html#docs"> preview reference</a>.</p>
<h3>Important behavior changes</h3>
<p>If you have previously published an app for Android, be aware that your app might be affected
-by changes in M.</p>
+by changes in the platform.</p>
-<p>Please see <a href="api-changes.html">Behavior Changes</a> for complete information.</p>
+<p>Please see <a href="behavior-changes.html">Behavior Changes</a> for complete information.</p>
-<h2 id="backup">Auto Backup for Apps</h2>
+<h2 id="backup">Automatic App Data Backup</h2>
<p>The system now performs automatic full data backup and restore for apps. This behavior is
-enabled by default for apps targeting M; you do not need to add any additional code. If users
-delete their Google account, their backup data is deleted as well.</p>
-<p>To learn how this feature works and how to configure what to back up on the file system,
-see the <a href="">App Backup for Apps guide</a>.</p>
-
-<h2 id="notifications">Notifications</h2>
-<p>M adds the following API changes for notifications:</p>
-<ul>
- <li>New {@code NotificationListenerService.INTERRUPTION_FILTER_ALARMS} filter level that
- corresponds to the new <em>Alarms only</em> do not disturb mode.</li>
- <li>New {@code Notification.CATEGORY_REMINDER} category value that is used to distinguish
- user-scheduled reminders from other events
- ({@link android.app.Notification#CATEGORY_EVENT}) and alarms
- ({@link android.app.Notification#CATEGORY_ALARM}).</li>
- <li>New {@code android.graphics.drawable.Icon} class which can be attached to your notifications
- via the Notification.Builder.setIcon() and Notification.Builder.setLargeIcon() methods.</li>
- <li>New {@code NotificationManager.getActiveNotifications()} method that allows your apps to
- find out which of their notifications are currently alive.</li>
-</ul>
+enabled by default for apps targeting M Preview; you do not need to add any additional code. If
+users delete their Google accounts, their backup data is deleted as well. To learn how this feature
+works and how to configure what to back up on the file system, see
+<a href="{@docRoot}preview/backup/index.html">Automatic App Data Backup</a>.</p>
<h2 id="authentication">Authentication</h2>
-<p>The M release offers new APIs to let you authenticate users by using their fingerprint scans on
+<p>This preview offers new APIs to let you authenticate users by using their fingerprint scans on
supported devices, and check how recently the user was last authenticated using a device unlocking
mechanism (such as a lockscreen password). Use these APIs in conjunction with
the <a href="{@docRoot}training/articles/keystore.html">Android Keystore system</a>.</p>
@@ -97,17 +93,15 @@
<p>To authenticate users via fingerprint scan, get an instance of the new
{@code android.hardware.fingerprint.FingerprintManager} class and call the
-{@code FingerprintManager.authenticate()} method. Your app must be running on a device with a
-fingerprint sensor. You must implement the user interface for the fingerprint
-authentication flow on your app, and use the standard fingerprint Android icon in your UI.
-If you are developing multiple apps that use fingerprint authentication, note that each app must
-authenticate the user’s fingerprint independently.
+{@code FingerprintManager.authenticate()} method. Your app must be running on a compatible
+device with a fingerprint sensor. You must implement the user interface for the fingerprint
+authentication flow on your app, and use the standard Android fingerprint icon in your UI.
+The Android fingerprint icon ({@code c_fp_40px.png}) is included in the
+<a href="https://github.com/googlesamples/android-FingerprintDialog"
+class="external-link">sample app</a>. If you are developing multiple apps that use fingerprint
+authentication, note that each app must authenticate the user’s fingerprint independently.
</p>
-<img src="{@docRoot}preview/images/fingerprint-screen_2x.png"
-srcset="{@docRoot}preview/images/fingerprint-screen.png 1x, preview/images/fingerprint-screen_2x.png 2x"
-style="margin:0 0 10px 20px" width="282" height="476" />
-
<p>To use this feature in your app, first add the {@code USE_FINGERPRINT} permission in your
manifest.</p>
@@ -116,34 +110,34 @@
android:name="android.permission.USE_FINGERPRINT" />
</pre>
-<p>The following snippet shows how you might listen for fingerprint events in your
-{@code FingerprintManager.AuthenticationCallback} implementation.</p>
+<img src="{@docRoot}preview/images/fingerprint-screen.png"
+srcset="{@docRoot}preview/images/fingerprint-screen.png 1x, {@docRoot}preview/images/fingerprint-screen_2x.png 2x"
+style="float:right; margin:0 0 10px 20px" width="282" height="476" />
-<pre>
-// Call this to start listening for fingerprint events
-public void startListening(FingerprintManager.CryptoObject cryptoObject) {
- if (!isFingerprintAuthAvailable()) {
- return;
- }
- mCancellationSignal = new CancellationSignal();
- mSelfCancelled = false;
- mFingerprintManager.authenticate(cryptoObject,
- mCancellationSignal, this, 0 /* flags */);
- // Icon to display when prompting users to start a fingerprint scan
- mIcon.setImageResource(R.drawable.ic_fp_40px);
-}
+<p>To see an app implementation of fingerprint authentication, refer to the
+<a href="https://github.com/googlesamples/android-FingerprintDialog" class="external-link">
+ Fingerprint Dialog sample</a>.</p>
-// Helper method to check if the device supports fingerprint
-// scanning and if the user has enrolled at least one fingerprint.
-public boolean isFingerprintAuthAvailable() {
- return mFingerprintManager.isHardwareDetected()
- && mFingerprintManager.hasEnrolledFingerprints();
-}
+<p>If you are testing this feature, follow these steps:</p>
+<ol>
+<li>Enroll a new fingerprint in the emulator by going to
+<strong>Settings > Security > Fingerprint</strong>, then follow the enrollment instructions.</li>
+<li>Install Android SDK Tools Revision 24.3, if you have not done so.</li>
+<li>Use an emulator to emulate fingerprint touch events with the
+following command. Use the same command to emulate fingerprint touch events on the lockscreen or
+in your app.
+<pre class="no-prettyprint">
+adb -e emu finger touch <finger_id>
</pre>
+<p>On Windows, you may have to run {@code telnet 127.0.0.1 <emulator-id>} followed by
+ {@code finger touch <finger_id>}.
+</p>
+</li>
+</ol>
<h3 id="confirm-credentials">Confirm Credentials</h3>
<p>Your app can authenticate users based on how recently they last unlocked their device. You can
-use the same public or secret key to authenticate users into multiple apps. This feature frees
+use the same public or secret key to authenticate users. This feature frees
users from having to remember additional app-specific passwords, and avoids the need for you to
implement your own authentication user interface.</p>
@@ -152,46 +146,14 @@
{@code android.security.KeyPairGeneratorSpec.Builder} and
{@code android.security.KeyGeneratorSpec.Builder} classes for public key pairs and secret keys
respectively. If you are importing keys, use the {@link android.security.KeyStoreParameter.Builder}
-class to set your constraints.</p>
+class to set your constraints. You can use the
+{@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence) createConfirmDeviceCredentialIntent()}
+method to re-authenticate the user within your app if the timeout expired.
+</p>
-<p>The following example shows how you might create a symmetric key in the Keystore which can only be
-used if the user has successfully unlocked the device within the last 5 minutes.</p>
-
-<pre>
-private void createKey() {
- // Generate a key to decrypt payment credentials, tokens, etc.
- // This will most likely be a registration step for the user when
- // they are setting up your app.
- try {
- KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
- ks.load(null);
- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES",
- "AndroidKeyStore");
- keyGenerator.init(new KeyGeneratorSpec.Builder(this)
- // Alias of the entry in Android KeyStore where the key will appear
- .setAlias(KEY_NAME)
- // Key use constraints
- .setPurposes(KeyStoreKeyProperties.Purpose.ENCRYPT
- | KeyStoreKeyProperties.Purpose.DECRYPT)
- .setBlockModes("CBC")
- .setUserAuthenticationRequired(true)
- // Require that the user has unlocked in the last 5 minutes
- .setUserAuthenticationValidityDurationSeconds(5 * 60)
- .setEncryptionPaddings("PKCS7Padding")
- .build());
- keyGenerator.generateKey();
- } catch (NoSuchAlgorithmException | NoSuchProviderException
- | InvalidAlgorithmParameterException | KeyStoreException
- | CertificateException | IOException e) {
- throw new RuntimeException(e);
- }
-}
-</pre>
-
-<p>To determine the last time users logged into their account, call the
-{@code android.accounts.AccountManager.confirmCredentials()} method. If the call is successful, the
-method returns an bundle that includes a {@code KEY_LAST_AUTHENTICATED_TIME} value which indicates
-the last time, in milliseconds, that the credential for that account was validated or created.</p>
+<p>To see an app implementation of this feature, refer to the
+<a href="https://github.com/googlesamples/android-ConfirmDeviceCredentials" class="external-link">
+ Confirm Device Credentials sample</a>.</p>
<h2 id="direct-share">Direct Share</h2>
@@ -199,7 +161,7 @@
srcset="{@docRoot}preview/images/direct-share-screen.png 1x, preview/images/direct-share-screen_2x.png 2x"
style="float:right; margin:0 0 20px 30px" width="312" height="385" />
-<p>This release provides you with APIs to makes sharing intuitive and quick for users. You can now
+<p>This preview provides you with APIs to makes sharing intuitive and quick for users. You can now
define <em>deep links</em> that target a specific activity in your app. These deep links are
exposed to users via the <em>Share</em> menu. This feature allows users to share content to
targets, such as contacts, within other apps. For example, the deep link might launch an
@@ -214,9 +176,6 @@
{@code SERVICE_INTERFACE} action.</p>
<p>The following example shows how you might declare the {@code ChooserTargetService} in your
manifest.</p>
-<br>
-<br>
-<br>
<pre>
<service android:name=".ChooserTargetService"
android:label="@string/service_name"
@@ -243,37 +202,142 @@
android:value=".ChooserTargetService" />
</activity>
</pre>
+<p>To see an app implementation of this feature, refer to the
+<a href="https://github.com/googlesamples/android-DeepLinkSharing" class="external-link">
+ Deep Link Sharing sample</a>.</p>
+
<h2 id="voice-interactions">Voice Interactions</h2>
<p>
-This release provides a new voice interaction API which, together with
+This preview provides a new voice interaction API which, together with
<a href="https://developers.google.com/voice-actions/" class="external-link">Voice Actions</a>,
allows you to build conversational voice experiences into your apps. Call the
{@code android.app.Activity.isVoiceInteraction()} method to determine if your activity was
started in response to a voice action. If so, your app can use the
{@code android.app.VoiceInteractor} class to request a voice confirmation from the user, select
-from a list of options, and more.</p>
-<p>To learn more about implementing voice actions, see the voice interaction API
+from a list of options, and more. To learn more about implementing voice actions, see the
<a href="https://developers.google.com/voice-actions/interaction/"
-class="external-link">guide</a>.
+class="external-link">Voice Actions developer site</a>.
</p>
+<h2 id="assist">Assist API</h2>
+<p>
+This preview offers a new way for users to engage with your apps through an assistant. To use this
+feature, the user must enable the assistant to use the current context. Once enabled, the user
+can summon the assistant within any app, by long-pressing on the <strong>Home</strong> button.</p>
+<p>The platform passes the current context to the assistant. In addition to the standard set of
+information that the platform passes to the assistant, your app can share additional information
+by using the new {@code android.app.Activity.AssistContent} class.</p>
+
+<p>To provide the assistant with additional context from your app, follow these steps:</p>
+
+<ol>
+<li>Implement the {@link android.app.Application.OnProvideAssistDataListener} interface.</li>
+<li>Register this listener by using
+{@link android.app.Application#registerOnProvideAssistDataListener(android.app.Application.OnProvideAssistDataListener) registerOnProvideAssistDataListener()}.</li>
+<li>In order to provide activity-specific contextual information, override the
+{@link android.app.Activity#onProvideAssistData(android.os.Bundle) onProvideAssistData()}
+callback and, optionally, the new {@code Activity.onProvideAssistContent()} callback.
+</ol>
+
+<h2 id="notifications">Notifications</h2>
+<p>This preview adds the following API changes for notifications:</p>
+<ul>
+ <li>New {@code NotificationListenerService.INTERRUPTION_FILTER_ALARMS} filter level that
+ corresponds to the new <em>Alarms only</em> do not disturb mode.</li>
+ <li>New {@code Notification.CATEGORY_REMINDER} category value that is used to distinguish
+ user-scheduled reminders from other events
+ ({@link android.app.Notification#CATEGORY_EVENT}) and alarms
+ ({@link android.app.Notification#CATEGORY_ALARM}).</li>
+ <li>New {@code android.graphics.drawable.Icon} class which can be attached to your notifications
+ via the {@code Notification.Builder.setSmallIcon(Icon)} and
+ {@code Notification.Builder.setLargeIcon(Icon)} methods.</li>
+ <li>New {@code NotificationManager.getActiveNotifications()} method that allows your apps to
+ find out which of their notifications are currently alive. To see an app implementation that
+ uses this feature, see the <a href="https://github.com/googlesamples/android-ActiveNotifications"
+ class="external-link">Active Notifications sample</a>.</li>
+</ul>
+
<h2 id="bluetooth-stylus">Bluetooth Stylus Support</h2>
-<p>The M release provides improved support for user input using a Bluetooth stylus. If the user
-touches a stylus with a button on the screen of your app, the
-{@link android.view.MotionEvent#getToolType(int) getTooltype()} method now returns
-{@code TOOL_TYPE_STYLUS}. The {@link android.view.MotionEvent#getButtonState() getButtonState()}
-method returns {@link android.view.MotionEvent#BUTTON_SECONDARY} when the user
+<p>This preview provides improved support for user input using a Bluetooth stylus. Users can pair
+and connect a compatible Bluetooth stylus with their phone or tablet. While connected, position
+information from the touch screen is fused with pressure and button information from the stylus to
+provide a greater range of expression than with the touch screen alone. Your app can listen for
+stylus button presses and perform secondary actions, by registering the new
+{@code View.onStylusButtonPressListener} and {@code GestureDetector.OnStylusButtonPressListener}
+callbacks in your activity.</p>
+
+<p>Use the {@link android.view.MotionEvent} methods and constants to detect stylus button
+interactions:</p>
+<ul>
+<li>If the user touches a stylus with a button on the screen of your app, the
+{@link android.view.MotionEvent#getToolType(int) getTooltype()} method returns
+{@link android.view.MotionEvent#TOOL_TYPE_STYLUS}.</li>
+<li>For apps targeting M Preview, the
+{@link android.view.MotionEvent#getButtonState() getButtonState()}
+method returns {@code MotionEvent.STYLUS_BUTTON_PRIMARY} when the user
presses the primary stylus button. If the stylus has a second button, the same method returns
-{@link android.view.MotionEvent#BUTTON_TERTIARY} when the user presses it. If the user presses
-both buttons simultaneously, the method returns both these values. In addition, the system reports
-the user button-press action to the new {@code View.onStylusButtonPressListener} and
-{@code GestureDetector.OnStylusButtonPressListener} callbacks in your activity, if you have
-registered these listeners in your app.</p>
+{@code MotionEvent.STYLUS_BUTTON_SECONDARY} when the user presses it. If the user presses
+both buttons simultaneously, the method returns both values OR'ed together
+({@code STYLUS_BUTTON_PRIMARY|STYLUS_BUTTON_SECONDARY}).</li>
+<li>
+For apps targeting a lower platform version, the
+{@link android.view.MotionEvent#getButtonState() getButtonState()} method returns
+{@link android.view.MotionEvent#BUTTON_SECONDARY} (for primary stylus button press),
+{@link android.view.MotionEvent#BUTTON_TERTIARY} (for secondary stylus button press), or both.
+</li>
+</ul>
-<h2 id="audio">New Audio Features</h2>
+<h2 id="ble-scanning">Improved Bluetooth Low Energy Scanning</h2>
+<p>
+If your app performs performs Bluetooth Low Energy scans, you can use the new
+{@code android.bluetooth.le.ScanSettings.Builder.setCallbackType()} method to specify that
+you want callbacks to only be notified when an advertisement packet matching the set
+{@link android.bluetooth.le.ScanFilter} is first found, and when it is not seen for a period of
+time. This approach to scanning is more power-efficient than what’s provided in the previous
+platform version.
+</p>
-<p>This release adds enhancements to audio processing on Android, including: </p>
+<h2 id="hotspot">Hotspot 2.0 Release 1 Support</h2>
+<p>
+This preview adds support for the Hotspot 2.0 Release 1 spec on Nexus 6 and Nexus 9 devices. To
+provision Hotspot 2.0 credentials in your app, use the new methods of the
+{@link android.net.wifi.WifiEnterpriseConfig} class, such as {@code setPlmn()} and
+{@code setRealm()}. In the {@link android.net.wifi.WifiConfiguration} object, you can set the
+{@link android.net.wifi.WifiConfiguration#FQDN} and the {@code providerFriendlyName} fields.
+The new {@code ScanResult.PasspointNetwork} property indicates if a detected
+network represents a Hotspot 2.0 access point.
+</p>
+
+<h2 id="4K-display">4K Display Mode</h2>
+<p>The platform now allows apps to request that the display resolution be upgraded to 4K rendering
+on compatible hardware. To query the current physical resolution, use the new
+{@code android.view.Display.Mode} APIs. If the UI is drawn at a lower logical resolution and is
+upscaled to a larger physical resolution, be aware that the physical resolution the
+{@code Display.Mode.getPhysicalWidth()} method returns may differ from the logical
+resolution reported by {@link android.view.Display#getSize(android.graphics.Point) getSize()}.</p>
+
+<p>You can request the system to change the physical resolution in your app as it runs, by setting
+the {@code WindowManager.LayoutParams.preferredDisplayModeId} property of your app’s window. This
+feature is useful if you want to switch to 4K display resolution. While in 4K display mode, the
+UI continues to be rendered at the original resolution (such as 1080p) and is upscaled to 4K, but
+{@link android.view.SurfaceView} objects may show content at the native resolution.</p>
+
+<p>To test the new 4K display mode, simulate a secondary display of a larger resolution using the
+<strong>Developer Options</strong> settings.</p>
+
+<h2 id="behavior-themeable-colorstatelists">Themeable ColorStateLists</h2>
+<p>Theme attributes are now supported in
+{@link android.content.res.ColorStateList} for devices running the M Preview. The
+{@link android.content.res.Resources#getColorStateList(int) getColorStateList()} and
+{@link android.content.res.Resources#getColor(int) getColor()} methods have been deprecated. If
+you are calling these APIs, call the new {@code Context.getColorStateList()} or
+{@code Context.getColor()} methods instead. These methods are also available in the
+v4 appcompat library via {@link android.support.v4.content.ContextCompat}.</p>
+
+<h2 id="audio">Audio Features</h2>
+
+<p>This preview adds enhancements to audio processing on Android, including: </p>
<ul>
<li>Support for the <a href="http://en.wikipedia.org/wiki/MIDI" class="external-link">MIDI</a>
protocol, with the new {@code android.media.midi} APIs. Use these APIs to send and receive MIDI
@@ -293,8 +357,78 @@
when an audio device is connected or disconnected.</li>
</ul>
-<h2 id="afw">New Android for Work Features</h2>
-<p>This release includes the following new APIs for Android for Work:</p>
+<h2 id="video">Video Features</h2>
+<p>This preview adds new capabilities to the video processing APIs, including:</p>
+<ul>
+<li>New {@code android.media.MediaSync} class which helps applications to synchronously render
+audio and video streams. The audio buffers are submitted in non-blocking fashion and are
+returned via a callback. It also supports dynamic playback rate.
+</li>
+<li>New {@code MediaDrm.EVENT_SESSION_RECLAIMED} event, which indicates that a session opened by
+the app has been reclaimed by the resource manager. If your app uses DRM sessions, you should
+handle this event and make sure not to use a reclaimed session.
+</li>
+<li>New {@code MediaCodec.CodecException.ERROR_RECLAIMED} error code, which indicates that the
+resource manager reclaimed the media resource used by the codec. With this exception, the codec
+must be released, as it has moved to terminal state.
+</li>
+<li>New {@code MediaCodecInfo.CodecCapabilities.getMaxSupportedInstances()} interface to get a
+hint for the max number of the supported concurrent codec instances.
+</li>
+<li>New {@code MediaPlayer.setPlaybackParams()} method to set the media playback rate for fast or
+slow motion playback. It also stretches or speeds up the audio playback automatically in
+conjunction with the video.</li>
+</ul>
+
+<h2 id="camera">Camera Features</h2>
+<p>This preview includes the following new APIs for accessing the camera’s flashlight and for
+camera reprocessing of images:</p>
+
+<h3 id="flashlight">Flashlight API</h3>
+<p>If a camera device has a flash unit, you can call the {@code CameraManager.setTorchMode()}
+method to switch the flash unit’s torch mode on or off without opening the camera device. The app
+does not have exclusive ownership of the flash unit or the camera device. The torch mode is turned
+off and becomes unavailable whenever the camera device becomes unavailable, or when other camera
+resources keeping the torch on become unavailable. Other apps can also call {@code setTorchMode()}
+to turn off the torch mode. When the last app that turned on the torch mode is closed, the torch
+mode is turned off.</p>
+
+<p>You can register a callback to be notified about torch mode status by calling the
+{@code CameraManager.registerTorchCallback()} method. The first time the callback is registered,
+it is immediately called with the torch mode status of all currently known camera devices with a
+flash unit. If the torch mode is turned on or off successfully, the
+{@code CameraManager.TorchCallback.onTorchModeChanged()} method is invoked.</p>
+
+<h3 id="reprocessing">Reprocessing API</h3>
+<p>The {@link android.hardware.camera2 Camera2} API is extended to support YUV and private
+opaque format image reprocessing. Your app determine if the reprocessing capabilities are available
+via {@code CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES}. If a device supports reprocessing,
+you can create a reprocessable camera capture session by calling
+{@code CameraDevice.createReprocessableCaptureSession()}, and create requests for input
+buffer reprocessing.</p>
+
+<p>Use the {@code ImageWriter} class to connect the input buffer flow to the camera reprocessing
+input. To get an empty buffer, follow this programming model:</p>
+
+<ol>
+<li>Call the {@code ImageWriter.dequeueInputImage()} method.</li>
+<li>Fill the data into the input buffer.</li>
+<li>Send the buffer to the camera by calling the {@code ImageWriter.queueInputImage()} method.</li>
+</ol>
+
+<p>If you are using a {@code ImageWriter} object together with an
+{@code android.graphics.ImageFormat.PRIVATE} image, your app cannot access the image
+data directly. Instead, pass the {@code ImageFormat.PRIVATE} image directly to the
+{@code ImageWriter} by calling the {@code ImageWriter.queueInputImage()} method without any
+buffer copy.</p>
+
+<p>The {@code ImageReader} class now supports {@code android.graphics.ImageFormat.PRIVATE} format
+image streams. This support allows your app to maintain a circular image queue of
+{@code ImageReader} output images, select one or more images, and send them to the
+{@code ImageWriter} for camera reprocessing.</p>
+
+<h2 id="afw">Android for Work Features</h2>
+<p>This preview includes the following new APIs for Android for Work:</p>
<ul>
<li><strong>Enhanced controls for Corporate-Owned, Single-Use devices:</strong> The Device Owner
can now control the following settings to improve management of
@@ -325,13 +459,13 @@
<li><strong>Auto-acceptance of system updates.</strong> By setting a system update policy with
{@code DevicePolicyManager.setSystemUpdatePolicy()}, a Device Owner can now auto-accept a system
update, for instance in the case of a kiosk device, or postpone the update and prevent it being
-taken by the user for up to 30 days. Furthermore, an administrator can set a time window in which an
-update must be taken, for example during the hours when a kiosk device is not in use. When a
-system update is available, the system checks if the Work Policy Controller app has set a system
+taken by the user for up to 30 days. Furthermore, an administrator can set a daily time window in
+which an update must be taken, for example during the hours when a kiosk device is not in use. When
+a system update is available, the system checks if the Work Policy Controller app has set a system
update policy, and behaves accordingly.
</li>
<li>
-<strong>Delegated certificate installation.</strong> A Profile or Device Owner can now grant a
+<strong>Delegated certificate installation:</strong> A Profile or Device Owner can now grant a
third-party app the ability to call these {@link android.app.admin.DevicePolicyManager} certificate
management APIs:
<ul>
@@ -349,21 +483,49 @@
installKeyPair()}</li>
</ul>
</li>
-<li><strong>Enterprise factory reset protection.</strong> When provisioning a Device Owner, you can
-now configure parameters for bypassing Factory Reset Protection (FRP), by setting the
+<li><strong>Enterprise factory reset protection:</strong> When provisioning a Device Owner, you can
+now configure parameters to unlock Factory Reset Protection (FRP) by setting the
{@code DeviceManagerPolicy.EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS} bundle. An NFC Programmer
-app can provide these parameters after a device has been reset to bypass FRP and provision the device,
+app can provide these parameters after a device has been reset to unlock FRP and provision the device,
without requiring the previously configured Google account. If you don't modify these parameters,
FRP remains in-place and prevents the device from being activated without the previously activated
-Google credentials.</li>
-<li><strong>Data usage tracking.</strong> A Profile or Device Owner can now query for the data
-usage statistics visible in <em>Settings > Data</em> usage by using the new
+Google credentials.
+<p>Additionally, by setting app restrictions on Google Play services, Device Owners can specify
+alternative Google accounts for unlocking FRP to replace the ones activated on the device.</p>
+</li>
+<li><strong>Data usage tracking.</strong> A Profile or Device Owner can now query for the
+data usage statistics visible in <strong>Settings > Data</strong> usage by using the new
{@code android.app.usage.NetworkStatsManager} methods. Profile Owners are automatically granted
permission to query data on the profile they manage, while Device Owners get access to usage data
of the managed primary user.</li>
+<li><strong>Runtime permission management:</strong> With the new runtime permissions model, a
+Profile or Device Owner can now silently grant or revoke an app’s permissions by calling
+{@code DevicePolicyManager.setPermissionGranted()}. Granting or revoking a single permission applies
+that setting to all permissions within that runtime permission group; the user is not prompted
+at runtime when any permission from that runtime permission group is required. Furthermore, the
+user cannot modify the selection made by the Profile or Device Owner within the app’s permissions
+screen in <strong>Settings</strong>.
+<img src="{@docRoot}preview/images/work-profile-screen_2x.png"
+srcset="{@docRoot}preview/images/work-profile-screen.png 1x, preview/images/work-profile-screen_2x.png 2x"
+style="float:right; margin:0 0 10px 20px" width="282" height="476" />
+<p>A Profile or Device Owner can also set a permission policy
+for all runtime requests of all applications using
+{@code DevicePolicyManager.setPermissionPolicy()}, to either prompt the user to grant the
+permission as normal or automatically grant or deny the permission silently. If the latter policy
+is set, the user cannot modify the selection made by the Profile or Device Owner within the
+app’s permissions screen in <strong>Settings</strong>.</p></li>
+<li><strong>VPN in Settings:</strong> VPN apps are now visible in
+ <strong>Settings > More > VPN</strong>.
+Additionally, the notifications that accompany VPN usage are now specific to whether that VPN is
+configured for a managed profile or the entire device.</li>
+<li><strong>Work status notification:</strong> A status bar briefcase icon now appears whenever
+an app from the managed profile has an activity in the foreground. Furthermore, if the device is
+unlocked directly to the activity of an app in the managed profile, a toast is displayed notifying
+the user that they are within the work profile.
+</li>
</ul>
<p class="note">
For a detailed view of all API changes in the M Developer Preview, see the <a href=
- "{@docRoot}preview/reference.html">API Differences Report</a>.
+ "{@docRoot}preview/download.html">API Differences Report</a>.
</p>
\ No newline at end of file
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd
new file mode 100644
index 0000000..0dd549b
--- /dev/null
+++ b/docs/html/preview/behavior-changes.jd
@@ -0,0 +1,407 @@
+page.title=Behavior Changes
+page.keywords=preview,sdk,compatibility
+sdk.platform.apiLevel=23
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ol id="toc44" class="hide-nested">
+ <li><a href="#behavior-runtime-permissions">Runtime Permissions</a></li>
+ <li><a href="#behavior-project-volta">Project Volta</a>
+ <ol>
+ <li><a href="#behavior-doze">Doze mode</a></li>
+ <li><a href="#behavior-app-standby">App Standby</a></li>
+ </ol>
+ </li>
+ <li><a href="#behavior-adoptable-storage">Adoptable Storage Devices</a></li>
+ <li><a href="#behavior-apache-http-client">Apache HTTP Client Removal</a></li>
+ <li><a href="#behavior-audiomanager-Changes">AudioManager Changes</a></li>
+ <li><a href="#behavior-test-selection">Text Selection</a></li>
+ <li><a href="#behavior-keystore">Android Keystore Changes</a></li>
+ <li><a href="#night-mode">Night Mode</a></li>
+ <li><a href="#behavior-network">Wi-Fi and Networking Changes</a></li>
+ <li><a href="#behavior-camera">Camera Service Changes</a></li>
+ <li><a href="#behavior-art-runtime">ART Runtime</a></li>
+ <li><a href="#behavior-apk-validation">APK Validation</a></li>
+ <li><a href="#behavior-afw">Android for Work Changes</a></li>
+</ol>
+
+<h2>API Differences</h2>
+<ol>
+<li><a href="{@docRoot}preview/download.html">API level 22 to M Preview »</a> </li>
+</ol>
+
+
+<h2>See Also</h2>
+<ol>
+<li><a href="{@docRoot}preview/api-overview.html">M Developer Preview API Overview</a> </li>
+</ol>
+
+</div>
+</div>
+
+<p>API Level: M</p>
+<p>Along with new features and capabilities, the M Developer Preview includes a variety of
+system changes and API behavior changes. This document highlights
+some of the key changes that you should be understand and account for in your apps.</p>
+
+<p>If you have previously published an app for Android, be aware that your app
+ might be affected by these changes in the platform.</p>
+
+<h2 id="behavior-runtime-permissions">Runtime Permissions</h1>
+<p>This preview introduces a new runtime permissions model, where users can now directly manage
+their app permissions at runtime. This model gives users improved visibility and control over
+permissions, while streamlining the installation and auto-update processes for app developers.
+Users can set permissions on or off for all apps running on the M Preview. However, apps that
+don’t target the M Preview cannot request permissions at runtime.</p>
+
+<p>On your apps that target the M Preview, make sure to check and request for permissions at
+runtime. To determine if your app has been granted a permission, call the
+new {@code Context.checkSelfPermission()} method. To request for a permission, call the new
+{@code Activity.requestPermission()} method.</p>
+
+<p>For more information on supporting the new permissions model in your app, see
+<a href="{@docRoot}preview/features/runtime-permissions.html">
+Android M Preview Runtime Permissions</a>.</p>
+
+<h2 id="behavior-project-volta">Project Volta</h2>
+<p>This preview introduces new power-saving optimizations for idle devices and apps.</p>
+
+<h3 id="behavior-doze">Doze mode</h3>
+<p>If a device is unplugged and left stationary with the screen off for a period of time, it
+goes into <em>Doze</em> mode where it attempts to keep the system in a sleep state. In this mode,
+devices periodically resume normal operations for brief periods of time so that app syncing can
+occur and the system can perform any pending operations.</p>
+
+<p>The following restrictions apply to your apps while in Doze mode:</p>
+<ul>
+<li>Network access is disabled, unless your app receives a high priority Google Cloud Messaging
+tickle.</li>
+<li><a href="{@docRoot}reference/android/os/PowerManager.WakeLock.html">Wake locks</a> are ignored.</li>
+<li>Alarms scheduled with the {@link android.app.AlarmManager} class are disabled, except for
+alarms that you've set with the {@link android.app.AlarmManager#setAlarmClock setAlarmClock()}
+method and {@code AlarmManager.setAndAllowWhileIdle()}.</li>
+<li>WiFi scans are not performed.</li>
+<li>Syncs and jobs for your sync adapters and {@link android.app.job.JobScheduler} are not
+permitted to run.</li>
+</ul>
+</p>
+<p>When the device exists doze mode, it executes any jobs and syncs that are pending.</p>
+<p>You can test this feature by connecting a device running the M Preview to your development
+machine and calling the following commands:
+</p>
+<pre class="no-prettyprint">
+$ adb shell dumpsys battery unplug
+$ adb shell dumpsys deviceidle step
+$ adb shell dumpsys deviceidle -h
+</pre>
+<p class="note"><strong>Note</strong>: The upcmoning
+<a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> release lets you designate
+high-priority messages. If your app receives high-priority GCM messages, it’s granted
+brief network access even when the device is in doze mode.
+</p>
+
+<h3 id="behavior-app-standby">App standby</h3>
+<p>With this preview, the system may determine that apps are idle when they are not in active
+use. Your app is considered idle after a period of time, unless the system detects
+any of these signals:</p>
+
+<ul>
+<li>The app has a process currently in the foreground (either as an activity or foreground service,
+or in use by another activity or foreground service).</li>
+<li>The app generates a notification that users see on the lock screen or in the
+notification tray.</li>
+<li>The user explicitly asks for the app to be exempt from optimizations,
+via <strong>Settings</strong>.</li>
+</ul>
+
+<p>If the device is unplugged, apps deemed idle will have their network access disabled
+and their syncs and jobs suspended. When the device is plugged into a power supply, these apps are
+allowed network access and can execute any jobs and syncs that are pending. If the
+device is idle for long periods of time, idle apps are allowed network access around once a day.</p>
+
+<p>You can test this feature by connecting a device running the M Preview to your development
+machine and calling the following commands:
+</p>
+<pre class="no-prettyprint">
+$ adb shell am broadcast -a android.os.action.DISCHARGING
+$ adb shell am set-idle <packageName> true
+$ adb shell am set-idle <packageName> false
+$ adb shell am get-idle <packageName>
+</pre>
+
+<p class="note"><strong>Note</strong>: The upcoming
+<a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM) release lets you
+designate high-priority messages. If your app receives high-priority GCM messages, it’s granted
+brief network access even when the app is idle.
+</p>
+
+<h2 id="behavior-adoptable-storage">Adoptable Storage Devices</h2>
+<p>
+With this preview, users can <em>adopt</em> external storage devices such as SD cards. Adopting an
+external storage device encrypts and formats the device to behave like internal storage. This
+feature allows users to move both apps and private data of those apps between storage devices. When
+moving apps, the system respects the
+<a href="{@docRoot}guide/topics/manifest/manifest-element.html#install">{@code android:installLocation}</a>
+preference in the manifest.</p>
+
+<p>If your app accesses the following APIs or fields, be aware that the file paths they return
+will dynamically change when the app is moved between internal and external storage devices.
+When building file paths, it is strongly recommended that you always call these APIs dynamically.
+Don’t use hardcoded file paths or persist fully-qualified file paths that were built previously.</p>
+
+<ul>
+<li>{@link android.content.Context} methods:
+ <ul>
+ <li>{@link android.content.Context#getFilesDir() getFilesDir()}</li>
+ <li>{@link android.content.Context#getCacheDir() getCacheDir()}</li>
+ <li>{@link android.content.Context#getCodeCacheDir() getCodeCacheDir()}</li>
+ <li>{@link android.content.Context#getDatabasePath(java.lang.String) getDatabasePath()}</li>
+ <li>{@link android.content.Context#getDir(java.lang.String,int) getDir()}</li>
+ <li>{@link android.content.Context#getNoBackupFilesDir() getNoBackupFilesDir()}</li>
+ <li>{@link android.content.Context#getFileStreamPath(java.lang.String) getFileStreamPath()}</li>
+ <li>{@link android.content.Context#getPackageCodePath() getPackageCodePath()}</li>
+ <li>{@link android.content.Context#getPackageResourcePath() getPackageResourcePath()}</li>
+ </ul>
+</li>
+<li>{@link android.content.pm.ApplicationInfo} fields:
+ <ul>
+ <li>{@link android.content.pm.ApplicationInfo#dataDir dataDir}</li>
+ <li>{@link android.content.pm.ApplicationInfo#sourceDir sourceDir}</li>
+ <li>{@link android.content.pm.ApplicationInfo#nativeLibraryDir nativeLibraryDir}</li>
+ <li>{@link android.content.pm.ApplicationInfo#publicSourceDir publicSourceDir}</li>
+ <li>{@link android.content.pm.ApplicationInfo#splitSourceDirs splitSourceDirs}</li>
+ <li>{@link android.content.pm.ApplicationInfo#splitPublicSourceDirs splitPublicSourceDirs}</li>
+ </ul>
+</li>
+</ul>
+
+<p>To debug this feature in the developer preview, you can enable adoption of a USB drive that is
+connected to an Android device through a USB On-The-Go (OTG) cable, by running this command:</p>
+
+<pre class="no-prettyprint">
+$ adb shell sm set-force-adoptable true
+</pre>
+
+<h2 id="behavior-apache-http-client">Apache HTTP Client Removal</h2>
+<p>This preview removes support for the Apache HTTP client. If your app is using this client and
+targets Android 2.3 (API level 9) or higher, use the {@link java.net.HttpURLConnection} class
+instead. This API is more efficient because it reduces network use through transparent compression
+and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you
+must first declare the following compile-time dependency in your {@code build.gradle} file:
+</p>
+<pre>
+android {
+ useLibrary 'org.apache.http.legacy'
+}
+</pre>
+<p>Android is moving away from OpenSSL to the
+<a href="https://boringssl.googlesource.com/boringssl/" class="external-link">BoringSSL</a>
+library. If you’re using the Android NDK in your app, don't link against cryptographic libraries
+that are not a part of the NDK API, such as {@code libcrypto.so} and {@code libssl.so}. These
+libraries are not public APIs, and may change or break without notice across releases and devices.
+In addition, you may expose yourself to security vulnerabilities. Instead, modify your
+native code to call the Java cryptography APIs via JNI or to statically link against a
+cryptography library of your choice.</p>
+
+<h2 id="behavior-audiomanager-Changes">AudioManager Changes</h2>
+<p>Setting the volume directly or muting specific streams via the {@link android.media.AudioManager}
+class is no longer supported. The {@link android.media.AudioManager#setStreamSolo(int,boolean)
+setStreamSolo()} method is deprecated, and you should call the
+{@code AudioManager.requestAudioFocus()} method instead. Similarly, the
+{@link android.media.AudioManager#setStreamMute(int,boolean) setStreamMute()} method is
+deprecated; instead, call the {@code AudioManager.adjustStreamVolume()} method
+and pass in the direction value {@code ADJUST_MUTE} or {@code ADJUST_UNMUTE}.</p>
+
+<h2 id="behavior-test-selection">Text Selection</h2>
+
+<img src="{@docRoot}preview/images/text-selection.gif"
+style="float:right; margin:0 0 20px 30px" width="360" height="640" />
+
+<p>When users select text in your app, you can now display text selection actions such as
+<em>Cut</em>, <em>Copy</em>, and <em>Paste</em> in a
+<a href="http://www.google.com/design/spec/patterns/selection.html#selection-text-selection"
+class="external-link">floating toolbar</a>. The user interaction implementation is similar to that
+for the contextual action bar, as described in
+<a href="{@docRoot}guide/topics/ui/menus.html#CABforViews">
+Enabling the contextual action mode for individual views</a>.</p>
+
+<p>To implement a floating toolbar for text selection, make the following changes in your existing
+apps:</p>
+<ol>
+<li>In your {@link android.view.View} or {@link android.app.Activity} object, change your
+{@link android.view.ActionMode} calls from
+{@code startActionMode(Callback)} to {@code startActionMode(Callback, ActionMode.TYPE_FLOATING)}.</li>
+<li>Take your existing implementation of {@code ActionMode.Callback} and make it extend
+{@code ActionMode.Callback2} instead.</li>
+<li>Override the {@code Callback2.onGetContentRect()} method to provide the coordinates of the
+content {@link android.graphics.Rect} object (such as a text selection rectangle) in the view.</li>
+<li>If the rectangle positioning is no longer valid, and this is the only element to be invalidated,
+call the {@code ActionMode.invalidateContentRect()} method.</li>
+</ol>
+
+<p>If you are using <a href="{@docRoot}tools/support-library/index.html">
+Android Support Library</a> revision 22.2, be aware that floating toolbars are not
+backward-compatible and appcompat takes control over {@link android.view.ActionMode} objects by
+default. This prevents floating toolbars from being displayed. To enable
+{@link android.view.ActionMode} support in an
+{@link android.support.v7.app.AppCompatActivity}, call
+{@code android.support.v7.app.AppCompatActivity.getDelegate()}, then call
+{@code android.support.v7.app.AppCompatDelegate.setHandleNativeActionModesEnabled()} on the returned
+{@link android.support.v7.app.AppCompatDelegate} object and set the input
+parameter to {@code false}. This call returns control of {@link android.view.ActionMode} objects to
+the framework. In devices running the M Preview, that allows the framework to support
+{@link android.support.v7.app.ActionBar} or floating toolbar modes, while on pre-M Preview devices,
+only the {@link android.support.v7.app.ActionBar} modes are supported.</p>
+
+<h2 id="behavior-keystore">Android Keystore Changes</h2>
+<p>With this preview, the
+<a href="{@docRoot}training/articles/keystore.html">Android Keystore provider</a> no longer supports
+DSA. ECDSA is still supported.</p>
+
+<p>Keys which do not require encryption at rest will no longer be deleted when secure lock screen
+is disabled or reset (for example, by the user or a Device Administrator). Keys which require
+encryption at rest will be deleted during these events.</p>
+
+<h2 id="night-mode">Night Mode (User-configurable Dark Theme)</h2>
+<p>
+Support for the {@code -night} resource qualifier has been updated. Previously, night mode was
+only available when a device was docked and in car mode. With this preview, night mode is
+available on
+all devices and is user-configurable via <strong>Settings > Display > Theme</strong>. You can adjust
+this setting globally using {@link android.app.UiModeManager#setNightMode(int) setNightMode()}. The
+Dark theme corresponds to {@link android.app.UiModeManager#MODE_NIGHT_YES}. When the device is in
+night mode, the resource framework prefers resources that have the {@code -night} qualifier. To
+take advantage of user-configurable Dark mode in your app, extend from the
+{@code Theme.Material.DayNight} set of themes rather than {@code Theme.Material} or
+{@code Theme.Material.Light}.
+</p>
+
+<h2 id="behavior-network">Wi-Fi and Networking Changes</h2>
+
+<p>This preview introduces the following behavior changes to the Wi-Fi and networking APIs.</p>
+<ul>
+<li>Your apps can now change the state of {@link android.net.wifi.WifiConfiguration} objects only
+if you created these objects. You are not permitted to modify or delete
+{@link android.net.wifi.WifiConfiguration} objects created by the user or by other apps.
+</li>
+<li>
+Previously, if an app forced the device to connect to a specific Wi-Fi network by using
+{@link android.net.wifi.WifiManager#enableNetwork(int,boolean) enableNetwork()} with the
+{@code disableAllOthers=true} setting, the device disconnected from other networks such as
+cellular data. In this preview, the device no longer disconnects from such other networks. If
+your app’s {@code targetSdkVersion} is {@code “20”} or lower, it is pinned to the selected
+Wi-Fi network. If your app’s {@code targetSdkVersion} is {@code “21”} or higher, use the
+multinetwork APIs (such as
+{@link android.net.Network#openConnection(java.net.URL) openConnection()},
+{@link android.net.Network#bindSocket(java.net.Socket) bindSocket()}, and the new
+{@code ConnectivityManager.bindProcessToNetwork()} method) to ensure that its network traffic is
+sent on the selected network.</li>
+</ul>
+
+<h2 id="behavior-camera">Camera Service Changes</h2>
+<p>In this preview, the model for accessing shared resources in the camera service has been changed
+from the previous “first come, first serve” access model to an access model where high-priority
+processes are favored. Changes to the service behavior include:</p>
+<ul>
+<li>Access to camera subsystem resources, including opening and configuring a camera device, is
+awarded based on the “priority” of the client application process. Application processes with
+user-visible or foreground activities are generally given a higher-priority, making camera resource
+acquisition and use more dependable.</li>
+<li>Active camera clients for lower priority apps may be “evicted” when a higher priority
+application attempts to use the camera. In the deprecated {@link android.hardware.Camera} API,
+this results in
+{@link android.hardware.Camera.ErrorCallback#onError(int,android.hardware.Camera) onError()} being
+called for the evicted client. In the {@link android.hardware.camera2 Camera2} API, it results in
+{@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected(android.hardware.camera2.CameraDevice) onDisconnected()}
+being called for the evicted client.</li>
+<li>On devices with appropriate camera hardware, separate application processes are able to
+independently open and use separate camera devices simultaneously. However, multi-process use
+cases, where simultaneous access causes significant degradation of performance or capabilities of
+any of the open camera devices, are now detected and disallowed by the camera service. This change
+may result in “evictions” for lower priority clients even when no other app is directly
+attempting to access the same camera device.
+</li>
+<li>
+Changing the current user causes active camera clients in apps owned by the previous user account
+to be evicted. Access to the camera is limited to user profiles owned by the current device user.
+In practice, this means that a “Guest” account, for example, will not be able to leave running
+processes that use the camera subsystem when the user has switched to a different account.
+</li>
+</ul>
+
+<h2 id="behavior-art-runtime">ART Runtime</h2>
+<p>The ART runtime now properly implements access rules for the
+{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()} method. This
+change fixes a problem where Dalvik was checking access rules incorrectly in previous versions.
+If your app uses the
+{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()} method and you
+want to override access checks, call the
+{@link java.lang.reflect.Constructor#setAccessible(boolean) setAccessible()} method with the input
+parameter set to {@code true}. If your app uses the
+<a href="{@docRoot}tools/support-library/features.html#v7-appcompat">v7 appcompat library</a> or the
+<a href="{@docRoot}tools/support-library/features.html#v7-recyclerview">v7 recyclerview library</a>,
+you must update your app to use to the latest versions of these libraries. Otherwise, make sure that
+any custom classes referenced from XML are updated so that their class constructors are accessible.</p>
+
+<p>This preview updates the behavior of the dynamic linker. The dynamic linker now understands the
+difference between a library’s {@code soname} and its path
+(<a href="https://code.google.com/p/android/issues/detail?id=6670" class="external-link">
+public bug 6670</a>), and search by {@code soname} is now
+implemented. Apps which previously worked that have bad {@code DT_NEEDED} entries
+(usually absolute paths on the build machine’s file system) may fail when loaded.</p>
+
+<p>The {@code dlopen(3) RTLD_LOCAL} flag is now correctly implemented. Note that
+{@code RTLD_LOCAL} is the default, so calls to {@code dlopen(3)} that didn’t explicitly use
+{@code RTLD_LOCAL} will be affected (unless your app explicitly used {@code RTLD_GLOBAL}). With
+{@code RTLD_LOCAL}, symbols will not be made available to libraries loaded by later calls to
+{@code dlopen(3)} (as opposed to being referenced by {@code DT_NEEDED} entries).</p>
+</p>
+
+<h2 id="behavior-apk-validation">APK Validation</h2>
+<p>The platform now performs stricter validation of APKs. An APK is considered corrupt if a file is
+declared in the manifest but not present in the APK itself. An APK must be re-signed if any of the
+contents are removed.</p>
+
+<h2 id="behavior-afw">Android for Work Changes</h2>
+<p>This preview includes the following behavior changes for Android for Work:</p>
+<ul>
+<li><strong>Work contacts in personal contexts.</strong> The Google Dialer
+Call Log now displays work contacts when the user views past calls. Both
+work and personal contacts are now available to devices over Bluetooth, but you can hide work
+profile contacts through a device policy by calling the new
+{@code DevicePolicyManager.setBluetoothContactSharingDisabled()} method. Initiating a call still
+shows personal contacts, as consistent with the experience in Android 5.0.
+</li>
+<li><strong>WiFi configuration removal:</strong> WiFi configurations added by a Profile Owner
+(for example, through calls to the
+{@link android.net.wifi.WifiManager#addNetwork(android.net.wifi.WifiConfiguration)
+addNetwork()} method) are now removed if that work profile is deleted.</li>
+<li><strong>WiFi configuration lockdown:</strong> Any WiFi configuration created by an active Device
+Owner can no longer be modified or deleted by the user. The user can still create and
+modify their own WiFi configurations, so long as the {@link android.os.UserManager} constant
+{@link android.os.UserManager#DISALLOW_CONFIG_WIFI} has not been set for that user.</li>
+<li><strong>Download Work Policy Controller via Google account addition:</strong> When a Google
+account that requires management via a Work Policy Controller (WPC) app is added to a device
+outside of a managed context, the add account flow now prompts the user to install the
+appropriate WPC. This behavior also applies to accounts added via
+<strong>Settings > Accounts</strong> in the initial device setup wizard.</li>
+<li><strong>Changes to specific DevicePolicyManager API behaviors:</strong>
+Calling the {@link android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName,boolean) setCameraDisabled()}
+method affects the camera for the calling user only; calling it from the managed profile doesn’t
+affect camera apps running on the primary user. In addition, the
+{@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures(android.content.ComponentName,int) setKeyguardDisabledFeatures()}
+method is now available for Profile Owners, in addition to Device Owners. A Profile Owner can set
+these keyguard restrictions:
+<ul>
+<li>{@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} and
+ {@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_FINGERPRINT}, which affect the
+ keyguard settings for the profile’s parent user.</li>
+<li>{@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, which
+ only affects notifications generated by applications in the managed profile.</li>
+</ul>
+</li>
+</ul>
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
index 0000000..679b7ad
--- /dev/null
+++ b/docs/html/preview/features/images/app-permissions-screen.png
Binary files 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
index 0000000..e3eb13f
--- /dev/null
+++ b/docs/html/preview/features/images/app-permissions-screen@2x.png
Binary files differ
diff --git a/docs/html/preview/features/runtime-permissions.jd b/docs/html/preview/features/runtime-permissions.jd
index 4a01010..f9646a8 100644
--- a/docs/html/preview/features/runtime-permissions.jd
+++ b/docs/html/preview/features/runtime-permissions.jd
@@ -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 @@
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 @@
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
+ ></strong> <i>app_name</i> <strong>> 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 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.
+ 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>
-<h2 id="">Coding for Runtime Permissions</h2>
+<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>
+ 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>
+
+<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 @@
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><uses-permission-sdk-m></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><uses-permission-sdk-m></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><uses-permission-sdk-m></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><uses-permission-sdk-m></code> behaves the same as
- <code><uses-permission></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"><uses-permission></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 @@
</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 -->
-</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]-->
-
- <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>
-
- <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>
-
- <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.
- </li>
-</ul>
-
-<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.
-</p>
-
-<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><uses-permission-sdk-m></code>.
</p>
-<h2 id="">Best Practices</h2>
+<h4 id="check-platform">Check what platform the app is running on</h4>
+
+<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>
+
+<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>
+
+<pre>
+@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>
+</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 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 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>
+
+<pre class="no-pretty-print">
+$ adb install -g <path_to_apk>
+</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 <package_name> <permission_name>
+</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 <package_name> <permission_name>
+</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 @@
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 @@
<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 @@
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/html/preview/images/work-profile-screen.png b/docs/html/preview/images/work-profile-screen.png
new file mode 100644
index 0000000..c3e4e44
--- /dev/null
+++ b/docs/html/preview/images/work-profile-screen.png
Binary files differ
diff --git a/docs/html/preview/images/work-profile-screen_2x.png b/docs/html/preview/images/work-profile-screen_2x.png
new file mode 100644
index 0000000..5dcf610
--- /dev/null
+++ b/docs/html/preview/images/work-profile-screen_2x.png
Binary files differ
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index 7e9f292..0371932 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -38,10 +38,9 @@
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/api-changes.html">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/behavior-changes.html">
Behavior Changes</a></div>
</li>
-
<li class="nav-section">
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/samples.html">
Samples</a></div>
diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd
index 56ec90a..f5a797c 100644
--- a/docs/html/training/auto/audio/index.jd
+++ b/docs/html/training/auto/audio/index.jd
@@ -21,6 +21,7 @@
<li><a href="#config_manifest">Configure Your Manifest</a></li>
<li><a href="#implement_browser">Build a Browser Service</a></li>
<li><a href="#implement_callback">Implement Play Controls</a></li>
+ <li><a href="#support_voice">Support Voice Actions</a></li>
</ol>
<h2>Related Samples</h2>
@@ -28,6 +29,8 @@
<ul>
<li><a href="{@docRoot}samples/MediaBrowserService/index.html">
MediaBrowserService</a></li>
+ <li><a href="//github.com/googlesamples/android-UniversalMusicPlayer">Universal Media
+ Player</a></li>
</ul>
<h2>See Also</h2>
@@ -58,7 +61,7 @@
Drivers want to access their music and other audio content on the road. Audio books, podcasts,
sports commentary, and recorded talks can make a long trip educational, inspirational, and
enjoyable. The Android framework allows you to extend your audio app so users can listen to their
- favorite tunes and audio content using a simpler, safer user interface.
+ favorite tunes and audio content using a simple, yet customizable user interface.
</p>
<p>
@@ -280,7 +283,7 @@
<p class="note"><strong>Note:</strong> You should consider providing different content
hierarchies depending on what client is making the query. In particular, Auto
applications have strict limits on how large a menu they can display. This is
-intended to prevent distracting the driver, and to make it easy for the driver
+intended to minimize distracting the driver, and to make it easy for the driver
to operate the app via voice commands. For more information on the Auto user
experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">
Auto Audio Apps</a> guidelines.</p>
@@ -383,7 +386,7 @@
<pre>
public void onCreate() {
- super.onCreate();
+ super.onCreate();
...
// Start a new MediaSession
@@ -426,6 +429,12 @@
{@link android.media.session.MediaSession.Callback#onPause onPause()}, your
app should resume playback.</dd>
+<p class="note">
+ <strong>Note:</strong> Google Play requires your app not to play music immediately when it
+ launches. For more information on this and other requirements, see
+<a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.
+</p>
+
<dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId
onPlayFromMediaId()}</dt>
<dd>Invoked when the user chooses to play a specific item. The method is passed
@@ -470,3 +479,196 @@
<a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a>,
<a href="{@docRoot}training/managing-audio/index.html">Managing Audio Playback</a>, and
<a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>.</p>
+
+
+<h2 id="support_voice">Support Voice Actions</h2>
+
+<p>To reduce driver distractions, you can add voice actions in your audio playback app. With voice
+action support, users can launch your app and play audio by providing voice input on Auto screens.
+If your audio playback app is already active and the user says
+<i>“Play a song”</i>, the system starts playing music without requiring the user to look at or touch
+the screen.</p>
+
+<h3 id="enable_playback">Enable your app to handle audio playback requests</h3>
+
+<p>Enable your audio app to launch with a voice command such as <i>"Play [search query] on
+[your app name]"</i> by adding the following entry in your manifest:</p>
+
+<pre>
+<activity>
+ <intent-filter>
+ <action android:name=
+ "android.media.action.MEDIA_PLAY_FROM_SEARCH" />
+ <category android:name=
+ "android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+</pre>
+
+<p>When the user says <i>“Play music on [your app name]”</i> on an Auto screen, Auto
+attempts to launch your app and play audio by calling your app’s
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
+method. If the user has not specified criteria such as a track name or music genre, the
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
+method receives an empty query parameter. Your app should respond by immediately playing audio, such
+as a song from a random queue or the most recent playlist.
+</p>
+
+<h3 id="parse_voice">Parse the voice query to build the playback queue</h3>
+
+<p>When a user searches for a specific criteria, such as <i>“Play jazz on [your app name]”</i>
+or <i>“Listen to [song title]”</i>, the
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
+callback method receives the voice search results in the query parameter and an extras bundle. For
+more information on how to handle search queries to play audio content, see
+<a href="https://developer.android.com/guide/components/intents-common.html#PlaySearch">Play music
+based on a search query</a>.
+</p>
+
+<p>To parse the voice search query to play back audio content in your app, follow these steps:</p>
+
+<ol>
+ <li>Use the extras bundle and search query string returned from the voice search to filter
+ results.</li>
+ <li>Build the audio content queue based on these results.</li>
+ <li>Play the audio content.</li>
+</ol>
+
+<p>The
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
+method takes an extras parameter with more detailed information from the voice search.
+These extras help you find the audio content in your app for playback. If the search results are
+unable to provide this data, you can implement logic to parse the raw search query and play the
+appropriate tracks based on the query.
+</p>
+
+<p>The following extras are supported in Android Auto:</p>
+
+<ul>
+ <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ALBUM"><code>android.intent.extra.album</code></a></li>
+ <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ARTIST"><code>android.intent.extra.artist</code></a></li>
+ <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_GENRE"><code>android.intent.extra.genre</code></a></li>
+ <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_PLAYLIST"><code>android.intent.extra.playlist</code></a></li>
+ <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_TITLE"><code>android.intent.extra.title</code></a></li>
+</ul>
+
+<p>The following snippet shows how to override the
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
+method in your
+<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html"><code>MediaSession.Callback</code></a>
+implementation to handle the search query and extras for playing audio content in your app:
+</p>
+
+<pre>
+@Override
+public void onPlayFromSearch(String query, Bundle extras) {
+ if (TextUtils.isEmpty(query)) {
+ // The user provided generic string e.g. 'Play music'
+ // Build appropriate playlist queue
+ } else {
+ // Build a queue based on songs that match "query" or "extras" param
+ String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS);
+ if (TextUtils.equals(mediaFocus,
+ MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) {
+ isArtistFocus = true;
+ artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST);
+ } else if (TextUtils.equals(mediaFocus,
+ MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) {
+ isAlbumFocus = true;
+ album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM);
+ }
+
+ // Implement additional "extras" param filtering
+ }
+
+ // Implement your logic to retrieve the queue
+ if (isArtistFocus) {
+ result = searchMusicByArtist(artist);
+ } else if (isAlbumFocus) {
+ result = searchMusicByAlbum(album);
+ }
+
+ if (result == null) {
+ // No focus found, search by query for song title
+ result = searchMusicBySongTitle(query);
+ }
+
+ if (result != null && !result.isEmpty()) {
+ // Immediately start playing from the beginning of the search results
+ // Implement your logic to start playing music
+ playMusic(result);
+ } else {
+ // Handle no queue found. Stop playing if the app
+ // is currently playing a song
+ }
+}
+</pre>
+
+<p class="note">
+ <strong>Note:</strong> To minimize driver distractions, immediately initiate audio content
+ playback in the
+ <a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
+ method when you have generated the audio content queue based on the user's request.
+</p>
+
+<p>For a more detailed example on how to implement voice search to play audio content in your app,
+see the
+<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
+sample.
+</p>
+
+<h3 id="implement_playback_controls">Implement playback control actions</h3>
+
+<p>To provide a hands-free experience while users drive and listen to audio content in Android Auto,
+your app should allow users to control audio content playback with voice actions. When users speak
+commands such as <i>“Next song”</i>, <i>“Pause music”</i>, or <i>“Resume music”</i>, the system
+triggers the corresponding callback method where you implement the playback control action.
+</p>
+
+<p>To provide voice-enabled playback controls, first enable the hardware controls by setting these
+flags in your app’s
+<a href="{@docRoot}reference/android/media/session/MediaSession.html"><code>MediaSession</code></a>
+object:
+</p>
+
+<pre>
+mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
+ MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
+</pre>
+
+<p>Then, implement the callback methods with the playback controls that you support in your app.
+Here’s a list of voice-enabled playback controls supported by Android Auto:
+</p>
+
+<table>
+ <tr>
+ <th>Example phrase</th>
+ <th>Callback method</th>
+ </tr>
+ <tr>
+ <td><i>"Next song"</i></td>
+ <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToNext()"><code>onSkipToNext()</code></a></td>
+ </tr>
+ <tr>
+ <td><i>"Previous song"</i></td>
+ <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToPrevious()"><code>onSkipToPrevious()</code></a></td>
+ </tr>
+ <tr>
+ <td><i>"Pause music"</i></td>
+ <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPause()"><code>onPause()</code></a></td>
+ </tr>
+ <tr>
+ <td><i>"Stop music"</i></td>
+ <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onStop()"><code>onStop()</code></a></td>
+ </tr>
+ <tr>
+ <td><i>"Resume music"</i></td>
+ <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlay()"><code>onPlay()</code></a></td>
+ </tr>
+</table>
+
+<p>For a more detailed example on how to implement voice-enabled playback actions in your app, see
+the
+<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
+sample.
+</p>
\ No newline at end of file
diff --git a/docs/html/training/auto/messaging/index.jd b/docs/html/training/auto/messaging/index.jd
index 7540a3f..0177c84 100644
--- a/docs/html/training/auto/messaging/index.jd
+++ b/docs/html/training/auto/messaging/index.jd
@@ -52,9 +52,8 @@
<p>
Staying connected through messages is important to many drivers. Chat apps can let users
- know if a child need to be picked up, or if a dinner location has been changed. Apps that provide
- sports information might tell the user who just won the big game, and let the user ask questions
- about other games being played. The Android framework enables messaging apps to extend their
+ know if a child need to be picked up, or if a dinner location has been changed.
+ The Android framework enables messaging apps to extend their
services into car dashboards using a standard user interface that lets drivers keep their eyes
on the road.
</p>
@@ -79,7 +78,7 @@
<p>
Messaging apps do not run directly on the Android dashboard hardware. They are installed on
- separate, Android mobile device. When the mobile device is plugged into a dashboard,
+ a separate Android mobile device. When the mobile device is plugged into a dashboard,
the installed messaging apps can offer services for viewing and responding to messages
through the Auto user interface.
</p>
@@ -98,7 +97,7 @@
has read or replied to a message.
</ul>
-<h3 id="#concepts">Concepts and Objects</h3>
+<h3 id="concepts">Concepts and objects</h3>
<p>Before you start designing your app, it's helpful to understand how Auto
handles messaging.</p>
@@ -106,23 +105,19 @@
<p>Each individual chunk of communication is a <em>message</em>. A message is a
short length of text, suitable for the Auto device to read aloud. In a chat app,
this might be a single message from one person to another: <code>"Fitzy -- Jane
-can't come to the ball, her youngest has the croup. :-( --Liz"</code> In a
-sports app, a message might be a single bit of news about a game: <code>"Granger
-scores for Harpies at 7 minutes in."</code></p>
+can't come to the ball, her youngest has the croup. :-( --Liz"</code>.</p>
<p>A <em>conversation</em> is a group of messages that are all grouped together
in some way. Auto uses the conversation information to group the messages
together when presenting them to the user. In a chat app, a conversation might
be all the messages between the user and another person (for example, all
-the messages back and forth between Darcy and Elizabeth). In a sports app, a
-conversation might be all the messages about a particular game. Every message
+the messages back and forth between Darcy and Elizabeth). Every message
belongs to a conversation, even if it's the only message in that conversation.
Each conversation has a <em>conversation name</em>.
The conversation name is used by Android Auto to
present the messages; it's up to your app to choose an appropriate conversation
name. In a chat app, the conversation name is usually the person your user is
-talking to.
-In a sports app, this might be the name of the teams playing in the game.</p>
+talking to.</p>
<p>The v4 support library defines an {@link
android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation
@@ -177,9 +172,7 @@
<li>If the user sends a reply, Auto triggers the app's "message reply" intent and
attaches a transcript of the user's response. The app can take appropriate
action, based on the app's logic. For example, a chat app might interpret the
-reply as a message to go to the other conversation participants, while a sports
-app might try to interpret the "reply" as a request for other information
-("What's the score in the Sharks game?").</li>
+reply as a message to go to the other conversation participants.</li>
</ol>
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
index 0000000..1868c7a
--- /dev/null
+++ b/docs/image_sources/preview/features/app-permissions-screen-orig.png
Binary files differ