diff --git a/docs/html/images/cards/card-user-ids_2x.png b/docs/html/images/cards/card-user-ids_2x.png new file mode 100644 index 0000000000000..4db4f3ce3d0c0 Binary files /dev/null and b/docs/html/images/cards/card-user-ids_2x.png differ diff --git a/docs/html/images/cards/card-user-permissions_2x.png b/docs/html/images/cards/card-user-permissions_2x.png new file mode 100644 index 0000000000000..6abac488647ea Binary files /dev/null and b/docs/html/images/cards/card-user-permissions_2x.png differ diff --git a/docs/html/images/cards/card-user_2x.png b/docs/html/images/cards/card-user_2x.png new file mode 100644 index 0000000000000..e4ef23d866740 Binary files /dev/null and b/docs/html/images/cards/card-user_2x.png differ diff --git a/docs/html/images/training/articles/user-data-overview-permissions-flow01.jpg b/docs/html/images/training/articles/user-data-overview-permissions-flow01.jpg new file mode 100644 index 0000000000000..e3b192b53df38 Binary files /dev/null and b/docs/html/images/training/articles/user-data-overview-permissions-flow01.jpg differ diff --git a/docs/html/images/training/articles/user-data-overview-permissions-flow02.jpg b/docs/html/images/training/articles/user-data-overview-permissions-flow02.jpg new file mode 100644 index 0000000000000..c2275eb59a905 Binary files /dev/null and b/docs/html/images/training/articles/user-data-overview-permissions-flow02.jpg differ diff --git a/docs/html/images/training/articles/user-data-overview-permissions-groups.png b/docs/html/images/training/articles/user-data-overview-permissions-groups.png new file mode 100644 index 0000000000000..599648941a0df Binary files /dev/null and b/docs/html/images/training/articles/user-data-overview-permissions-groups.png differ diff --git a/docs/html/images/training/articles/user-data-overview-permissions-usage.jpg b/docs/html/images/training/articles/user-data-overview-permissions-usage.jpg new file mode 100644 index 0000000000000..07323693a6db1 Binary files /dev/null and b/docs/html/images/training/articles/user-data-overview-permissions-usage.jpg differ diff --git a/docs/html/training/articles/user-data-ids.jd b/docs/html/training/articles/user-data-ids.jd new file mode 100644 index 0000000000000..6541373143612 --- /dev/null +++ b/docs/html/training/articles/user-data-ids.jd @@ -0,0 +1,740 @@ +page.title=Best Practices for Unique Identifiers +page.metaDescription=How to manage unique identifiers the right way for users. +page.tags=ids, user data +meta.tags="ids", "user data" +page.image=images/cards/card-user-ids_2x.png + +page.article=true +@jd:body + +
+
+

In this document

+
    +
  1. Tenets of Working with + Android Identifiers
  2. +
  3. Identifiers in Android 6.0+
  4. +
  5. Working with Advertising IDs
  6. +
  7. Working with Instance IDs and GUIDs
  8. +
  9. Understanding Identifier + Characteristics +
      +
    1. Scope
    2. +
    3. Resettability & persistence
    4. +
    5. Uniqueness +
    6. Integrity protection and + non-repudiability
    7. +
    +
  10. +
  11. Common Use Cases and the Identifier to Use +
      +
    1. Tracking signed-out user + preferences
    2. +
    3. Tracking signed-out user behavior
    4. +
    5. Generating + signed-out/anonymous user analytics
    6. +
    7. Tracking signed-out user + conversion
    8. +
    9. Handling multiple installations
    10. +
    11. Anti-fraud: + Enforcing free content limits / detecting Sybil attacks
    12. +
    13. Managing telephony and carrier + functionality
    14. +
    15. Abuse detection: + Identifying bots and DDoS attacks
    16. +
    17. Abuse detection: + Detecting high value stolen credentials
    18. +
    +
  12. +
+
+
+ +

+ While there are valid reasons why your application may need to identify a + device rather than an instance of the application or an authenticated user on + the device, for the vast majority of applications, the ultimate goal is to + identify a particular installation of your app (not the actual + physical device). +

+ +

+ Fortunately, identifying an installation on Android is straightforward using + an Instance ID or by creating your own GUID at install time. This document + provides guidance for selecting appropriate identifiers for your application, + based on your use-case. +

+ +

+ For a general look at Android permissions, please see Permissions + and User Privacy. For specific best practices for + working with Android permissions, please see Best Practices for + App Permissions. +

+ + +

Tenets of Working with Android Identifiers

+ +

+ We recommend that you follow these tenets when working with Android + identifiers: +

+ +

+ #1: Avoid using hardware identifiers. Hardware + identifiers such as SSAID (Android ID) and IMEI can be avoided in most + use-cases without limiting required functionality. +

+ +

+ #2: Only use Advertising ID for user profiling or ads + use-cases. When using an + Advertising ID, always respect the Limit Ad + Tracking flag, ensure the identifier cannot be connected to personally + identifiable information (PII) and avoid bridging Advertising ID resets. +

+ +

+ #3: Use an Instance ID or a privately stored GUID whenever + possible for all other use-cases except payment fraud prevention and + telephony. For the vast majority of non-ads use-cases, an + instance ID or GUID should be sufficient. +

+ +

+ #4: Use APIs that are appropriate to your use-case to minimize + privacy risk. Use the + DRM + API API for high value content + protection and the SafetyNet + API for abuse prevention. The Safetynet API is + the easiest way to determine whether a device is genuine without incurring + privacy risk. +

+ +

+ The remaining sections of this guide elaborate on these rules in the context + of developing Android applications. +

+ +

Identifiers in Android 6.0+

+ +

+ MAC addresses are globally unique, not user-resettable and survive factory + reset. It is generally not recommended to use MAC address for any form of + user identification. As a result, as of Android M, local device MAC addresses + (for example, Wifi and Bluetooth) are not available via third party + APIs. The {@link android.net.wifi.WifiInfo#getMacAddress WifiInfo.getMacAddress()} + method and the {@link android.bluetooth.BluetoothAdapter#getAddress + BluetoothAdapter.getDefaultAdapter().getAddress()} method will + both return 02:00:00:00:00:00.. +

+ +

+ Additionally, you must hold the following permissions to access MAC addresses + of nearby external devices available via Bluetooth and Wifi scans: +

+ + + + + + + + + + + + + + + + +
Method/Property + Permissions Required +
+ WifiManager.getScanResults() + + ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION +
+ BluetoothDevice.ACTION_FOUND + + ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION +
+ BluetoothLeScanner.startScan(ScanCallback) + + ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION +
+ + +

Working with Advertising IDs

+ +

+ Advertising ID is a user-resettable identifier and is appropriate for Ads + use-cases, but there are some key points to bear in mind when using it: +

+ +

+ Always respect the user’s intention in resetting the advertising + ID. Do not bridge user resets by using a more persistent device + identifier or fingerprint to link subsequent Advertising IDs together without + the user’s consent. The Google Play + Developer Content Policy states: +

+ +
+
+

...upon reset, a new advertising + identifier must not be connected to a previous advertising identifier or data + derived from a previous advertising identifier without the explicit consent + of the user

+
+
+ +

+ Always respect the associated Interest Based Advertising + flag. Advertising IDs are configurable in that users can limit + the amount of tracking associated with the ID. Always use the + AdvertisingIdClient.Info.isLimitAdTrackingEnabled() method to + ensure you are not circumventing your users' wishes. The Google Play + Developer Content Policy states: +

+ + +
+
+

...you must abide by a user’s ‘opt out of + interest-based advertising’ setting. If a user has enabled this setting, you + may not use the advertising identifier for creating user profiles for + advertising purposes or for targeting users with interest-based advertising. + Allowed activities include contextual advertising, frequency capping, + conversion tracking, reporting and security and fraud detection.

+
+
+ +

+ Be aware of any privacy or security policies associated with SDKs + you use that are related to Advertising ID use. For example, if + you are using the Google Analytics SDK + mTracker.enableAdvertisingIdCollection(true) + method, make sure to review and adhere to all applicable + Analytics SDK policies. +

+ +

+ Also, be aware that the Google Play + Developer Content Policy requires that the Advertising ID “must not be + connected to personally-identifiable information or associated with any + persistent device identifier (for example: SSAID, MAC address, IMEI, etc.,) + without the explicit consent of the user.” +

+ +

+ As an example, suppose you want to collect information to populate database + tables with the following columns: +

+ + + + + + +
+ + + + + + + +
+ timestamp + ad_id + account_id + clickid
+ +

TABLE-01

+
+ + + + + + + +
+ account_id + name + dob + country
+

TABLE-02

+
+ + +

+ In this example, the ad_id column could be joined to PII via the + account_id column in both tables, which would be a violation of + the Google Play + Developer Content Policy. +

+ +

+ Keep in mind that links between Advertiser ID and PII aren't always this + explicit. It's possible to have “quasi-identifiers” that appear in both PII + and Ad ID keyed tables, which also cause problems. For example, assume we + change TABLE-01 and TABLE-02 as follows: +

+ + + + + + +
+ + + + + + +
+ timestamp + ad_id + clickid + dev_model
+ + +

TABLE-01

+
+ + + + + + + + +
+ timestamp + demo + account_id + dev_model + name
+

TABLE-02

+
+ + +

+ In this case, with sufficiently rare click events, it's still possible to + join between the Advertiser ID TABLE-01 and the PII contained in TABLE-2 + using the timestamp of the event and the device model. +

+ +

+ While it is often difficult to guarantee that no such quasi-identifiers exist + in a dataset, the most obvious join risks can be prevented by generalizing + unique data where possible. In the example, this would mean reducing the + accuracy of the timestamp so that multiple devices with the same model appear + for every timestamp. +

+ +

+ Other solutions include: +

+ + + +

+ For more information on working responsibly with Advertising IDs, please see + the + Advertising ID help center article. +

+ +

Working with Instance IDs and GUIDs

+ +

+ The most straightforward solution to identifying an application instance + running on a device is to use an Instance ID, and this is the recommended + solution in the majority of non-ads use-cases. Only the app instance for + which it was provisioned can access this identifier, and it's (relatively) + easily resettable because it only persists as long as the app is installed. +

+ +

+ As a result, Instance IDs provide better privacy properties compared to + non-resettable, device-scoped hardware IDs. They also come with a key-pair + for message signing (and similar actions) and are available on Android, iOS + and Chrome. Please see the What is Instance ID? help + center document for more information. +

+ +

+ In cases where an Instance ID isn't practical, custom globally unique IDs + (GUIDs) can also be used to uniquely identify an app instance. The simplest + way to do so is by generating your own GUID using the following code. +

+ +
String uniqueID = UUID.randomUUID().toString();
+ +

+ Because the identifier is globally unique, it can be used to identify a + specific app instance. To avoid concerns related to linking the identifier + across applications, GUIDs should be stored in internal storage rather than + external (shared) storage. Please see Storage Options guide for + more information. +

+ + +

Understanding Identifier Characteristics

+ +

+ The Android Operating system offers a number of IDs with different behavior + characteristics and which ID you should use depends on how those following + characteristics work with your use-case. But these characteristics also come + with privacy implications so it's important to understand how these + characteristics play together. +

+ +

Scope

+ +

+ Identifier scope explains which systems can access the identifier. Android + identifier scope generally comes in three flavors: +

+ + + +

+ The wider the scope granted to an identifier, the greater the risk of it + being used for tracking purposes. Conversely, if an identifier can only be + accessed by a single app instance, it can’t be used to track a device across + transactions in different apps. +

+

Resettability and persistence

+ +

+ Resettability and persistence define the lifespan of the identifier and + explain how it can be reset. Common reset triggers are: in-app resets, resets + via System Settings, resets on launch, and resets on installation. Android + Identifiers can have varying lifespans, but the lifespan is usually related + to how the ID is reset: +

+ + +

+ Resettability gives users the ability to create a new ID that is + disassociated from any existing profile information. This is important + because the longer, and more reliably, an identifier persists (e.g. across + factory resets etc.), the greater the risk that the user may be subjected to + long-term tracking. If the identifier is reset upon app reinstall, this + reduces the persistence and provides a means for the ID to be reset, even if + there is no explicit user control to reset it from within the app or the + System Settings. +

+

Uniqueness

+ +

+ Uniqueness establishes the likelihood that identical identifiers exist within + the associated scope. At the highest level, a globally unique identifier will + never have a collision - even on other devices/apps. Otherwise, the level of + uniqueness depends on the size of the identifier and the source of randomness + used to create it. For example, the chance of a collision is much higher for + random identifiers seeded with the calendar date of installation (e.g., + 2015-01-05) than for identifiers seeded with the Unix timestamp of + installation (e.g., 1445530977). +

+ +

+ In general, user account identifiers can be considered unique (i.e., each + device/account combo has a unique ID). On the other hand, the less the unique + an identifier is within a population (e.g. of devices), the greater the + privacy protection because it's less useful for tracking an individual user. +

+ +

Integrity protection and +non-repudiability

+ +

+ An identifier that is difficult to spoof or replay can be used to prove that + the associated device or account has certain properties (e.g. it’s not a + virtual device used by a spammer). Difficult to spoof identifiers also + provide non-repudiability. If the device signs a message with a + secret key, it is difficult to claim someone else’s device sent the message. + Non-repudiability could be something a user wants (e.g. authenticating a + payment) or it could be an undesirable property (e.g. sending a message they + regret). +

+ + +

Common Use Cases and the Identifier to Use

+ +

+ This section provides alternatives to using hardware IDs such as IMEI or + SSAID for the majority of use-cases. Relying on hardware IDs is discouraged + because the user cannot reset them and generally has limited control over + their collection. +

+ +

Tracking signed-out user preferences

+ +

+ In this case, you are saving per-device state on the server side. +

+ +

+ We Recommend: Instance ID or a GUID. +

+ +

+ Why this Recommendation? +

+ +

+ Persisting information through reinstalls is not recommended because users + may want to reset their preferences by reinstalling the app. +

+ +

Tracking signed-out user behavior

+ +

+ In this case, you have created a profile of a user based on their + behavior across different apps/sessions on the same device. +

+ +

+ We Recommend: Advertising ID. +

+ +

+ Why this Recommendation? +

+ +

+ Use of the Advertising ID is mandatory for Advertising use-cases per the + Google + Play Developer Content Policy because the user can reset it. +

+ +

Generating signed-out/anonymous user analytics

+ +

+ In this case, you are measuring usage statistics and analytics for + signed-out or anonymous users. +

+ +

+ We Recommend: Instance ID; if an Instance ID is + insufficient, you can also use a GUID. +

+ +

+ Why this Recommendation? +

+ +

+ An Instance ID or a GUID is scoped to the app that creates it, which prevents + it from being used to track users across apps. It is also easily reset by + clearing app data or reinstalling the app. Creating Instance IDs and GUIDs is + straightforward: +

+ + + +

+ Be aware that if you have told the user that the data you are collecting is + anonymous, you should ensure you are not connecting the + identifier to PII or other identifiers that may be linked to + PII. +

+ +

+ You can also use Google Analytics for Mobile Apps, which offers a solution + for per-app analytics. +

+ +

Tracking signed-out user conversion

+ +

+ In this case, you are tracking conversions to detect if your marketing + strategy was successful. +

+ +

+ We Recommend: Advertising ID. +

+ +

+ Why this Recommendation? +

+ +

+ This is an ads-related use-case which may require an ID that is available + across different apps so using an Advertising ID is the most appropriate + solution. +

+ +

Handling multiple installations

+ +

+ In this case, you need to identify the correct instance of the app when + it's installed on multiple devices for the same user. +

+ +

+ We Recommend: Instance ID or GUID. +

+ +

+ Why this Recommendation? +

+ +

+ Instance ID is designed explicitly for this purpose; its scope is limited to + the app so that it cannot be used to track users across different apps and it + is reset upon app reinstall. In the rare cases where an Instance ID is + insufficient, you can also use a GUID. +

+ +

Anti-fraud: Enforcing free content limits / detecting Sybil attacks

+ +

+ In this case, you want to limit the number of free content (e.g. + articles) a user can see on a device. +

+ +

+ We Recommend: Instance ID or GUID. +

+ +

+ Why this Recommendation? +

+ +

+ Using a GUID or Instance ID forces the user to reinstall the app in order to + overcome the content limits, which is a sufficient burden to deter most + people. If this is not sufficient protection, Android provides a + DRM API + which can be used to limit access to content. +

+ +

Managing telephony and carrier functionality

+ +

+ In this case, your app is interacting with the device's phone and texting + functionality. +

+ +

+ We Recommend: IMEI, IMSI, and Line1. +

+ +

+ Why this Recommendation? +

+ +

+ Leveraging hardware identifiers is acceptable if it is required for + telephony/carrier related functionality; for example, switching between + cellular carriers/SIM slots or delivering SMS messages over IP (for Line1) - + SIM-based user accounts. But it's important to note that in Android 6.0+ + these identifiers can only be used via a runtime permission and that users + may toggle off this permission so your app should handle these exceptions + gracefully. +

+ +

Abuse detection: +Identifying bots and DDoS attacks

+ +

+ In this case, you are trying to detect multiple fake devices attacking + your backend services. +

+ +

+ We Recommend: The Safetynet API. +

+ +

+ Why this Recommendation? +

+ +

+ An identifier in isolation does little to indicate that a device is genuine. + You can verify that a request comes from a genuine Android device (as opposed + to an emulator or other code spoofing another device) using the Safetynet + API's SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce) + method to verify the integrity of a device making a request. For more + detailed information, please see Safetynet's API documentation. +

+ +

Abuse detection: +Detecting high value stolen credentials

+ +

+ In this case, you are trying to detect if a single device is being used + multiple times with high-value, stolen credentials (e.g. to make fraudulent + payments). +

+ +

+ We Recommend: IMEI/IMSI (requires PHONE + permission group in Android 6.0 (API level 23) and higher.) +

+ +

+ Why this Recommendation? +

+ +

+ With stolen credentials, devices can be used to monetize multiple high value + stolen credentials (such as tokenized credit cards). In these scenarios, + software IDs can be reset to avoid detection, so hardware identifiers may be + used. +

\ No newline at end of file diff --git a/docs/html/training/articles/user-data-overview.jd b/docs/html/training/articles/user-data-overview.jd new file mode 100644 index 0000000000000..109826af0659f --- /dev/null +++ b/docs/html/training/articles/user-data-overview.jd @@ -0,0 +1,266 @@ +page.title=Permissions and User Privacy +page.metaDescription=An overview of permissions on Android and how to manage them. +page.tags="user data","permissions","identifiers" +page.image=images/cards/card-user_2x.png + +page.article=true +@jd:body + +
+
+

In this document

+
    +
  1. Introduction
  2. +
  3. Permission Groups
  4. +
  5. Permission + Requests and App Downloads
  6. +
  7. Permission Requests + Trend Downward
  8. +
+

You should also read

+
    +
  1. System Permissions
  2. +
  3. Working with System + Permissions
  4. +
+
+
+ +

+ Permissions protect sensitive information available from a device and should + only be used when access to information is necessary for the functioning of + your app. +

+ +

+ This document provides a high-level overview on how permissions work in + Android so you can make better, more informed decisions about the permissions + you're requesting. The information in this document is not use-case specific + and avoids complex, low-level discussions of the underlying code. +

+ +

+ For specific recommendations on how to manage permissions, please see + Best + Practices for App Permissions. For best practices on using unique + identifiers on Android, please see Best Practices for Unique + Identifiers. For details on how to work with permissions in your code, + see Working with System + Permissions. +

+ + +

Introduction

+ +

+ Every Android application must have a manifest file that presents + essential information about the app to the Android system. The Android system + also requires apps to request permission when they want to access sensitive + device or user information, and these requests must be documented in advance + as a part of your app's manifest. Moreover, accessing sensitive information + can affect user behavior, so it's important to make sure you are only making + permission requests when that information is necessary for the functioning of + your app. +

+ + +

Permission Groups

+ +

+ Permissions in Android are organized into permission + groups that organize, and group, permissions related to a device's + capabilities or features. Under this system, permission requests are handled + at the group level and a single permission group + corresponds to several permission declarations in + the app manifest; for example, the SMS group includes both the + READ_SMS and the WRITE_SMS declarations. +

+ + +
+ +
+ +

+ This arrangement is simpler and more informative for users; once an app is + granted permission to access the group, it can use API calls within that + group and users with auto-update enabled will not be asked for additional + permissions because they have already granted access to the group. Grouping + permissions in this way enables the user to make more meaningful and informed + choices, without being overwhelmed by complex and technical permission + requests. +

+ +

+ This also means that when you request access to a particular API call or + query a content provider behind a permission, the user will be presented with + a request to grant permission for the whole group rather than the specific + API call. For example, if you request the MANAGE_ACOUNTS + permission, the user will be asked to grant access to the Identity + group which is composed of the GET_ACCOUNTS, + READ_PROFILE, and WRITE_PROFILE permissions, and + all their associated methods. +

+ +
+ +
+ +

+ One consequence of grouping permissions is that a single API call within your + app can have a multiplying effect in terms of the number of permissions + requested by your app. +

+ +
    +
  1. API Call →
  2. +
  3. Triggers a specific Permission Group access +request →
  4. +
  5. Successful request grants access to all permissions in +group (if auto-update +enabled) →
  6. +
  7. Each permission grants access to all APIs under that +permission
  8. +
+ +

+ As another example, let's assume your application uses one or more TelephonyManager + methods, such as: +

+ +
+TelephonyManager.getDeviceId()
+TelephonyManager.getSubscriberId()
+TelephonyManager.getSimSerialNumber()
+TelephonyManager.getLine1Number()
+TelephonyManager.getVoiceMailNumber()
+
+ +

+ To use these methods, the READ_PHONE_STATE permission must be + declared in the app's manifest, and the associated permission group, + Device ID and Call information, will be surfaced to the user. This + is important, because it means the user will be asked to grant permission for + the relevant group and all its associated permissions and API calls, rather + than for the specific API call you're requesting. +

+ +

For a full mapping between permissions and their associated permission groups, +please refer to the appropriate version-specific documentation below:

+ + + + +

Permission Requests and App Downloads

+ +
+
+

I'm currently using the READ_PHONE_STATE permission in Android to pause my +media player when there's a call, and to resume playback when the call is over. +The permission seems to scare a lot of people...1

+
+
+ +

+ Research shows that among apps that are otherwise identical (e.g., + functionality, brand recognition), requesting fewer permissions leads to more + downloads. Publicly available sources exist that assign grades to apps based + on their permissions usage and allow users to compare related apps by score; + such grades exist for many of the current Android apps and users pay close + attention to the related rankings. +

+ +

+ One study2, in which users + were shown two unbranded apps with similar ratings that had the same + functionality but different sets of permission requests, showed that users + were, on average, 3 times more likely to install the app with fewer + permissions requests. And a similar study3 showed that users are 1.7 + times more likely, on average, to select the application with fewer + permission requests. +

+ +

+ Finally, permissions usage is not evenly distributed across apps within + a similar category of Play apps. For example, 39.3% of arcade game apps in + the Play store request no permissions that are surfaced to the user while + only 1.5% of arcade games request the Phone permission group (see Figure + 1). +

+ +
+
+
+ +

Figure 1. Distribution of + permission groups use across Arcade Games category.

+
+
+
+ +

+ Users comparing your app to other similar apps may determine that it is + making unusual permission requests for that category - in this case, Arcade + Games apps accessing the Phone permission group. As a result, they + may install a similar app in that category that avoids those + requests.4 +

+ + +

Permission Requests Trend Downward

+ +

+ A recent analysis of Play store apps over time indicated that many developers + trim permissions after first publishing their apps, suggesting that they may + be employing more caution around which permission groups they declare. +

+ +
+
+
+ +

Figure 2. Developer usage of popular + permissions has decreased over time.

+
+
+
+ +

+ The graph in Figure 2 illustrates this trend. There has been a + steady decrease in the average percentage of developers' apps requesting at + least one of the three most popular permissions in the Play store + (READ_PHONE_STATE, ACCESS_FINE_LOCATION, and + ACCESS_COARSE_LOCATION). These results indicate that developers + are reducing the permissions their apps request in response to user behavior. +

+ +

+ The bottom line is that providing the same functionality to the user with + minimal access to sensitive information means more downloads for your app. + For specific recommendations on how to achieve this, please see Best Practices for + Application Permissions. +

+ + +

References

+ +

[1] Developer quote on StackOverflow. (source)

+

[2] Using Personal Examples to Improve Risk Communication for Security and Privacy Decisions, by M. Harbach, M. Hettig, S. Weber, and M. Smith. In Proceedings of ACM CHI 2014.

+

[3] Modeling Users’ Mobile App Privacy Preferences: Restoring Usability in a Sea of Permission Settings, by J. Lin B. Liu, N. Sadeh and J. Hong. In Proceedings of SOUPS 2014.

+

[4] Teens and Mobile Apps Privacy. (source)

diff --git a/docs/html/training/articles/user-data-permissions.jd b/docs/html/training/articles/user-data-permissions.jd new file mode 100644 index 0000000000000..99f14b996bf3d --- /dev/null +++ b/docs/html/training/articles/user-data-permissions.jd @@ -0,0 +1,381 @@ +page.title=Best Practices for App Permissions +page.metaDescription=How to manage permissions to give users context and control. +page.tags=permissions, user data +meta.tags="permissions", "user data" +page.image=images/cards/card-user-permissions_2x.png + +page.article=true +@jd:body + +
+
+

In this document

+
    +
  1. Tenets
  2. +
  3. Permissions in Android + 6.0+
  4. +
  5. Avoid Requesting +Unnecessary Permissions +
      +
    1. Camera/Contact + access with realtime user requests
    2. +
    3. Running in +the background after losing audio focus
    4. +
    5. Determine the +device your instance is running on
    6. +
    7. +Create a unique identifier for advertising or user analytics
    8. +
    +
  6. +
  7. Know the Libraries You're +Working With
  8. +
  9. Be Transparent
  10. +
+

You should also read

+
    +
  1. System Permissions
  2. +
  3. Working with System + Permissions
  4. +
+
+
+ +

+ Permission requests protect sensitive information available from a device and + should only be used when access to information is necessary for the + functioning of your app. This document provides tips on ways you might be + able to achieve the same (or better) functionality without requiring access + to such information; it is not an exhaustive discussion of how permissions + work in the Android operating system. +

+ +

+ For a more general look at Android permissions, please see Permissions + and User Privacy. For details on how to work with permissions in your code, + see Working with System Permissions. + For best practices for working with unique identifiers, please see Best Practices for + Unique Identifiers. +

+ +

Tenets of Working +with Android Permissions

+ +

+ We recommend following these tenets when working with Android permissions: +

+ +

+ #1: Only use the permissions necessary for your app to + work. Depending on how you are using the permissions, there may + be another way to do what you need (system intents, identifiers, + backgrounding for phone calls) without relying on access to sensitive + information. +

+ +

+ #2: Pay attention to permissions required by + libraries. When you include a library, you also inherit its + permission requirements. You should be aware of what you're including, the + permissions they require, and what those permissions are used for. +

+ +

+ #3: Be transparent. When you make a permissions + request, be clear about what you’re accessing, and why, so users can make + informed decisions. Make this information available alongside the permission + request including install, runtime, or update permission dialogues. +

+ +

+ #4: Make system accesses explicit. Providing + continuous indications when you access sensitive capabilities (for example, the + camera or microphone) makes it clear to users when you’re collecting data and + avoids the perception that you're collecting data surreptitiously. +

+ +

+ The remaining sections of this guide elaborate on these rules in the context + of developing Android applications. +

+ +

Permissions in Android 6.0+

+ +

+ Android 6.0 Marshmallow introduced a new permissions model that + lets apps request permissions from the user at runtime, rather than prior to + installation. Apps that support the new model request permissions when the app + actually requires the services or data protected by the services. While this + doesn't (necessarily) change overall app behavior, it does create a few + changes relevant to the way sensitive user data is handled: +

+ +

+ Increased situational context: Users are be + prompted at runtime, in the context of your app, for permission to access the + functionality covered by those permission groups. Users are be more sensitive to + the context in which the permission is requested, and if there’s a mismatch + between what you are requesting and the purpose of your app, it's even + more important to provide detailed explanation to the user as to why you’re + requesting the permission; whenever possible, you should provide an + explanation of your request both at the time of the request and in a + follow-up dialog if the user denies the request. +

+ +

+ Greater flexibility in granting permissions: Users + can deny access to individual permissions at the time they’re requested + and in settings, but they may still be surprised when functionality is + broken as a result. It’s a good idea to monitor how many users are denying + permissions (e.g. using Google Analytics) so that you can either refactor + your app to avoid depending on that permission or provide a better + explanation of why you need the permission for your app to work properly. You + should also make sure that your app handles exceptions created when users + deny permission requests or toggle off permissions in settings. +

+ +

+ Increased transactional burden: Users will be asked + to grant access for permission groups individually and not as a set. This + makes it extremely important to minimize the number of permissions you’re + requesting because it increases the user burden for granting permissions and + increases the probability that at least one of the requests will be denied. +

+ +

Avoid Requesting +Unnecessary Permissions

+ +

+ This section provides alternatives to common use-cases that will help you + limit the number of permission requests you make. Since the number and type + of user-surfaced permissions requested affects downloads compared to other + similar apps requesting fewer permissions, it’s best to avoid requesting + permissions for unnecessary functionality. +

+ +

Camera/contact +access with realtime user requests

+ +

+ In this case, you need occasional access to the device's camera or + contact information and don’t mind the user being asked every time you need + access. +

+ +

+ If your requirement for access to user data is infrequent — in other + words, it's not unacceptably disruptive for the user to be presented with a + runtime dialogue each time you need to access data — you can use an + intent based request. Android provides system intents that + applications can use without requiring permissions because the user chooses + what, if anything, to share with the app at the time the intent based request + is issued. +

+ +

+ For example, an intent action type of MediaStore.ACTION_IMAGE_CAPTURE + or MediaStore.ACTION_VIDEO_CAPTURE + can be used to capture images or videos without directly using the Camera object (or + requiring the permission). In this case, the system intent will ask for the + user’s permission on your behalf every time an image is captured. +

+ +

Running in +the background after losing audio focus

+ +

+ In this case, your application needs to go into the background when the + user gets a phone call and refocus only once the call stops. +

+ +

+ The common approach in these cases - for example, a media player muting or + pausing during a phone call - is to listen for changes in the call state + using PhoneStateListener or listening for the broadcast of + android.intent.action.PHONE_STATE. The problem with this + solution is that it requires the READ_PHONE_STATE permission, + which forces the user to grant access to a wide cross section of sensitive + data such as their device and SIM hardware IDs and the phone number of the + incoming call. +

+ +

+ You can avoid this by requesting AudioFocus for your app, which + doesn't require explicit permissions (because it does not access sensitive + information). Simply put the code required to background your audio in the + + onAudioFocusChange() event handler and it will run automatically + when the OS shifts its audio focus. More detailed documentation on how to do + this can be found here. +

+ +

Determine the +device your instance is running on

+ +

+ In this case, you need a unique identifier to determine which device the + instance of your app is running on. +

+ +

+ Applications may have device-specific preferences or messaging (e.g., saving + a device-specific playlist for a user in the cloud so that they can have a + different playlist for their car and at home). A common solution is to + leverage device identifiers such as Device IMEI, but this + requires the Device ID and call information + permission group (PHONE in M+). It also uses an identifier which + cannot be reset and is shared across all apps. +

+ +

+ There are two alternatives to using these types of identifiers: +

+ +
    +
  1. Use the com.google.android.gms.iid InstanceID API. + getInstance(Context context).getID() will return a + unique device identifier for your application instance. The +result is an app instance scoped identifier that can be used as a key when +storing information about the app and is reset if the user re-installs the app. +
  2. Create your own identifier that’s scoped to your app’s storage using basic + system functions like randomUUID().
  3. +
+ +

Create a unique +identifier for advertising or user analytics

+ +

+ In this case, you need a unique identifier for building a profile for + users who are not signed in to your app (e.g., for ads targeting or measuring + conversions). +

+ +

+ Building a profile for advertising and user analytics sometimes requires an + identifier that is shared across other applications. Common solutions for + this involve leveraging device identifiers such as Device IMEI, + which requires the Device ID and call information + permission group (PHONE in API level 23+) and cannot be reset by + the user. In any of these cases, in addition to using a non-resettable + identifier and requesting a permission that might seem unusual to users, you + will also be in violation of the Play Developer + Program Policies. +

+ +

+ Unfortunately, in these cases using the + com.google.android.gms.iid InstanceID API or system functions to + create an app-scoped ID are not appropriate solutions because the ID may need + to be shared across apps. An alternative solution is to use the + Advertising Identifier available from the + AdvertisingIdClient.Info class via the getId() + method. You can create an AdvertisingIdClient.Info object using + the getAdvertisingIdInfo(Context) method and call the + getId() method to use the identifier. Note that this + method is blocking, so you should not call it from the main + thread; a detailed explanation of this method is available here. +

+ +

Know the Libraries You're +Working With

+ +

+ Sometimes permissions are required by the libraries you use in your app. For + example, ads and analytics libraries may require access to the + Location or Identity permissions groups to + implement the required functionality. But from the user’s point of view, the + permission request comes from your app, not the library. +

+ +

+ Just as users select apps that use fewer permissions for the same + functionality, developers should review their libraries and select + third-party SDKs that are not using unnecessary permissions. For example, try + to avoid libraries that require the Identity permission group + unless there is a clear user-facing reason why the app needs those permissions. + In particular, for libraries that provide location functionality, make sure you + are not required to request the FINE_LOCATION permission unless + you are using location-based targeting functionality. +

+ +

Be Transparent

+ +

You should inform your users about what you’re accessing and why. Research shows +that users are much less uncomfortable with permissions requests if they know +why the app needs them. A user study showed that:

+ +
+
+

...a user’s willingness to grant a given permission to a given mobile app is +strongly influenced by the purpose associated with such a permission. For +instance a user’s willingness to grant access to his or her location will vary +based on whether the request is required to support the app’s core +functionality or whether it is to share this information with an advertising +network or an analytics company.1

+
+
+ +

+ Based on his group’s research, Professor Jason Hong from CMU concluded that, + in general: +

+ +
+
+

...when people know why an app is using something as sensitive as their location — +for example, for targeted advertising — it makes them more comfortable than +when simply told an app is using their location.1

+
+
+ +

+ As a result, if you’re only using a fraction of the API calls that fall under + a permission group, it helps to explicitly list which of those permissions + you're using, and why. For example: +

+ + + +

+ Under certain conditions, it's also advantageous to let users know about + sensitive data accesses in real-time. For example, if you’re accessing the + camera or microphone, it’s usually a good idea to let the user know with a + notification icon somewhere in your app, or in the notification tray (if the + application is running in the background), so it doesn't seem like you're + collecting data surreptitiously. +

+ +

+ Ultimately, if you need to request a permission to make something in your app + work, but the reason is not clear to the user, find a way to let the user + know why you need the most sensitive permissions. +

+ +

References

+ +

+ [1] Modeling Users’ Mobile App Privacy Preferences: Restoring Usability + in a Sea of Permission Settings, by J. Lin B. Liu, N. Sadeh and J. Hong. + In Proceedings of SOUPS 2014. +

diff --git a/docs/html/training/best-permissions-ids.jd b/docs/html/training/best-permissions-ids.jd new file mode 100644 index 0000000000000..e98c0953ddfa7 --- /dev/null +++ b/docs/html/training/best-permissions-ids.jd @@ -0,0 +1,9 @@ +page.title=Best Practices for Permissions and Identifiers +page.trainingcourse=true + +@jd:body + + + +

The articles below highlight key guidelines for using permissions +and identifiers properly in your apps.

\ No newline at end of file diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 9e156d0821d3b..5ebb298dc349c 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -2083,6 +2083,36 @@ results." + + +