Using performance class to optimize your user experience

Posted by Don Turner, Developer Relations Engineer, and Francois Goldfain, Director of Android Media Framework

Illustration of woman on a phone 

Today we're launching the Jetpack Core Performance library in alpha. This library enables you to easily understand what a device is capable of, and tailor your user experience accordingly. It does this by allowing you to obtain the device’s performance class on devices running Android 11 (API level 30) and above.

A performance class is a ranking that reflects both a device's level of performance and its overall capabilities. As such, it largely reflects the device’s hardware specifications, but also how it performs in certain real-world scenarios, verified by the Android Compatibility Test Suite.

The performance class requirements currently focus on media use cases. For example, a Media Performance Class 12 device is guaranteed to:

  • have 6+ GB of RAM
  • have a 12+ megapixel rear-facing camera supporting video capture at [email protected],
  • be able to initialize a video codec in <50ms even when under load
  • and many other requirements.

A device that meets these requirements can optimally handle many popular media use cases including the typical video pipelines in social media apps for capturing, encoding, and sharing.

As an app developer, this means you can reliably group devices with the same level of performance and tailor your app’s behavior to those different groups. This enables you to deliver an optimal experience to users with both more and less capable devices. Performance class requirements will expand with each major Android release, making it possible to easily target different levels of experience to the performance class range you find appropriate. For example, you might wish to tailor “more premium” and “more functional” experiences to certain performance classes.


How to use performance class

To add performance class to your app, include the following dependency in your build.gradle:

implementation 'androidx.core:core-performance:1.0.0-alpha02'

Then use it to tailor your user experience. For example, to encode higher resolution video depending on Media Performance Class:

class OptimalVideoSettings(context: Context){

   private val devicePerf: DevicePerformance = DevicePerformance.create(context)

   val encodeHeight by lazy {
       when (devicePerf.mediaPerformanceClass) {
           Build.VERSION_CODES.S -> 1080 // On performance class 12 use 1080p
           Build.VERSION_CODES.R -> 720 // On performance class 11 use 720p
           else -> 480
       }
   }

   val encodeFps by lazy {
       when(devicePerf.mediaPerformanceClass){
           Build.VERSION_CODES.S -> 60 // On performance class 12 use 60 fps
           Build.VERSION_CODES.R -> 30 // On performance class 11 use 30 fps
           else -> 30
       }
   }
}

When to use performance class

The Android device ecosystem is very diverse. The same application code can lead to very different behaviors depending on the device’s capabilities. For example, encoding a 4K video might take a few seconds on one device but a few minutes on another. User expectations also vary greatly based on the device they purchase. To provide an optimized user experience, it is common to group devices based on some criteria, such as RAM size or year released, then tailor your app's features for each group.

The problem with using an arbitrary value such as RAM size for grouping is that it provides no guarantees of a device's performance. There will also always be outliers that perform better or worse than expected within that group. Grouping on performance class solves this problem since it provides these guarantees, backed by real-world tests.

Manually testing devices that belong to different performance classes is one option to assess and identify the changes needed to balance functionalities and usability. However, the recommended approach to validate changes in the app experience is to run A/B tests and analyze their impact on app metrics. You can do this with the support of an experimentation platform such as Firebase. Providing the device’s performance class to the experimentation platform gives an additional performance dimension to the test results. This lets you identify the right optimizations for each class of device.


Snap Inc.

Snap has been using device clustering and A/B testing to fine tune their experience for Snapchatters. By leveraging performance class, Snapchat confidently identifies device capability in a scalable way and delivers an optimal experience. For example, the visual quality of shared videos is increased by using higher resolution and bitrate on Media Performance Class 12 devices than by default. As more devices are upgraded to meet Media Performance Class, Snapchat will run additional A/B tests and deploy features better optimized for the device capabilities.


Device support

The performance class requirements are developed in collaboration with leading developers and device manufacturers, who recognize the need for a simple, reliable, class-based system to allow app optimizations at scale.

In particular, Oppo, OnePlus, realme, Vivo and Xiaomi have been first to optimize their flagship devices to ensure that they meet the Media Performance Class 12 requirements. As a result, Build.VERSION.MEDIA_PERFORMANCE_CLASS returns Build.VERSION_CODES.S (the Android 12 API level) on the following devices:


Why a Jetpack library?

The Jetpack Core Performance library was introduced to extend performance class to devices not yet running Android 12 or not advertising their eligible performance class at the time they passed the Android Compatibility Test Suite.

The library, which supports devices running Android 11 and above, aims to address this. It reports the performance class of many devices based on the test results collected during the device certification or through additional testing done by the Google team. We're adding new devices regularly, so make sure you’re using the latest version of the Core Performance library to get maximum device coverage.

Reporting performance class to Firebase

When using Firebase as an experimentation platform for A/B tests, it's easy to send the device performance class to Firebase Analytics using a user property. Filtering the A/B test reports by performance class can indicate which experimental values led to the best metrics for each group of devices.

Here's an example of an A/B test which varies the encoding height of a video, and reports the performance class using a user property.

class MyApplication : Application() {

    private lateinit var devicePerf: DevicePerformance 
    private lateinit var firebaseAnalytics: FirebaseAnalytics
         

    override fun onCreate() {
        devicePerf = DevicePerformance.create(this)
        firebaseAnalytics = Firebase.analytics        
        firebaseAnalytics.setUserProperty(
           "androidx.core.performance.DevicePerformance.mediaPerformanceClass",
           devicePerf.mediaPerformanceClass)
    }

    fun getVideoEncodeHeight() : Long = remoteConfig.getLong("encode_height")
}

Next steps

We'd love for you to try out the Core Performance library in your app. If you have any issues or feature requests please file them here.

Also, we'd be interested to hear any feedback you have on the performance class requirements. Are there specific performance criteria or hardware requirements that are important for your app's use cases? If so, please let us know using the Android issue tracker.