Device compatibility mode

Android activates a compatibility mode for apps that declare orientation or resizability restrictions. Compatibility mode ensures acceptable app behavior on large screen devices and foldable flip phones but with suboptimal usability.

Per-app overrides enable device manufacturers, virtual device owners1, and users to change app behavior to improve app layout or prevent apps from breaking on select devices.

Android 16

Android 16 (API level 36) ignores screen orientation, aspect ratio, and app resizability restrictions to improve the layout of apps on form factors with smallest width >= 600dp.

The following per-app overrides are nonfunctional for apps that target API level 36:

Opt out

Your app can target API level 36 but opt out of the Android 16 behavior, in which case OVERRIDE_ANY_ORIENTATION_TO_USER is not applicable.

Declare manifest property

To opt out of the API level 36 behavior, declare the PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY manifest property.

To opt out for a specific activity, set the property in the <activity> element:

<activity ...>
    <property
        android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
        android:value="true" />
    ...
</activity>

To opt out for your entire app, set the property in the <application> element:

<application ...>
    <property
        android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
        android:value="true" />
    ...
</application>

Reference devices

The following devices may require per-app overrides because of unusual configurations or configurations that are not well supported by apps:

  • Tablets: The natural orientation of some tablets, such as Pixel Tablet, is landscape. A device is in its natural orientation when Display#getRotation() returns Surface.ROTATION_0. If apps assume ROTATION_0 is portrait, app layouts and camera preview can be mismatched to the device display.
  • Landscape foldables: Some foldable devices, such as Pixel Fold, are in portrait orientation when folded, but landscape orientation when unfolded. If apps assume the unfolded orientation is portrait, flickering loops or layout issues are likely.
  • Foldable flip phones: Unfolded flip phones are typically in portrait orientation. But, when folded, the phones usually have a small display in landscape orientation. Apps must identify and accommodate the different orientations of the displays.
  • External displays: Select devices can start a desktop windowing session on external, connected displays. Apps must query external displays for information such as screen size and resolution; otherwise, apps may make incorrect assumptions about the displays, which can lead to incorrect app behavior.
  • Car displays: Many, but not all, car displays are landscape. Developing parked apps for car displays is similar to developing for tablets.

Common compatibility issues

Apps experience compatibility issues most often because of app orientation restrictions, resizability and aspect ratio restrictions, incorrect handling of camera preview orientation, and misused APIs.

Letterboxing

Letterboxing positions the app in the center of the screen or, on large screens, to one side or the other for convenient access. Mattes (solid‑colored bars or blurred wallpaper) fill the unused display area along the sides or top and bottom of the app.

Letterboxing happens often on large screen devices because the dimensions and aspect ratio of the device display are usually different from those of standard phones, for which most apps are designed.

Figure 1. App restricted to portrait orientation is letterboxed on landscape tablet and foldable.

Issue

App doesn't support all display configurations because the app has fixed orientation, fixed aspect ratio, or is not resizable.

Configuration settings that control app orientation and resizability include the following:

  • screenOrientation: Specifies a fixed orientation for an app. Apps can also set orientation at runtime by using Activity#setRequestedOrientation().

  • resizeableActivity: Indicates whether the system can resize apps to fit windows of varying dimensions. On Android 11 (API level 30) and lower, specifies whether apps support multi‑window mode. On Android 12 (API level 31) and higher, specifies whether apps support multi‑window mode on small screens (compact window size class). On Android 12 and higher, apps support multi‑window mode on large screens (medium or expanded window size class) regardless of this setting.

  • maxAspectRatio: Specifies the maximum aspect ratio supported by the app. Only apps with resizeableActivity set to false can set maxAspectRatio.

  • minAspectRatio: Specifies the minimum aspect ratio supported by the app. Only apps with resizeableActivity set to false can set minAspectRatio.

Optimization

App should support all device and multi-window mode display orientations and sizes. Remove all orientation and fixed aspect ratio restrictions from your app layouts and app manifest file.

Compatibility workaround

If an app with fixed orientation or fixed aspect ratio runs in a window where the app does not directly support the window size or orientation, Android letterboxes the app to preserve continuity.

Beginning with Android 12 (API level 31) and continuing with 12L (API level 32), the platform applies a variety of enhancements to letterboxed apps. Device manufacturers implement the UI enhancements. You don't need to do any additional development for your app to benefit from the improvements.

Android 12 (API level 31) introduces the following aesthetic enhancements, which can be configured by device manufacturers:

  • Rounded corners: The corners of the app window have a more refined look.
  • System bar transparency: Status and navigation bars, which overlay the app, are semitransparent, making icons on the bars always viewable over the letterbox background.
  • Configurable aspect ratio: The aspect ratio of the app can be adjusted to improve the app's appearance.

Figure 2. Letterboxed app with UI enhancements.

12L (API level 32) adds the following functional improvements:

  • Configurable positioning: On large screens, device manufacturers can position the app to the left or right side of the display, making interaction easier.

  • Redesigned restart button: Device manufacturers can give the restart button for size compatibility mode a new look for better recognition by users.

Android 13 (API level 33) adds a user education dialog about positioning the letterboxed app on screen or including the letterbox in split‑screen mode:

Figure 3. Letterboxed app with user education dialog.

Size compatibility mode

Size compatibility mode is letterboxing that maintains the app aspect ratio and includes a restart control. The control enables users to restart the app and redraw the display. Android invokes size compatibility mode for apps that are nonresizable. When an activity moves to a display container that is incompatible with the activity's dimensions, the system may rescale the app to fill the device display in at least one dimension.

Device configuration changes that can trigger size compatibility mode include the following:

  • Device rotation
  • Foldable device folding or unfolding
  • Change between full screen and split-screen display modes

Issue

Size compatibility mode typically applies to activities that are restricted in orientation or aspect ratio and are configured (or determined by the system) to be nonresizable.

Your app is considered to be resizable—and won't be placed in size compatibility mode—if it meets any of the following criteria:

If your app does not meet any of the conditions, it is considered not resizable and could be placed in size compatibility mode.

Optimization

App should support all display sizes. Make your app resizable by setting the android:resizeableActivity attribute of the <activity> or <application> element to true in the app manifest. Design responsive/adaptive layouts for your app. For more information, see Support different display sizes and Support multi-window mode.

Compatibility workaround

Android places an app in size compatibility mode when the system determines the display of the letterboxed app can be improved by rescaling the app to fill the display window in at least one dimension. The system displays a restart control which recreates the app process, recreating the activity and redrawing the display. See also Processes and threads overview.

Display compatibility mode

Display compatibility mode prevents an app from restarting when the app moves between different displays, which can trigger a configuration change such as a color mode, touchscreen availability, or screen density change.

Display compatibility mode mode is enabled by default for games (based on the android:appCategory flag) to improve stability and continuity. Unlike size compatibility mode, display compatibility mode does not freeze the app's configuration. The app can still receive all configuration updates through APIs such as the onConfigurationChanged() callback but is spared from a disruptive restart. This means games that properly support APIs such as onConfigurationChanged() can still responsively update their UI even if they are in display compatibility mode.

To opt out of display compatibility mode and handle configuration changes in your app, declare support for the configuration changes in the app's AndroidManifest.xml file, and handle the configuration changes in the onConfigurationChanged() callback.

<activity
    android:name=".MyGameActivity"
    android:configChanges="colorMode|touchscreen|density|...">
    ...
</activity>

Flickering loops

When an app doesn't support all display orientations, it might repeatedly request new orientations when a configuration change occurs, creating an infinite loop that makes the display flicker or the app rotate endlessly.

Issue

On Android 12 (API level 31) and higher, device manufacturers can configure their devices to ignore orientation restrictions specified by apps and instead enforce compatibility modes. For example, a foldable device could ignore an activity's android:screenOrientation="portrait" setting when the activity is displayed on the device's landscape tablet-size, inner screen.

If an app's orientation restrictions are ignored, the app can programmatically set its orientation by calling Activity#setRequestedOrientation(). The call triggers an app restart if the app is not handling configuration changes (see Handle configuration changes). After the restart, the app's orientation restrictions are again ignored, the app repeats the call to setRequestedOrientation(), the call triggers an app restart, and so on in a self-perpetuating loop.

Another way you might encounter this is when the natural orientation (the usual orientation as determined by Android) of a device screen is landscape (that is, calling Display#getRotation() returns Surface.ROTATION_0 while the device has a landscape aspect ratio). Historically, apps have assumed that Display.getRotation() = Surface.ROTATION_0 means the device is in portrait orientation, but this is not always the case, for example, on the inner screen of some foldable devices and on some tablets.

An app in landscape orientation on a foldable inner display, might check the screen rotation, receive a value of ROTATION_0, assume the natural orientation of the device is portrait, and call setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ) to reconfigure the app layout. After the app restarts (in landscape orientation), it might again check the screen rotation, receive a value of ROTATION_0, call setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT), and continue the infinite loop.

Optimization

Apps should not do the following:

  • Set a default orientation with Activity#setRequestedOrientation() in the activity onCreate() method because the orientation request can be triggered unexpectedly by unhandled configuration changes
  • Assume the natural orientation of the device (ROTATION_0) is portrait
  • Set orientation based on signals not related to the current window size such as Display#getRotation(), presence of a FoldingFeature, or deprecated APIs.

Compatibility workaround

Android ignores calls to Activity#setRequestedOrientation() in the following situations:

  • The activity has already relaunched from a previous call to the method or the camera compat force rotation treatment has been enabled (see Camera preview below).

    Device manufacturers can apply this behavior to an app with OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION.

  • The activity made more than two orientation requests in one second, which indicates a loop has occurred. Of the two requests in the loop, Android uses the one that maximizes the app display area.

    Device manufacturers can apply this behavior to an app with OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED.

  • Virtual device owners have overridden the method call on select devices.

Camera preview

The camera preview (or viewfinder) of camera apps can be misaligned or distorted on tablets, laptops, and foldable displays.

Issue

The Android Compatibility Definition Document states that a camera image sensor "MUST be oriented so that the long dimension of the camera aligns with the screen's long dimension."

Apps often assume that device orientation and camera sensor orientation are portrait—a reasonable assumption on standard mobile phones. But the natural orientation of tablets and laptops and their camera sensors can be landscape. Also, new form factors like foldables can have multiple natural orientations and multiple camera sensors in varying orientations.

Starting an activity with a camera orientation the app does not expect or switching between different cameras or device screens (for foldables) can cause a misaligned or distorted camera preview.

Optimization

Camera apps must correctly identify and manage device orientation and camera sensor orientation to present a correctly aligned and scaled camera preview. Apps must calculate device rotation, sensor rotation, and screen or window aspect ratio, and then apply the results to the camera preview. For detailed guidance, see Camera preview and Introducing Camera Viewfinder.

Compatibility workaround

A device is in natural orientation when Display#getRotation() returns Surface.ROTATION_0. The system calculates CameraCharacteristics.SENSOR_ORIENTATION from the device's natural orientation. Android aligns the portrait window of portrait‑restricted apps with the natural orientation of the device, which is what most apps expect. Android also crops the camera sensor image when the sensor orientation is landscape and the camera preview is portrait. The specific workarounds include the following:

  • Force rotate camera previews for portrait-restricted apps: Apps restricted to portrait orientation expect the device's natural orientation and the camera sensor orientation to be portrait. However, on Android 12 (API level 31) and higher, apps can run in multiple device orientations if device manufacturers ignore the orientation specification.

    When a portrait-restricted app is connected to the camera, Android force rotates the app to align the app portrait window with the natural orientation of the device.

    On some tablets (see reference devices), the app portrait window is rotated to full screen portrait to align with the device's natural orientation. The app occupies the full screen after force rotation.

    On the landscape inner screen of foldables (see reference devices), portrait-only activities are rotated to landscape to align with the unfolded natural orientation. The app is letterboxed after force rotation.

  • Inner front camera cropping: The inner front camera sensor on some foldables is in landscape orientation. In addition to force rotating the camera preview on the foldable inner display, Android crops the inner front (landscape) camera field of view so that the sensor captures a view opposite the device orientation.

  • Force refresh camera previews: The system cycles through activity methods onStop() and onStart() (by default) or onPause() and onResume() (applied by the OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE per-app override) after force rotation to make sure the camera preview is properly displayed.

  • Aspect ratio scaling: The system dynamically changes the aspect ratio of the force rotated camera preview to a higher minimum aspect ratio, which ensures the camera preview is properly scaled.

App developers can override these workarounds if the apps handle camera preview correctly. See Per-app overrides.

Commonly misused APIs

As Android has added support for features like multi‑window mode and devices like foldables, legacy APIs have been deprecated and replaced by up‑to‑date APIs that work for all display sizes and device form factors. However, the deprecated APIs are still available for backward compatibility.

Some View APIs are designed for special purposes that are not always well understood by developers.

Issue

Developers continue to use deprecated Display APIs and incorrectly assume the APIs return the app bounds instead of device display area bounds. Or developers mistakenly use special‑purpose view APIs to get general display metrics. The result is miscalculations when repositioning UI elements after app window resizing events, causing layout issues.

Deprecated and commonly misused Display APIs:

For more information, see Support multi-window mode.

Misused view APIs:

Optimization

Never rely on physical display size for positioning UI elements. Migrate your app to APIs based on WindowMetrics, including the following WindowManager APIs:

Compatibility workaround

Two overrides adjust the deprecated Display APIs and misused View APIs to return the app bounds: ALWAYS_SANDBOX_DISPLAY_APIS for Display APIs; OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS for View APIs. ALWAYS_SANDBOX_DISPLAY_APIS is also applied by default to apps that qualify for size compatibility mode.

Transparent activities

Transparent activities are the result of transparent background styles, for example:

<style name="Transparent" parent="AppTheme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
</style>

Themes related to dialogs, such as Theme.MaterialComponents.Dialog, can include styles that make activities transparent.

Transparent activities don't cover all the available display space, which makes them difficult to manage because the available display area can change based on configuration changes like device rotation, device folding and unfolding, and multi‑window mode.

Issue

A transparent activity should conform to the bounds of the first opaque activity below the transparent activity in the task activity stack. However, an opaque activity that launches a permission dialog can be a trampoline (an activity that launches another activity then disappears); and so, the system can't determine the bounds of the trampoline activity that launched the transparent permission dialog activity.

Optimization

Transparent activities inherit their constraints from the top-most opaque activity beneath them in a task's activity stack. The opaque activity must be available for the entire lifecycle of the transparent activity, from activity creation to destruction. For this reason, don't launch permission requests from trampoline activities.

If a trampoline activity launches a permission request, the user might not be able to see the permission dialog because the trampoline activity will have been destroyed before the user has had a chance to respond to the dialog, and the dimensions and position of the dialog activity might have been calculated incorrectly.

Apps should always launch permission requests from activities that remain visible until the user has made a permission decision.

Rounded corners

An activity can be transparent because of a style that specifies background transparency or because the contents of the activity don't fill the available display space. If a transparent activity fills the available display space, the system automatically applies rounded corners to the activity when configured to do so by the device manufacturer. But, if a transparent activity (like a permission dialog) doesn't fill the available space, it's up to you to decide whether or not to apply rounded corners.

Permission dialogs don't fill the available display space because the dialog layout typically uses LayoutParams.WRAP_CONTENT rather than LayoutParams.MATCH_PARENT.

Compatibility workaround

Keep activities that launch dialog activities visible until the user has responded to the dialog.

The system ensures that a transparent activity inherits all constraints from the first opaque activity beneath the transparent activity in the activity stack, including constraints related to:

  • Size compatibility mode
  • Orientation
  • Aspect Ratio

Unity games

Unity games run on Android full screen or in multi‑window mode. However, many Unity games lose focus and stop drawing content when the app is placed in multi‑window mode.

Issue

Unity added a Resizable Window option in Unity 2019.4 to support multi‑window mode on Android. However, the initial implementation did not react to the activity lifecycle in multi-window mode correctly, causing UnityPlayer to suspend playback when the app loses focus. The player rendered a black screen or the last, frozen frame of the game. Gameplay resumed only when the user tapped the screen. Many apps using the Unity engine face this issue and render as a black window in multi‑window mode.

Optimization

Upgrade Unity to 2019.4.40 or later and re‑export your game. Keep the Resizable Window option checked in the Android Player settings, otherwise the game pauses when not in focus even though the game is entirely visible in multi‑window mode.

Compatibility workaround

Device manufacturers can apply the OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS per‑app override to provide a fake focus event to an app in multi‑window mode. The override enables the activity to redraw content and not be blacked out.

Desktop windowing

When apps run in a desktop windowing environment, they may encounter additional compatibility modes.

Apps with locked orientation are freely resizable. Even if an activity is locked to portrait orientation, users can still resize the app to landscape orientation.

Animation of a portrait app being resized to landscape.

However, if an activity is declared as nonresizable (resizeableActivity = false), the activity UI scales while maintaining the same aspect ratio.

Animation of app being resized. UI scales to fill the desktop window.

Camera preview in desktop windowing

When apps in desktop windowing start a camera preview, the viewfinder has its UI scaled while keeping its original aspect ratio. The rest of the app window can be freely resized.

Test your app for compatibility issues

To test your app and understand how it behaves on different form factors, take advantage of the following resources:

Is letterboxed

Verify that each activity can use all of the display space available to the app. First, declare the following code in your test folder:

Kotlin

fun isLetterboxed(activity: AppCompatActivity): Boolean {
    if (isInMultiWindowMode) return false

    val wmc = WindowMetricsCalculator.getOrCreate()
    val currentBounds = wmc.computeCurrentWindowMetrics(this).bounds
    val maxBounds = wmc.computeMaximumWindowMetrics(this).bounds

    val isScreenPortrait = maxBounds.height() > maxBounds.width()

    return if (isScreenPortrait) {
        currentBounds.height() < maxBounds.height()
    } else {
        currentBounds.width() < maxBounds.width()
    }
}

Java

public boolean isLetterboxed(AppCompatActivity activity) {
    if (activity.isInMultiWindowMode()) {
        return false;
    }

    WindowMetricsCalculator wmc = WindowMetricsCalculator.getOrCreate();
    Rect currentBounds = wmc.computeCurrentWindowMetrics(activity).getBounds();
    Rect maxBounds = wmc.computeMaximumWindowMetrics(activity).getBounds();

    boolean isScreenPortrait = maxBounds.height() > maxBounds.width();

    return (isScreenPortrait)
        ? currentBounds.height() < maxBounds.height()
        : currentBounds.width() < maxBounds.width();
}

Then run a test to assert the behavior and make sure the target activity is not letterboxed:

Kotlin

@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)

@Test
fun activity_launched_notLetterBoxed() {
    activityRule.scenario.onActivity {
        assertFalse(it.isLetterboxed())
    }
}

Java

@Rule
public ActivityScenarioRule<MainActivity> rule = new ActivityScenarioRule<>(MainActivity.class);

@Test
public void activity_launched_notLetterBoxed() {
    try (ActivityScenario<MainActivity> scenario =
        ActivityScenario.launch(MainActivity.class)) {
            scenario.onActivity( activity -> {
                assertFalse(activity.isLetterboxed());
            });
        }
}

Ideally, run this kind of test only until it passes and asserts that your app's activities take up the entire display space available to the app. Test your app on all device types to ensure consistent behavior.

Per-app overrides

Android provides overrides that change the configured behavior of apps. For example, the FORCE_RESIZE_APP override instructs the system to bypass size compatibility mode and resize the app to fit display dimensions even if resizeableActivity="false" is specified in the app manifest.

Device manufacturers apply overrides to select apps—or all apps—on specific large screen devices. On Android 14 (API level 34) and higher, users can apply overrides to apps through device settings. On Android 16 (API level 36) and higher, virtual device owners apply overrides on select devices the virtual device owners manage.

User per-app overrides

On Android 14 and higher, a settings menu enables users to change the aspect ratio of apps. Large screen devices such as the reference devices implement the menu.

The menu contains a list of all apps installed on the device. Users choose an app and then set the app aspect ratio to 3:4, 1:1, full screen, or other value configured by the device manufacturer. Users can also reset the aspect ratio to the app default, which is specified in the app manifest.

Apps can opt out of the compatibility override by setting the following PackageManager.Property tags:

  • PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE

    To opt out of the user aspect ratio compatibility override, add the property to your app manifest and set the value to false:

    <application>
        <property
            android:name="android.window.
            PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"
            android:value="false" />
    </application>
    

    Your app will be excluded from the list of apps in device settings. Users won't be able to override the app's aspect ratio.

    Setting the property to true has no effect.

  • PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE

    To opt out of the full-screen option of the user aspect ratio compatibility override, add the property to your app manifest and set the value to false:

    <application>
        <property
            android:name="android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE"
            android:value="false" />
    </application>
    

    The full-screen option is removed from the list of aspect ratio options in device settings. Users won't be able to apply the full-screen override to your app.

    Setting this property to true has no effect.

Optimize your app for all screens: Don't set aspect ratio restrictions in your app. Use window size classes to support different layouts based on the amount of available display space.

Device per-app overrides

Device manufacturers and virtual device owners (select trusted and privileged apps) apply overrides on a per‑app basis on specific devices, including tablets, foldables, ChromeOS devices, and car displays. The reference devices may apply some of the overrides to a variety of apps by default.

Apps can opt out of most overrides (see the Per-app overrides table below).

You can test your app with overrides enabled or disabled using the compatibility framework (see Compatibility framework tools). When enabled, overrides apply to the entire app.

You can also use the Android Debug Bridge (adb) to enable or disable overrides and determine which overrides apply to your app.

Enable or disable overrides as follows:

adb shell am compat enable/disable <override name/id> <package>

For the reference devices, check which overrides apply to your app:

adb shell dumpsys platform_compat | grep <package name>

The following table lists available overrides along with guidance on how to optimize your app so the app does not need to rely on overrides. You can add property flags to your app manifest to opt out of some overrides.

Per-app overrides
Type Name ID Description
Resizability FORCE_RESIZE_APP 174042936 Bypasses size compatibility mode for app on configuration changes.
FORCE_NON_RESIZE_APP 181136395 Forces app into size compatibility mode on configuration changes.
Aspect ratio OVERRIDE_MIN_ASPECT_RATIO 174042980 Gatekeeper override that must be enabled to apply any other aspect ratio overrides.
OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY 203647190 If enabled (the default), limits override scope to portrait-only activities.