Sunday, December 12, 2010

New Gingerbread API: StrictMode

[This post is by Brad Fitzpatrick, an Android Software Engineer who worries unreasonably about responsiveness. —Tim Bray]

Back Story

One great thing about Google is “20% time”: spending 20% of your time working on projects outside your main focus area. When I joined Google, I bounced all over the place, often joking that I had seven 20% projects. One project I kept coming back to was Android. I loved its open nature, giving me access to do whatever I wanted, including opening my garage door when I approached my house on my motorcycle. I really wanted it to succeed but I worried about one thing: It wasn’t always super smooth. Animations would sometimes stutter and UI elements weren’t always immediately responsive to input. It was pretty obvious that things were sometimes happening on the wrong thread.

As a heavy SMS user, one of my 20% projects during the Cupcake (Android 1.5) release was speeding up the Messaging app and making it feel smoother. I got the app to a happy state and then continued bouncing between other 20% projects. When the Donut (Android 1.6) release came out, I noticed that a few of my Messaging optimizations had been accidentally broken. I was sad for a bit but then I realized what Android really needed was always-on, built-in, pervasive performance monitoring.

I joined the Android team full-time just over a year ago and spent a lot of time investigating Froyo performance issues, in particular debugging ANRs (those annoying dialogs you get when an application stalls its main thread’s Looper). Debugging ANRs with the tools at hand was painful and boring. There wasn’t enough instrumentation to find the causes, especially when multiple processes were involved (doing Binder or ContentResolver operations to Services or ContentProviders in other processes). There had to be a better way to track down latency hiccups and ANRs...

Enter StrictMode

“I see you were doing 120 ms in a 16 ms zone...”



StrictMode is a new API in Gingerbread which primarily lets you set a policy on a thread declaring what you’re not allowed to do on that thread, and what the penalty is if you violate the policy. Implementation-wise, this policy is simply a thread-local integer bitmask.

By default everything is allowed and it won’t get in your way unless you want it to. The flags you can enable in the thread policy include:

  • detect disk writes


  • detect disk reads


  • detect network usage


  • on a violation: log


  • on a violation: crash


  • on a violation: dropbox


  • on a violation: show an annoying dialog


In addition, StrictMode has about a dozen hooks around most of the places that hit the disk (in java.io.*, android.database.sqlite.*, etc) and network (java.net.*) which check the current thread’s policy, reacting as you’ve asked.

StrictMode’s powerful part is that the per-thread policies are propagated whenever Binder IPC calls are made to other Services or Providers, and stack traces are stitched together across any number of processes.

Nobody wants to be slow

You might know all the places where your app does disk I/O, but do you know all the places where the system services and providers do? I don’t. I’m learning, but it’s a lot of code. We’re continually working to clarify performance implications in the SDK docs, but I usually rely on StrictMode to help catch calls that inadvertently hit the disk.

Background on disks on phones

Wait, what’s wrong with hitting the disk? Android devices are all running flash memory, right? That’s like a super-fast SSD with no moving parts? I shouldn’t have to care? Unfortunately, you do.

You can’t depend on the flash components or filesystems used in most Android devices to be consistently fast. The YAFFS filesystem used on many Android devices, for instance, has a global lock around all its operations. Only one disk operation can be in-flight across the entire device. Even a simple “stat” operation can take quite a while if you are unlucky. Other devices with more traditional block device-based filesystems still occasionally suffer when the block rotation layer decides to garbage collect and do some slow internal flash erase operations. (For some good geeky background reading, see lwn.net/Articles/353411)

The take-away is that the “disk” (or filesystem) on mobile devices is usually fast, but the 90th percentile latencies are often quite poor. Also, most filesystems slow down quite a bit as they get more full. (See slides from Google I/O Zippy Android apps talk, linked off code.google.com/p/zippy-android)

The “main” Thread

Android callbacks and lifecycle events all typically happen on the main thread (aka “UI thread”). This makes life easier most of the time, but it’s also something you need to be careful of because all animations, scrolls, and flings process their animations by callbacks on the main thread.

If you want to run an animation at 60 fps and an input event comes in (also on the main thread), you have 16 ms to run your code reacting to that input event. If you take longer than 16 ms, perhaps by writing to disk, you’ve now stuttered your animation. Disk reads are often better, but they can also take longer than 16 ms, especially on YAFFS if you’re waiting for the filesystem lock that’s held by a process in the middle of a write.

The network is especially slow and inconsistent, so you should never do network requests on your main thread. In fact, in the upcoming Honeycomb release we’ve made network requests on the main thread a fatal error, unless your app is targeting an API version before Honeycomb. So if you want to get ready for the Honeycomb SDK, make sure you’re never doing network requests on your UI thread. (see “Tips on being smooth” below.)

Enabling StrictMode

The recommended way to use StrictMode is to turn it on during development, learn from it, and turn it off before you ship your app.

For example, in your application or component’s onCreate():

 public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
}
super.onCreate();
}

Or, simply:

    public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.enableDefaults();
}
super.onCreate();
}

That latter form was specifically added so you can target pre-Gingerbread API versions but still easily enable StrictMode using reflection or other techniques. For instance, you could be targeting Donut (Android 1.6) but still use StrictMode if you’re testing on a Gingerbread device or emulator, as long as you use enough Reflection to call StrictMode.enableDefaults().

Watching StrictMode

If you’re using penaltyLog(), the default, just run adb logcat and watch the terminal output. Any violations will be logged to your console, slightly rate-limited for duplicate elimination.

If you want to get fancier, turn on penaltyDropbox() and they’ll be written to the DropBoxManager, where you can extract them later with

adb shell dumpsys dropbox data_app_strictmode --print

Tips on being smooth

In addition to Thread and java.util.concurrent.*, check out some of the Android APIs such as Handler, AsyncTask, AsyncQueryHandler, and IntentService.

Our Experience

During Android development we have a new “dogfood” build each day that the whole team uses. Throughout the development of Gingerbread we set up our daily dogfood builds to enable StrictMode logging and upload all found violations for analysis. Every hour a MapReduce job runs and produces an interactive report of all the event loop stalls, their stack traces (including cross-process ones), their latency percentiles, which processes/packages they appear in, etc.

Using the data from StrictMode we fixed hundreds of responsiveness bugs and animation glitches all across the board. We made performance optimizations in the Android core (e.g. system services and providers) so all apps on the system will benefit, as well as fixing up tons of app-specific issues (in both AOSP apps and Google apps). Even if you’re using Froyo today, the recent updates to GMail, Google Maps, and YouTube all benefited from StrictMode data collection gathered on Gingerbread devices.

Where we couldn’t automatically speed up the system, we instead added APIs to make certain patterns easier to do efficiently. For example, there is a new method SharedPreferences.Editor.apply(), which you should be using instead of commit() if you don’t need commit()’s return value. (It turns out almost nobody ever checks it.) You can even use reflection to conditionally use apply() vs. commit() depending on the user’s platform version.

Googlers who switched from Froyo to Gingerbread without seeing all the baby steps between were shocked at how much more responsive the system became. Our friends on the Chrome team then recently added something similar. Of course, StrictMode can’t take all the credit. The new concurrent garbage collector in Gingerbread also greatly reduces latency hiccups.

The Future

The StrictMode API and its capabilities will continue to expand. We have some good stuff lined up for StrictMode in Honeycomb but let us know what else you’d like to see! I’ll be answering questions on stackoverflow.com for questions tagged “strictmode”. Thanks!

Friday, December 10, 2010

Android Market Client Update

[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]

The Android Market engineering team has been hard at work on improving the Android Market experience for users and developers. Today, I’m pleased to announce a significant update to the Android Market client. Over the next two weeks, we’ll be rolling out a new Android Market client to all devices running Android 1.6 or higher.

This new Market client introduces important features that improve merchandising of applications, streamline the browse-to-purchase experience, and make it easier for developers to distribute their applications.

With a focus on improving discoverability and merchandising, we’ve introduced a new carousel on the home and category screens. Users can quickly flip through the carousel to view promoted applications and immediately go to the download page for the application they want. Developers have been very active in creating great Widgets and Live Wallpapers. To make it easier for users to find their favorites, we’re introducing two new categories for Widgets and Live Wallpapers. Applications that include Widgets and Wallpapers will be automatically added to those new categories. We’ll also be adding more categories for popular applications and games in the weeks ahead. In addition, the app details page now includes Related content, which makes it easier for users to quickly find apps of similar interest.




To streamline the browse-to-purchase experience, users can now access all the information about an application on a single page without the need to navigate across different tabs. We’re also introducing application content rating to provide users with more information about applications they are interested in. Since most users who request a refund do so within minutes of purchase, we will reduce the refund window on Market to 15 minutes. This change will be largely transparent to buyers, but will help developers manage their businesses more effectively.



To make it easier for developers to distribute and manage their products, we will introduce support for device targeting based on screen sizes and densities, as well as on GL texture compression formats. We are also increasing the maximum size for .apk files on Market to 50MB, to better support richer games.

With this release, we aimed to deliver features that are most requested by users and developers. However, we’re not done yet. We plan to continue to rapidly enhance Android Market for both users and developers and make it the best content distribution service for the Android ecosystem.

Please stay tuned as we continue to deliver new capabilities in the coming weeks and months.

Thursday, December 9, 2010

Saving Data Safely

With the advent of Gingerbread, we’re going to be running a series of posts in this space about the aspects of Android 2.3 that developers should care about. One thing that developers should care about more than anything else is not losing data. The rules are changing slightly as Gingerbread arrives, so I thought that would be a good starting point. I didn’t write this; I pulled it together from the contents of an email thread involving Android engineers Brad Fitzpatrick, Dianne Hackborn, Brian Swetland, and Chris Tate.

The question is: how do you make really sure your data’s been written to persistent storage? The answer involves a low-level system call named fsync(). Old C programmers like me mostly learned this the hard way back in the Bad Old Days; in 2008 at OSCON I immensely enjoyed Eat My Data: How Everybody Gets File IO Wrong by Stewart Smith; I've included a picture I took of one of his slides.

The reason this should be of concern to Android developers is that with 2.3, an increasing proportion of devices, notably including the Nexus S, are going to be moving from YAFFS to the ext4 filesystem, which buffers much more aggressively; thus you need to be more assertive about making sure your data gets to permanent storage when you want it to.

If you just use SharedPreferences or SQLite, you can relax, because we’ve made sure they Do The Right Thing about buffering. But if you have your own on-disk format, keep in mind that your data doesn't actually consistently reach the flash chip when you write() it or even when you close() it. There are several layers of buffering between you and the hardware! And because of ext4 buffering policy, any POSIX guarantees that you thought you had before (but actually didn't), you especially don't have now.

Some Android devices are already running non-YAFFS filesystems, but as we brought up the Nexus S, buffering issues have actually bitten us a couple of times in framework code. When the Gingerbread source code becomes available, you’ll find lots of examples of how file I/O should be done.

To start with, for raw data consider using one of the synchronous modes of java.io.RandomAccessFile, which take care of calling fsync() for you in the appropriate way. If you can’t, you’ll want Java code that looks something like this.

     public static boolean sync(FileOutputStream stream) {
try {
if (stream != null) {
stream.getFD().sync();
}
return true;
} catch (IOException e) {
}
return false;

In some applications, you might even want to check the return status of the close() call.

Now of course, there are two sides to this story. When you call fsync() and force the data onto storage, that can be slow; worse, unpredictably slow. So be sure to call it when you need it, but be careful not to call it carelessly.

Background reading if you want to know more:

Monday, December 6, 2010

Android 2.3 Platform and Updated SDK Tools

Today we're announcing a new version of the Android platform — Android 2.3 (Gingerbread). It includes many new platform technologies and APIs to help developers create great apps. Some of the highlights include:

Enhancements for game development: To improve overall responsiveness, we’ve added a new concurrent garbage collector and optimized the platform’s overall event handling. We’ve also given developers native access to more parts of the system by exposing a broad set of native APIs. From native code, applications can now access input and sensor events, EGL/OpenGL ES, OpenSL ES, and assets, as well a new framework for managing lifecycle and windows. For precise motion processing, developers can use several new sensor types, including gyroscope.

Rich multimedia: To provide a great multimedia environment for games and other applications, we’ve added support for the new video formats VP8 and WebM, as well as support for AAC and AMR-wideband encoding. The platform also provides new audio effects such as reverb, equalization, headphone virtualization, and bass boost.

New forms of communication: The platform now includes support for front-facing camera, SIP/VOIP, and Near Field Communications (NFC), to let developers include new capabilities in their applications.

For a complete overview of what’s new in the platform, see the Android 2.3 Platform Highlights.

Alongside the new platform, we are releasing updates to the SDK Tools (r8), NDK, and ADT Plugin for Eclipse (8.0.0). New features include:

Simplified debug builds: Developers can easily generate debug packages without having to manually configure the application’s manifest, making workflow more efficient.

Integrated ProGuard support: ProGuard is now packaged with the SDK Tools. Developers can now obfuscate their code as an integrated part of a release build.

HierarchyViewer improvements: The HierarchyViewer tool includes an updated UI and is now accessible directly from the ADT Plugin.

Preview of new UI Builder: An early release of a new visual layout editor lets developers create layouts in ADT by dragging and dropping UI elements from contextual menus. It’s a work in progress and we intend to iterate quickly on it.

To get started developing or testing applications on Android 2.3, visit the Android Developers site for information about the Android 2.3 platform, the SDK Tools, the ADT Plugin and the new NDK.

Check out the video below to learn more about the new developer features in Android 2.3.

Wednesday, November 24, 2010

Content Rating for Android Market

[This post is by Eric Chu, Android Developer Ecosystem. —Tim Bray]

Providing users with more information about applications on Android Market has been a top request from Android users. Starting in a few weeks, we will be showing content ratings for all applications on Android Market. This new capability will provide users with additional information to help them select the best applications for them.

Android Market’s content policy remains the same as before: applications will be rated according to four content rating levels: All, Pre-teen, Teen, & Mature. Details on the rating levels can be found at Android Market Help Center.

To prepare for this launch, starting next week, developers submitting new or updated applications will be required to include a rating for all applications and games uploaded onto Android Market. In addition, developers will have the next several weeks to add a rating to their existing applications and games. Once content rating is visible to users, any applications or games that do not include a rating will be treated as “Mature”.

We are working hard to rapidly deliver improvements and upgrades to Android Market. Please look for more Android Market upgrades in the coming weeks. Thanks for your continued support and please don’t hesitate to give us feedback on what else we can do to make you more successful with Android and Android Market.

Thursday, November 11, 2010

Market Housekeeping Alert

We’ve had quite a bit of discussion in this space recently about how to make sure that your app is visible in Android Market to any device that can run it, and only to those devices. In particular, check out two recent pieces by Reto Meier, Future-Proofing Your App and The Five Steps to Future Hardware Happiness.

As Reto points out, Market used to infer some <uses-feature> settings for older apps that were uploaded before certain device features arrived. This hasn’t been the case for applications uploaded since June of this year; developers have had to be careful about <uses-feature> and its android:required attribute. From what we see, it looks like most of you have got this sorted out and things are working smoothly.

However, there are still apps that haven’t been re-uploaded since June. In preparation for introducing some new Market features (that we think you’ll like), we’re about to launch a re-scan of all those legacy apps, looking at their Android Manifests and updating Market’s database. This means that if you have an app that you haven’t updated since June, and it lacks up-to-date <uses-feature> settings, it may stop being visible on certain devices.

We think the set of apps that will have this problem will be small, if only since most successful apps are updated regularly. If you want to be sure, check Reto’s advice here under "Android Market Rule #2”.

We’ve said it before but it bears repeating: There are a lot of different sizes and shapes and flavors of Android devices in the product pipeline, and you want your app available on every one that can possibly run it. So this is an area that is going to be requiring attention from developers on a continuing basis.

Wednesday, November 10, 2010

Android Market Action

Almost instantly after I joined Google, it became obvious to me that the number-one area where Android developers wanted to see action and progress was in Android Market; your concerns in this area vastly outweighed whatever issues might be bothering you about the handsets and the framework and the programming tools. In recent months there has been a steady, quiet, incremental flow of improvements and upgrades. They add up. This is by way of a glance back at developments since the arrival of Froyo last summer.

First, we introduced error reporting to Market, so developers can see if their apps are locking up or crashing; and if so, exactly where.

Second, we upgraded the Market publisher site to include user comments, so you can read what people are saying about you, or at least what they’re saying in a language you understand.

Third, we added the licensing server, which, when used properly, tilts the economics of Android apps toward you, the developer, and against the pirates.

Fourth, we cranked up the number of countries people can buy and sell apps in: as of now, you can sell them in 29 countries and buy them in 32.

Fifth, we rolled in a “recent changes” feature, a place for developers to put their release notes. Android Market has a zero-friction process for app update, and the really great apps have followed the “release early, release often” philosophy. As a developer, I like having a place to write down what’s behind an app release, and as a person who downloads lots of apps, I like to know what the goodies are in each new update.

Sixth, Market now has a “draft upload” feature; this removes a lot of the tension and strain from the app-update process. Get your screenshots and feature graphics and text and APK all squared away with as much editing as you need to, then update them all with one click.

You’ll notice that I didn’t say “Sixth and last”, because this is a team on a roll and I expect lots more goodness from them; if you care about the larger Android ecosystem, or are already a developer, or are thinking of becoming one, stay tuned to this channel.