"Elements of Android R" Version 0.1 Released
Subscribers now have
access to Version 0.1 of Elements of Android R,
in PDF, EPUB, and MOBI/Kindle formats. Just log into
your Warescription page to download it,
or set up an account and subscribe!
As with last year’s Elements of Android Q,
this will be a small book, focusing on the changes introduced by Android R.
This first version covers a fair bit of ground, including:
- Changes to scoped storage,
MediaStore, and permissions
- Data access auditing and application exit auditing
- The new package visibility restrictions
- Sharing UIs between apps using
As new developer preview releases of R roll out, I will add more chapters plus update the
existing ones to reflect any behavior changes that I see in what I have covered
Everyone’s timelines are scrambled due to the COVID-19 pandemic, so predicting
what will happen in the coming months is difficult. In theory, R
Developer Preview 3 should ship sometime in April. With luck, I will have an update
to this book out a few weeks after that.
—Mar 30, 2020
A Peek at SurfaceControlViewHost in Android R
One of the items that I found interesting in
the second half of my R DP2 random musings
SurfaceControlViewHost. I experimented with it this week, and it at least
partially works. In a nutshell: one app can embed and display a live UI from another app.
For some developers, this sort of cross-app UI embedding has been “the Holy Grail”
for years. You can do a limited version of this with
RemoteViews, but the
widget set is minimal by modern standards. You could create your own
RemoteViews-like structure, but keeping all of the participating apps in sync
can get troublesome. Android 9’s slices… well, OK, those never really caught
But, with Android R and
SurfaceControlViewHost, it is not that hard to set
up cross-process UI delivery. There are no obvious limits as to what that UI
can look like, because the UI itself is not really shared. Instead, the two
processes seem to be sharing a
Surface, with the UI-supplying process rendering
a view hierarchy to that
Surface and the UI-hosting process displaying that
Surface as part of a
How Do You Make It Work?
I’ll have code available on Monday, as part of the Elements of Android R release.
UPDATE 2020-03-29: The
modules implement what I describe here.
Here are the basic mechanics:
Have two apps, with some sort of IPC channel between them. I elected to use
a bound service, playing with Google’s
Messenger pattern for getting data between the apps.
In the source code, you will see an
EmbedServer and an
that represent these two apps.
Have the UI client (
EmbedClient) set up a
SurfaceView and identify the
on which that
SurfaceView will appear. Then, it needs to send to the other app the dimensions
SurfaceView, the ID of the
Display to use, and a “host token” obtained
getHostToken(). All of those can be stuffed into
Bundle for easy delivery via common IPC patterns (e.g., as part of a
Have the UI provider (
EmbedServer) set up that UI, such as via view binding.
When it receives the details from the client, it can set up a
tied to the
Display and “host token”. It can then attach the root view of the
view hierarchy to the
addView(). Then, it needs to
SurfacePackage from that
and send that back to the client.
Parcelable, so you can send
it via any common IPC mechanism (e.g., as part of a return
Once the client receives the
SurfacePackage, attach it to the
And that’s it. At this point, the client should be showing the provided UI in
SurfaceView. If the provider updates that UI, the client should show the updates
in real time.
What About Input?
The docs indicate that touch events on the
should get sent from the client process to the provider process, with the implication
that this will trigger events on the widgets in the provider’s view hierarchy.
Unfortunately, I could not get that part to work.
That’s quite possibly a bug in my experimental code. There is very little documentation
on this, and I may have missed a step somewhere. Otherwise, it’s possible that there
is a bug in DP2.
What’s Google Going to Do With This?
I have no idea.
Seriously, they could use this for:
A richer replacement for app widgets and slices
A richer option for custom views in notifications
Embedding any of their apps in any other one of their apps (e.g., more powerful
options for launching a Hangout from Calendar)
But, my guess is that whatever they have in mind will be something I won’t expect.
What Can We Do With This?
Well, not much, insofar as this is only available on Android R. Since this requires
new methods on
SurfaceView, my guess is that this cannot be backported via a Jetpack
library. For the time being, approximately 0.0% of your user base is running Android R.
However, longer-term, this opens up some interesting possibilities.
From a security standpoint, this technique should allow for us to better sandbox
untrusted content. We have had options for doing that, with dedicated low-permission
processes, but they had only classic IPC ways of getting information out of the
sandbox. Now, they can present a full UI, yet still not have any means of attacking
the client displaying that UI.
Apps with a rich third-party ecosystem of plugins could adopt this for incrementally tighter
integration with those plugins. Right now, the only easy thing is for the app to
start an activity in the plugin, if the plugin needs to supply UI. Otherwise, you
were stuck with the UI integration options I mentioned earlier, like
Now, though, a plugin can provide finer-grained UI elements that could be embedded
in the core app’s UI, to offer a more seamless experience to the user.
Assuming that there is no significant performance overhead for delivering a UI
this way, this opens the doors for popular content publishers to get their
content embedded in other apps, yet still maintain complete control over that
But, once again, my guess is that the best use of this tech is something that I am not currently
Ordinarily, I would have expected presentations on this at Google I|O. Now, in our
I|O-free world, I do not know when or how Google might provide more information
on this API and how they (and we) might use it. But, it’s something that I will
be keeping an eye on, as it’s one of the more intriguing new additions in Android R.
—Mar 27, 2020
R Raw Paths and All Files Access
In R DP1, I could not get the “raw paths” feature or the “all files access” feature
In R DP2, both seem to be working fine.
The documentation is a bit confusing, but here is what I have seen in light
In a nutshell,
READ_EXTERNAL_STORAGE works like it did from Android 4.4 through
Android 9. If you request it, and the user grants it, you can traverse external
storage more or less as you were used to.
However, there are caveats:
The documentation mentions reduced performance. I have not attempted to do any
sort of apples-to-apples comparison, but I don’t get the sense that the performance
degradation is severe.
As the documentation notes, you still do not have access to
Android/ and its
I have not tried removable storage.
While the documentation emphasizes native libraries, read access works fine from Java/Kotlin.
I have not tried native library access, but I assume that it works.
Also, methods like
Environment are still deprecated. My guess is that we are supposed to use
StorageVolume, as that was added in Android R. I have
not experimented with that yet.
getExternalStorageDirectory() works, at least
on R DP2, returning the conventional location.
All Files Access
MANAGE_EXTERNAL_STORAGE is the new
If you request
MANAGE_EXTERNAL_STORAGE in the manifest,
and you use
to bring up the Settings screen for this, and the user grants the permission, then
you can write content to external storage. The effect is akin to what we had
from Android 4.4 through Android 9.
Again, though, there are caveats:
The same concerns exist around how we get the filesystem path to use.
Presumably, write performance is also reduced.
Even with this permission, you still do not have access to
Android/ and its
I still have not tried removable storage (hey, I’ve been busy writing this blog post).
There is no obvious means to find out if we hold this permission. It is not a
dangerous permission, so
checkSelfPermission() does not work.
The issue has been marked as “fixed”, but
I did not notice a method for this in DP2, so perhaps the method will show up
in a later developer preview.
Given last year’s continuous changes in this area in the Q developer previews, I am
not making any final recommendations until R ships as Android 11.
Also, the fact that filesystem-style access is back in R does not change the fact that
we should be losing that access in Q.
is supposed to be ignored by Android 10 once our
targetSdkVersion hits 29.
Assuming that remains the case (I have not re-tested it), then we still lack
filesystem-style access in Android 10, even though we have it in 9 and 11.
If so, you are still going to be needing to try to adopt the Storage
Access Framework and/or the
MediaStore to handle Android 10. Plus, the
MANAGE_EXTERNAL_STORAGE permission screen is decidedly more scary-looking
than the normal
dangerous permission dialog, so fewer users will be willing
to grant it.
So, I’ll be watching this area in DP3 and beyond, to see what changes, if anything.
However, it looks like external storage is making a comeback, after I left it for
dead almost exactly one year ago.
—Mar 22, 2020
More Random Musings on R DP2!
Rich Hong pointed me to
the DP1 -> DP2 API differences report.
Which is really good, because, as it turns out, all the cool stuff isn’t in the
actual R DP2 docs.
So, here are some more random musings, based on that API differences report, and
building upon yesterday’s original set of R DP2 musings.
Things That Show How Android Is In Control
As XDA-Developers mentioned a few hours ago,
there is a new API for adding “quick controls” to the menu we get on a long-press of the POWER
button. Apps can implement a
to advertise options for this “quick controls” area. This appears to work a bit
TileService does for adding tiles to the notification shade. The
available types of controls are defined as constants on a
class, and the candidates are mostly appliances and similar sorts of household
items… and, apparently, a pergola.
However, I feel quite confident that enterprising developers will find ways
to use this for ‘device types’ that are somewhat broader in nature.
Things That Share
In Android 10, we got
I blew past it, in part because I couldn’t figure out what it was for our how we
would really use it.
In R DP2, we now have
Its JavaDocs have a very interesting sentence:
The primary usage of this class is to embed a View hierarchy from one process in to another.
The implication is that we might now have something that developers have been
asking for since the very early days of Android: the ability to embed the UI
of one app in another. Whether that is the intended purpose or not remains to be
seen, as all of this is still rather under-documented.
Things That Affect Security
There is a new
API for developers of VPN clients.
We also now have
VerifiedMotionEvent. We seem to
get these from
whose JavaDocs state:
Verify the details of an
InputEvent that came from the system. If the event did not come from the system, or its details could not be verified, then this will return null.
It is unclear what the scenarios are where the
InputEvent would not come from “the system”,
in part because there is no real definition here of “the system”. However, if you
have a highly-secure input scenario (e.g., passcode for a banking app), this
may be worth investigating further.
Things That Are Getting Massaged
If you have been using various ways of implementing full-screen UIs, such
setSystemUiVisibility(), your current API calls may now be deprecated.
That is moving to
ChooserTargetService that were the original approach
for direct-share targets are now deprecated in favor of Android 10’s
Sharing Shortcuts API.
What Happens Next?
collapse of Google I/O does start to raise
questions about Android R’s rollout. It would not surprise me if things get
delayed, both at the level of the developer previews and betas and at the level
of a final release. After all, Google has to do what everyone else is doing: try to get stuff
done in the face of a pandemic.
However, eventually, the sun will shine again, SARS-CoV-2 will have reduced impact,
and Android R will ship. Between now and then, I will write and blog what I can
on what Android R means for us developers.
—Mar 20, 2020
Random Musings on the R Developer Preview 2
Each time Google releases a new developer preview, I read what I can
to see if there are things that warrant more attention from
developers. I try to emphasize mainstream features that any developer
might reasonably use, along with things that may not
get quite as much attention, because they are buried in the JavaDocs.
This time, I can’t readily do the “buried in the JavaDocs” part, because
the release notes
lacks a link to the DP1 -> DP2 API difference report. Instead, it has two
links pointing to the API 29 -> DP2 report,
which makes it more difficult for me to identify what is new to DP2.
If this gets fixed, I may
follow up with another blog post.
UPDATE 2020-03-20: Rich Hong pointed me to
the DP1 -> DP2 API differences report.
In the meantime, here are some musings, as random as ever…
Things That Might Piss Off Users
Apparently, Android R will nag users to not use a USB headset
with apps that… don’t record audio. The workaround: have the app say that it records audio.
UPDATE 2020-03-25: They have refined the language here — the “nag” dialog
to which I was referring is only for apps that use
UsbManager. That reduces the scope of
this problem dramatically.
Things That Could Break Your App
I worry that the package visibility changes
are going to break more apps than perhaps Google realizes. While I haven’t tested
this aspect of R DP2 yet, it appears that your app now can’t find out what other apps are installed,
on a general basis. The cited example is
queryIntentActivities(), but to make
this really work you would need to seriously lobotomize
You can whitelist certain packages and certain
structures to try to get by this for certain use cases. And, this is where
QUERY_ALL_PACKAGES permission seen in DP1 comes into play —
this permission removes these new restrictions. Given the “look for Google Play
to provide guidelines for apps that need this permission” caveat, it is safest to assume
that if you try using it, eventually you will be banned from the Play Store by a
If your app has been dutifully following the new Android 10 rules for
background location access… get ready for new user flows.
If your app has been clearing the cache of other apps… sorry, but
that appears to no longer be an option.
Probably the move to Conscrypt for
will not cause problems for most apps, but it’s something to keep an eye on.
UPDATE 2020-03-20: A Googler reached out to correct me on this one. Conscrypt
has been used for
SSLSocket for some time. However, there are some implementation
tweaks in Android R — now
SSLSocket is “just a wrapper” of
Again, there should be few problems here, but it is something to note.
Things That Are Generally Positive
might be useful for some developers, though I suspect not all that many.
Basically, it allows you to say that users who upgrade your app get old-style
external storage while new users get scoped storage, by my read of it.
Being able to use more than one camera
The blog post
mentions some new window inset options for more synchronized behavior with
soft keyboards as they collapse and expand. Strangely, I don’t see this in the main Android R
release documentation. It’s a slick feature, albeit one that I do not expect will get
adopted that much. As with Android 10’s gesture-based navigation, I think Google
is seriously over-estimating developers’ willingness to rewrite UIs for these sorts of things.
After all, we can’t get apps to support landscape, and that feature has been around since API Level 1.
So, while I’m sure highly-polished apps will use this new synchronized IME
stuff to become even more highly-polished… most apps will muddle along as they have been.
Things That Make Me Go “Hmmmmmm…”
The per-process network access control
feature seems great… except that the supplied XML is mystifying. Where
does this go? What does an empty
<process /> element mean? What does
<process> element without children mean? Does the
deny-permission element names, coupled with the fully-qualified permission names,
mean that this works for all permissions, not just
What is referred to as dynamic intent filters
seems to overstate the case: the only dynamic element is the roster of supported
MIME types. The rationale given for this feature is:
This is a problem for virtualization apps (such as virtual machines and remote desktops) because they have no way of knowing exactly what software the user will install inside them.
That rationale seems odd to me. I certainly can’t rule it out, but it is unclear
under what circumstances “virtual machines and remote desktops” would know about
particular MIME types that they should support dynamically. Plus, virtual machines
would seem to be in violation of Play Store policies regarding dynamic code loading
just by existing. The feature seems fine, but something seems fishy.
What Happens Next?
I think I have found enough stuff that works to warrant releasing an
Elements of Android R in the coming weeks, so stay tuned!
UPDATE 2020-03-20: I have more musings on R DP2!
—Mar 19, 2020