The CommonsBlog


Droidception

The question has popped up on Stack Overflow a few times: how the heck does Parallel Space do what it is doing?

Parallel Space allows the user to have N copies of your app, each with its own portion of internal storage. The user could then register as Foo in one copy and Bar in another, and use each copy of the app independently. This does not require Android for Work, Samsung KNOX, or any other hardware-supplied partitioning system – Parallel Space is just an ordinary Android app.

LBE Tech, the firm behind Parallel Space, has not said much about how they do it, other than it involves “MultiDroid, the first application virtualization engine on Android”. And I have never used Parallel Space personally, let alone attempted to examine it (though others have).

My guess is that this is a commercialization of Boxify, or at least an implementation of the same concept.


If somebody asked us what our Android apps run on, our initial response might be “ummmm… Android?”, as the answer seems obvious.

However, most apps do not really interact much with Android, the OS, directly.

When you get past all the Java, most things in Android eventually hit one of two things:

  • an IPC call using Binder, which covers everything from system services to starting activities

  • a native call to a JNI-style C/C++ library linked into our app, including many such calls that come from framework code

Boxify, in effect, proxies both of those through its own app.

The details are in the Boxify paper. In a nutshell, Boxify:

  • Forks a process

  • Loads your APK into that process

  • Replaces a lot of system service implementations, like ActivityManager and PackageManager, with its own implementations that route the IPC through Boxify

  • Uses “syscall hooking” to replace necessary system calls with others that, again, route through Boxify

  • Runs your tweaked-in-memory app (notably, nothing Boxify does requires modifying the APK itself)

So, for example, let’s think about disk I/O. Usually, we find out where to write by calling methods on Context or Environment. Those, in turn, wind up returning paths supplied by Boxify. When you try to open a FileInputStream or something, the Linux syscalls triggered by that I/O also route through Boxify, as it leverages android:isolatedProcess to carefully manage what capabilities the APK can actually perform, and so your app would not be able to write to disk otherwise.


Boxify, itself, was written as a proof of concept for running apps in dedicated sandboxes, particularly for “untrusted apps”, to use the authors’ term.

However, this sort of virtualization technique – Android apps running inside other Android apps, for an Inception-style experience – requires that you trust the virtualization engine. After all, by definition, it can see all I/O between the app and Android, as it proxies all of that I/O. It is a MITM attack on the app.

I have little doubt that such virtualization can be put to plenty of positive uses. At the same time, I sincerely hope that Google and independent security researchers examine any such virtualization app, to “trust, but verify”, to use the Reagan-era maxim.

However, this illustrates yet another way – on top of custom ROMs, emulators, and related tricks – where a user can arrange to run your app in an environment that the user controls more than they do a standard Android environment. That, on top of standard rooting techniques, further emphasizes that you cannot defend yourself from the user. DRM solutions and related techniques are difficult to secure when the user controls the entire environment around your app. Treating the user as the enemy might work for a majority of users, but those who might really be your enemy may well be able to work around whatever DRM-style protections you add. These protections resemble the Maginot Line: strong defenses against predictable attacks that may prove useless with a nimble adversary. IMHO, you are better served finding a business model that does not require you to treat the user as the enemy.

Jan 17, 2017


The Busy Coder's Guide to Android Development Version 8.2 Released

Subscribers now have access to the latest release of The Busy Coder’s Guide to Android Development, known as Version 8.2, in all formats. Just log into your Warescription page and download away, or set up an account and subscribe!

In this update, I:

  • Added a chapter on the basics of using RxJava

  • Added a chapter on viewing PDFs, including embedding PDF viewers in your app

  • Added a chapter on advanced RecyclerView techniques, starting with using RecyclerView to replace a ViewPager for page-at-a-time user interfaces

  • Removed the appendix focusing on Android 7.0’s changes, with that material being moved into appropriate chapters of the book

  • Added various miscellaneous improvements and errata fixes

This update also uses two different font sizes for code listings, employing a larger font for listings whose lines are all fairly short, to help improve readabililty.

Due to a change in the publication process, links between chapters are showing up with changebars in this version. This should be a one-time issue, not affecting future versions of the book.

Also, the APK edition of the book has a new appinar on Android 7.0’s changes to notifications.

The next update is planned for late February.

Jan 09, 2017


Options for Viewing PDFs

A remarkable number of developers come to Stack Overflow to ask about how to show a PDF… without using a third-party PDF viewer app. The conventional solution for showing PDFs is to use a third-party app, via ACTION_VIEW, as that minimizes work on the developer’s part and gives the user the flexibility to choose what tool to use to view the PDF. But, some developers do not want this.

Frankly, I haven’t quite figured out why they do not want this.

The stated reason, in many cases, is that the developers do not control the PDF viewer app, and therefore do not trust it. However, since the #1 recommended solution is to upload the PDF to a Web site, then use a Google Docs URL to render it in a WebView… how exactly is that an improvement?

Regardless of rationale, there are some in-process options for viewing PDFs, though they have their issues.

The only one native to Android proper is PdfRenderer, and that was only added in Android 5.0, leaving out a lot of current devices at the present time. Also, it seems to have been developed primarily for use with print preview, and specifically with previewing the sorts of PDFs that you might create with WebView or a Canvas. In other words: PdfRenderer chokes on various PDF files, rendering nothing at all. Plus, all it does is give you the ability to convert a page of PDF to a Bitmap, so you still have to roll your own UI around that. It also requires a seekable stream from a ParcelFileDescriptor, which pretty much limits you to rendering files (no assets, no raw resources, etc.).

The PDF renderer that Mozilla uses for Firefox is PDF.js. This works with Android’s WebView, but only the modern incarnation of WebView (i.e., Android 4.4+). It will also add ~2MB to your APK file, in the form of a few MB of JavaScript that you need to package as assets. But, it can handle a fairly wide range of PDF files.

The PDF renderer that Google uses for Chromium is pdfium. However, this is C/C++ code, not JavaScript. Bartosz Schiller’s AndroidPdfViewer library wraps Pdfium in a View that handles rendering and standard gestures (e.g., horizontal swipes to move between pages). This works well on older Android versions (I tested through 4.1), but it adds about 5MB to your APK per CPU architecture. By default, you get six architectures and 30MB of overhead. With careful pruning of unnecessary CPU support (see ya, MIPS) and ABI splits, you can minimize the per-APK footprint, but you wind up with greater deployment complexity.

The next update to my Android book — due out on Monday, if all goes well — has a chapter profiling and demonstrating these options.

I suspect that there are some commercial PDF viewing libraries, which may be worth considering as well.

But, overall, most developers should just let ACTION_VIEW handle the details of letting the user view a PDF.

Jan 04, 2017


PSA: v25.1.0 Support Fragments Behavior Change

The most recent Awesome Android Newsletter contained a link to an Android issue about a side-effect of an API change.

Up until a few weeks ago, both for the native implementation of fragments (android.app.Fragment) and the Android Support Library backport in support-v4 (android.support.v4.app.Fragment), when executing a replace() transaction, the fragment being replaced would be called with onStop() before the replacement fragment would be called with onStart().

However, the v25.1.0 version of the backport inverts this by default, with onStart() of the replacement fragment being called before onStop() is called on the fragment being replaced.

And, since this issue is flagged as “working as intended”, this default behavior seems unlikely to change.

Note that the native implementation of fragments behaves as it has – this change has not affected Android 7.1.1, for example. Also note that calling setAllowOptimization(false) on the FragmentTransaction should revert this change and roll you back to the prior behavior.

This is part of a larger optimization change that aims to apply only the subset of your transactions that represent the overall net change in the state of the fragments. Quoting the documentation:

For example, one transaction adds fragment A, a second adds fragment B, then a third removes fragment A. Without optimization, fragment B could expect that while it is being created, fragment A will also exist because fragment A will be removed after fragment B was added. With optimization, fragment B cannot expect fragment A to exist when it has been created because fragment A’s add/remove will be optimized out.

If you have code that is dependent upon the order of these lifecycle events, you will want to double-check how your code behaves with fragment optimizations enabled. If you encounter problems, either adjust your code or disable the optimizations.

Dec 27, 2016


About the Support ExifInterface

Version 25.1.0 of the Android Support library has debuted a new com.android.support:exifinterface artifact, which offers a standalone implementation of ExifInterface, a Java class for reading the EXIF tags from JPEG and raw files.

If that class name sounds familiar, that is because:

  • in May, I suggested moving ExifInterface into Android Support, to provide InputStream as a data source, to better work with content Uri values

  • in September, I suggested moving ExifInterface into Android Support, to give us an implementation that was free of the security bug that Tim Strazzere uncovered

The new ExifInterface is not showing up in the online Android developer documentation. Also, there are no JavaDocs in the Android Support Repository (the JavaDocs JAR is effectively empty). Hopefully, this is a temporary hiccup.

Based on eyeballing the source to android.support.media.ExifInterface, it seems like they matched the API of the Android 7.0 ExifInterface implementation.

This solves two problems:

  1. We now have an ExifInterface constructor that takes an InputStream

  2. This implementation is pure Java, and so it avoids the buggy JHEAD implementation that was the source of the security flaw

Note though that this class — and its SDK counterpart — offers a limited API compared with ExifInterface code elsewhere in the AOSP. In particular:

  • You cannot modify the thumbnail image

  • You cannot save modified EXIF tags, thumbnails, etc. to a different JPEG file than the one that you started with

Hence, you may find yourself still needing to use a separate EXIF parser, just to get needed functionality.

That being said, though, the ExifInterface in the the Android Support library is a welcome addition, and I am very grateful to the engineers who took the time to create it!

Dec 15, 2016


Older Posts