Android 5.0 "Lollipop" a month on: the OS sets the high bar for a mobile OS and the Nexus 9 shines but there are some pitfalls for developers. If you're getting reports of crashes on Lollipop, be sure to check out these potential gotchas!

The Google Nexus 9 tablet is built with the NVIDIA® Tegra® K1 64 bit mobile processor and SHIELD tablet 8 was one of the first Android devices to receive the Lollipop OTA. To ensure the best user experience for these two important products, NVIDIA tested thousands of games and applications in the lead up to Lollipop's release. The core OS and driver teams used the testing to better stabilize and hone the platforms. The Content & Technology team on the other hand, scoured the bugs for patterns and common problems that required developer intervention. We learned a lot and worked with many great developers to get bugs fixed before consumers ever saw them. Here are some of the more common issues we saw; we hope they help you save some hair from being pulled out!

NOTE: This is a follow-on post from the "Android Lollipop and Nexus 9 launch" blog. Check it out for a primer of what Lollipop has to offer.

Debugging Java and Native Code

We've heard from some developers about random crashes when trying to debug projects that used to debug without issue under earlier versions of Android. There's a small note in the NDK r10c release notes that states:

Made it possible to enter ART debugging mode, when debugging on an Android 5.0 device using ART as its virtual machine, by specifying the art-on option. For more information, see prebuilt/common/gdb/common.setup in the directory containing the NDK.

Android NDK, Revision 10c (October 2014)

Be sure to enable the art-on option in your gdb.setup file for any application which includes a mix of Java and native code.

If you're looking for a comprehensive debugging solution for Android Java and Native code, NVIDIA's free Nsight Tegra Visual Studio Edition tool is for you. From within Microsoft Visual Studio, you have flexible project management, accelerated compilation (now supporting IncrediBuild) and proper debugging of NDK based applications using breakpoints, steps, watchlists and all the other modern features you've come to expect. Version 2 is fully compatible with Android 5.0 "Lollipop" and is packaged with TADP.

Nsight Tegra even enables the art-on option for you automatically when needed for your project! Check it out!

Using OpenGL ES 3.1 and Android Extension Pack

[IMG] NVIDIA Tegra K1 64 bit

For the graphics and 3D lovers out there, Android Lollipop brings with it the Android Extension Pack (AEP). AEP extends OpenGL ES 3.1 with a set of 3D extensions that provide higher level, desktop style 3D features. To get going with AEP, grab a Nexus 9 or SHIELD tablet and look over Google's AEP guide. For examples of the latest cutting edge graphics on Android, check out NVIDIA's GameWorks OpenGL Samples.

NVIDIA also provides a free GPU profiling tool called Tegra Graphics Debugger, which lets you profile and debug AEP (as well as OpenGL ES 1.0, 2.0, 3.x and full OpenGL).


Market Filtering for AEP

If you are writing an application or demo specifically for AEP (we encourage fallbacks but understand this is not always possible), be sure to filter for AEP in the Play Store. Using the following line in the AndroidManifest.xml limits display of the app to only those devices with AEP support so should avoid any user confusion.

<uses feature android:name="android.hardware.opengles.aep" android:required="true" />

Telling the Time

To better match the ISO specification for clock(), Lollipop has an amended implementation of the libc Bionic clock() function. It provides an "approximation to the processor time used" (ie CPU time) rather than the wall-clock. Thus, if timing of the total amount of time passed is needed, use clock_gettime() for the process wall-clock. Indeed, to avoid time possibly going backwards, use the CLOCK_MONOTONIC qualifier.

In our testing, we've seen some games with counters, count-downs or lap timers running either too slow or too fast. Additionally some UI and screen updates can jitter or update inconsistently. Check your code for blocks such as this:

do {
  do {
    cur_time = clock();  // This should use "clock_gettime(CLOCK_MONOTONIC, &now)"
  } while ((cur_time – last_update_time) < 1s);

  last_update_time = cur_time;
  updateUiTimers(cur_time);
} while ( checkExit() == FALSE);

JNI Strictness and a Shared Stack

Android Lollipop introduces a new Java runtime called the Android Run Time (ART). The switch to ART improves performance but has some implementation differences as compared to Dalvik. In particular, watch out for these potential trip ups.

  • ART is more strict when using the Java Native Interface (JNI) to run C/C++ code; JNI code which ran without errors on Kitkat may crash on Lollipop.
  • Java and C/C++ native code now share the stack. If your Java or native code sets custom stack sizes, carefully review your code. In particular check calls to pthread_attr_setstack() and pthread_attr_setstacksize() and any explicit stack sizes used in Java's Thread constructor.
  • Code from some obfuscators, optimizers and custom build tools which generate non-standard code or code which is incompatible with compacting garbage collection may exhibit issues. So if you're seeing odd issues or crashes on Lollipop, try disabling such tools and see if the issues disappear.

Implicit Service Intents

One fairly common problem we've noticed is aborts due to implicit service intents. These used to cause a warning in most cases but with ART that's reversed and they force an error more often than not. To correctly construct an Intent, specify the intent package as well as the action (thus making explicit to the system which service to launch).

There's an example of this in the Google LVL file LicenseChecker.java, specifically the intent launching the licensing service:

new Intent(
	new String(
		Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))),

Note the comma at the end terminates the 'new Intent' block. One way to avoid the implicit declaration is to use a chained call and add setPackage to the end of the declaration before the comma to explicitly direct the intent:

new Intent(
	new String(
		Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))).setPackage("com.android.vending"),

Third Party Libraries with Implicit Intents

A large proportion of problematic games in our testing of Lollipop exhibited issues with third party libraries. This includes everything from tiny input handlers, to cross platform advertisement services, to full 3D engines. The best advice we can give is to check all third party vendors and upgrade to their latest libraries!

NuPlayer the Nu Android Sound System

The Android sound system has been rewritten to provide lower latency and more features. NuPlayer is sleak and sexy but is also more strict. If you're seeing sound issues or crashes that you trace back to sound effects or music, be sure your data is in the correct format and you are correctly calling the sound libraries.

If you suspect sound issues on Lollipop devices, try switching to the previous sound engine "AwesomePlayer":

Settings -> Developer Options -> Media -> Use NuPlayer (uncheck)

Keep in mind, NuPlayer is the default sound engine under Lollipop so your users will be using it and likely will not have it disabled. Make sure your app works with NuPlayer.

Lollipop Brings Forth Android TV

[IMG] Android TV

With the release of Lollipop, Android now has an official place on the TV! Developers can prepare their games for the living room with relatively simple changes. In particular, pay attention to:

For full details, check out the Android TV Developer Guide and Google's SDK documentation.

Battery Historian

On mobile devices power is always a top priority. Knowing how much power your are using has been quite a difficult question to answer without specialized vendor tools. Google has provided a higher level Android tool called Battery Historian. Using the tool you can easily view the history of power events recorded by the system to better understand how your app is using power. There are many aspects to lowering power usage but some to consider are:

  • Pausing or lowering calculations when paused or when the user becomes inactive
  • Limiting framerate - if your game isn't an intense fighting game maybe 60fps isn't needed and 30fps or even 20fps is adequate and will let the CPU and GPU sleep between updates.
  • Doing low priority tasks more slowly on background threads (this may take longer but allow CPU frequencies to stay lower thus lowering the required CPU voltage and saving overall power).
  • Consolidating network traffic to limit wifi and cellular network usage.

[IMG] Nexus 9 Tablet

Conclusion

With the launch of Android Lollipop, Google has reset the bar for mobile operating systems. Lollipop has many great new features for developers to leverage and provide enhanced user experiences. With these features come some pitfalls. We hope this article helps you dodge the gotchas so you can concentrate on bringing forth the next generation of amazing Android games and applications.