FRED CHUNG: Hi I'm Fred.
Privacy, a focus area on Android.
And it's been evolving over the last several releases.
The scope of these changes includes updates
for users and developers.
In this presentation, we'll cover some user-facing changes.
But we'll focus primarily on developer issues,
such as new APIs, behavior changes, and testing.
There are several things that drive Android's privacy design.
We wanted to give users control on when and how much
of their data is shared.
At the same time, it's important to provide
transparency through the system and in app UIs. For developers,
we wanted to provide some guardrails to help you design
your apps, such that they only access the least
amount of data needed for the use case or data minimization.
In Android 11, we've continued to innovate
in areas like permissions, storage, and access
to installed packages.
We also added some new APIs to help you identify potentially
unexpected data usage.
Now, let's start with one-time permission.
When users are given a choice, they
are choosing to share less private data with apps.
We also saw that there are apps that request background
locations access with no need for it or don't explain why.
The results-- one-star ratings like this.
So we asked our users, apart from location data,
what other types of data are important to them.
Based on the feedback, in Android 11,
we are bringing users more granular control
over users private data--
location, camera, and microphone.
And we also are significantly limiting access
to background location.
Now, you may have this very important question in mind.
Well, generally, we don't need to make any changes to your app
to work with one-time permission.
Well, assuming you are already currently following
Android permission best practices.
Let's have a look at an example.
Let's say we have a messaging app.
This code snippet follows permission request
best practice, which applies to any one-time permissions.
When the user taps on the location sharing button,
a few things happen.
First, we check if the permission is granted.
When this is first run it isn't.
Next, we let the system decide if the app could show
an in-context UI explanation.
Normally, but not always the first time
the system will consider that it's not needed.
In that case, the app requests a location permission.
This prompts a system dialog offering the user
three options.
Let's say the user selects Deny.
Then, you'll receive a callback here.
Since the request was denied, you
should make sure to explain which
functionality within your app won't
work because of that decision.
In this case, we could show an explanation, for example,
in a snack bar to indicate that the functionality isn't
available.
Android 10 introduced granular foreground and background
location permissions.
Most location use cases can be done with foreground only.
You could just request coarse or perhaps, fine location
if needed.
If background location is really needed for your use case,
it's good practice to incrementally request
permissions to give users a chance to understand and decide
based on context.
You should first ask for foreground location.
When they user interacts with a feature that
requires background location, you
could display an optional in-app UI explaining the reason
for needing the permission.
It is strongly recommended that the UI
is shown based on the result of should show permission request
rationale API.
When your app requests background location permission,
the request permissions API will send the user directly
to the settings instead of the regular permission request
dialogues.
It is also important to note that the in-app rationale
UI in the middle should include both positive and negative
actions where users can deny the request because the settings
screen is rate limited.
The requestPermissions API takes a string array of permissions
as an input parameter.
In your existing code, you may already
have a pattern like this where foreground and background
permissions are requested together.
If your target API level is 30 or above,
the app must follow the best practice
to request foreground and background
locations separately.
Otherwise, the API will ignore the entire batch of permissions
included in the call.
So this is something to keep in mind.
If an app hasn't been used by the user for several months,
Android 11 will reset your app's permissions
as if the user has denied your apps
permissions in app settings.
No change is needed generally.
Just check for permissions before accessing sensitive data
requests if you don't already have them.
Also, this will only affect apps with a target API level of 30.
Most apps don't need this.
But there are certain cases where
the users expect the app to primarily work
in the background.
You could consider using this action
to redirect a user to the app's details
setting screen to toggle auto resets for the app.
And now, let's talk about a new support for apps
to discover potentially unintended access
to private data.
Sometimes, you may be wondering why your app accesses
certain pieces of data.
However, that's not always clear.
So what are the challenges?
Launch apps often have some orphan code,
and they may have large teams.
Accidental data access can happen.
Any apps may use closed-source third-party SDKs.
These libraries might access private data
without knowledge of the developer
by piggybacking on top of already granted private data
access.
For these cases, data access may or may not be intended,
and it's not always easy to identify.
Data Access API in Android 11 helps
provides transparency to this.
Whenever an app cause an API that returns private data,
the system calls into a collection handler
immediately before returning to the calling code.
So the Handler can collect a stack trace, for example,
to record which code to perform the access.
Let's look at the API.
This shows how to set up a callback for data access
through the AppOpsManager class.
If you want to consistently track it for the entire app,
you can set it up within application onCreate.
Let's say you want to localize it
to a particular part of your app.
You could do it within activity onCreate.
Within the callback class, your app
will be notified of data access in synchronous API calls.
When this happens, you may log to stack trace, as I mentioned.
It also works for asynchronous API access.
Check out the API reference for more detail.
More complex apps often contains multiple features.
For example, a mapping app might provide a navigation,
explore nearby shopping, and find friend features.
In Android 11, it allows for an app
to attribute data access to a particular feature of an app.
Each of the features may use a subset of private data.
For example, the find friends feature might not
need to use the microphone.
Mapping data access to a higher level of abstraction
makes it easier to find what features have accidental data
access.
Further, this will make it easier
to explain to the user what private data is used for.
Let's see how the API works.
To attribute features in your code,
create an attributionContext and give it a meaningful name that
corresponds to your feature.
For example, "find_friends," then
you can pass the context to an API call.
Within the callback, you can recover the attribute
through the attribute tag variable.
Then, you can, for example track the attribute
within your analytics solution and associate
a particular feature with the private data access.
Foreground services are usually used
to implement ongoing tasks, such as downloading large files.
There are battery implications, and you
should use them judiciously.
To provide better accountability for apps
to access private data in foreground service,
the platform relies on foreground
service-type attribute in a manifest.
The attribute was introduced in Android 10.
There were a few defined types the OS.
Apps can declare their intentions
to access this information within their foreground
services.
One of the enforced types is location.
In Android 11, there's a couple of new types, camera,
and microphone.
Since Android 9, apps can no longer
access the camera and mic in the background.
So for quite some time, this can only be done in the foreground.
If your app targets Android 11, it additionally needs
to declare the new types, or else,
the foreground service cannot receive related data.
Here's the manifest entry for the camera type.
If the foreground service needs to access different data,
you can declare them together like this.
To recap, on Android 11, if you need to use a foreground
service to access any of this data,
you must declare the corresponding foreground
service type in the manifest.
To provide better accountability for access
to installed apps on a device, Android 11
includes some changes to how apps can query and interact
with other packages.
For several common scenarios, you
don't need to make any changes.
Let's have a look.
If you target Android 11, you can still
use this package manager API to get the package info
for your own app, as expected.
Now, this API will return only the calling
app in certain system packages, such as the media provider that
implements core Android functionality.
If you sent an implicit intent for another app to take action,
for example, use the image_capture intent
to take a picture using the preinstalled camera app.
In this scenario, another app calls your app's content
provider and expects results.
Without making any changes, your app
can query and interact with the requesting app.
Besides the scenarios we just discussed, by default,
your app will return NameNotFound exception
regardless of whether the specified package is installed.
Let's go through a few cases and ways to handle them.
If you need to explicitly interact with another app,
for example bind or service, use the new elements in a manifest
to explicitly specify the packages your app needs
to query or interact with.
You could include multiple entries as shown here.
Or you can do this implicitly through an intent filter
signature.
The app can now query for all apps
that handle an action sent intent for JPEG images.
Likewise, if your app needs to access another app's content
provider, you could specify its authorities like this.
In practice, we found that most apps can easily
express necessary package interactions
with the declarations we just saw.
However, the system also provides query or packages
permission, which would allow certain use cases
to read all installed packages.
Look for upcoming guidance from Google Play for apps
that need this permission.
Sometimes, if an app sends a view intent with a certain URL,
you may want to take the user directly
to the default native app instead of a web browser.
If you just did this, your user may get a disambiguation dialog
box, not the most direct way.
On Android 11, there's a couple of new intent flags
that could make this smoother.
The first one is called ACTIVITY REQUIRE REQUIRE NON BROWSER.
It ensures that the intent is only handled
by the default native app.
If one isn't available on a device,
it will result in an ActivityNotFoundException.
In the exception handle, you can choose
to take over handling the intent.
For example, display the URL in a Chrome tab within your app.
There's another similar intent flag called activity required
default. It ensures that there must be one default app that
can handle the view intent, else,
it will also result in the same exception
so you can override the experience for your users.
Let's look at a scenario related to sharing a content
provider with another app.
You should ensure that the receiving
app has visibility to the data by explicitly setting the read
and/or write URI permissions.
To conclude this section, I'm sharing an ADB
diagnostic command to verify if your app is
impacted by this change.
Check it out.
Many apps rely on shared storage.
So let's talk about that.
Before Android 10, there were two classifications
of external storage--
app storage and shared storage.
Any apps with storage permission had access
to all shared storage content.
This is regardless if you only need
to access your app-specific files or those
that belong to others.
And users notice.
In order to better demarcate external storage access,
Android 10 scoped storage changed this
by adding distinction between media
files and other documents.
Rather than apps gaining access to all files in shared storage,
they now only have access to media files by default.
In order to gain access to documents
which could potentially contain more sensitive data,
the app needs to ask the user to grant access specifically
to those documents.
I've listed a summary of scoped storage changes in Android 10
here.
From early feedback, developers told us
they need more time to migrate, which makes sense.
We responded to that by supporting a temporary opt-out
via the requestLegacyExternalStorage
manifest attribute.
Android 11 improves upon scoped storage in a number of ways.
Let's have a look.
First, we've made further adjustments
to storage permissions.
We've also updated the user consent
flow for modifying media.
You can batch multiple edit or delete requests in one dialog.
Let's have a look at the API.
You can specify a list of URIs representing the media files
that need editing.
Then, you create a PendingIntent for the write request.
Then, pass it into the startIntentSenderForResult API
and the system will show a constant dialogue
that looks like this.
Finally, if the user grants access,
you'll be able to edit related media files
upon receiving a callback.
Many apps use the storage access framework for users
to select files.
There's a couple of changes to it as well.
The OPEN_DOCUMENT_TREE intent action
gives app access to a folder structure selected by the user.
To better restrict access to only the files you need,
your user can no longer access several locations
in a document's UI that are considered too broad
or may contain files created by other applications.
They include the root download an app-specific data and obb
folders.
Similarly, through the OPEN_DOCUMENT intent action,
users won't be able to select files
from again, app-specific data and obb directories.
Our general guidance for accessing media files
is through the MediaStore, because it
lets the system better manage file access
and it's more performant.
So in Android 10, direct file path access was restricted.
However, many developers told us that this isn't always
possible, which we can understand.
For example, this is important for apps using
third-party media libraries.
In response, we are enabling this in Android 11.
File path access for media provides
a native file-like interface to MediaStore
to allow apps and libraries to continue using file
APIs to access media content.
If this is something your app needs,
the recommended approach is to opt out of scoped storage
with a manifest flag on Android 10.
That would give your app a uniform way
of dealing with file paths across different versions.
You can check out details on storage best practice here.
While most use cases can follow these best practices,
certain use cases may still need broad access
to files on external storage.
In Android 11, apps can declare manage external storage
permission, which will allow them
to request the user to grant them
all files access in Settings.
This is designed to enable specifically
use cases such as file managers, backup and restore, or document
management apps.
Look for Google Play to provide guidelines
for apps that can use this permission.
We just cover quite a few privacy improvements
and best practices.
Android privacy is designed to offer better control,
transparency, and help developers
use data responsibly.
If you want to learn more about building privacy-friendly apps,
check out our resources here.
Thank you.