Foldable devices offer unique viewing experiences. Rear display mode and dual‑screen mode enable you to build special display features for foldable devices such as rear‑camera selfie preview and simultaneous but different displays on inner and outer screens.

## Rear display mode

Typically when a foldable device is unfolded, only the inner screen is active. Rear display mode lets you move an activity to the outer screen of a foldable device, which usually faces away from the user while the device is unfolded. The inner display automatically turns off.

A novel application is to display the camera preview on the outer screen, so users can take selfies with the rear camera, which usually provides much better picture‑taking performance than the front camera.

To activate rear display mode, users respond to a dialog to allow the app to switch screens, for example:
![](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/foldables/rear-display-dialog.png)**Figure 1.**System dialog to allow starting rear display mode.

The system creates the dialog, so no development on your part is required. Different dialogs appear depending on the device state; for example, the system directs users to unfold the device if the device is closed. You can't customize the dialog, and it can vary on devices from different OEMs.

You can try out rear display mode with the Pixel Fold camera app. See a sample implementation in the codelab[Optimize your camera app on foldable devices with Jetpack WindowManager](https://developer.android.com/codelabs/android-camera-foldables).

## Dual-screen mode

Dual-screen mode lets you show content on both displays of a foldable at the same time. Dual‑screen mode is available on Pixel Fold running Android 14 (API level 34) or higher.

An example use case is the dual-screen interpreter.
![](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/foldables/dual-screen-interpreter.png)**Figure 2.**Dual-screen interpreter showing different content on front and rear displays.

## Enable the modes programmatically

You can access rear display mode and dual‑screen mode through the[Jetpack WindowManager](https://developer.android.com/jetpack/androidx/releases/window)APIs, starting from library version 1.2.0-beta03.

Add the WindowManager dependency to your app's module`build.gradle`file:  

### Groovy

    dependencies {
        // TODO: Define window_version in your project's build configuration.
        implementation "androidx.window:window:$window_version"
    }

### Kotlin

    dependencies {
        // Define window_version in your project's build configuration.
        implementation("androidx.window:window:$window_version")
    }

The entry point is the[`WindowAreaController`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaController), which provides the information and behavior related to moving windows between displays or between display areas on a device.`WindowAreaController`lets you query the list of available[`WindowAreaInfo`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaInfo)objects.

Use`WindowAreaInfo`to access the[`WindowAreaSession`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaSession), an interface that represents an active window area feature. Use`WindowAreaSession`to determine the availability of a specific[`WindowAreaCapability`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaCapability).

Each capability is related to a particular[`WindowAreaCapability.Operation`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaCapability.Operation). In version 1.2.0-beta03, Jetpack WindowManager supports two kinds of operations:

- [`WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaCapability.Operation#OPERATION_PRESENT_ON_AREA()), which is used to start dual‑screen mode
- [`WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaCapability.Operation#OPERATION_TRANSFER_ACTIVITY_TO_AREA()), which is used to start rear display mode

Here's an example of how to declare variables for rear display mode and dual‑screen mode in your app's main activity:  

### Kotlin

    private lateinit var windowAreaController: WindowAreaController
    private lateinit var displayExecutor: Executor
    private var windowAreaSession: WindowAreaSession? = null
    private var windowAreaInfo: WindowAreaInfo? = null
    private var capabilityStatus: WindowAreaCapability.Status =
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED

    private val dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
    private val rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA

### Java

    private WindowAreaControllerCallbackAdapter windowAreaController = null;
    private Executor displayExecutor = null;
    private WindowAreaSessionPresenter windowAreaSession = null;
    private WindowAreaInfo windowAreaInfo = null;
    private WindowAreaCapability.Status capabilityStatus  =
            WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED;

    private WindowAreaCapability.Operation dualScreenOperation =
            WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA;
    private WindowAreaCapability.Operation rearDisplayOperation =
            WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA;

Here's how to initialize the variables in the`onCreate()`method of your activity:
**Note:** The Kotlin code uses the[`Flow`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)approach of[`WindowAreaController.windowAreaInfos`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaController#windowAreaInfos()), while the Java code is based on[`WindowAreaControllerCallbackAdapter`](https://developer.android.com/reference/androidx/window/java/area/WindowAreaControllerCallbackAdapter).  

### Kotlin

    displayExecutor = ContextCompat.getMainExecutor(this)
    windowAreaController = WindowAreaController.getOrCreate()

    lifecycleScope.launch(Dispatchers.Main) {
        lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
            windowAreaController.windowAreaInfos
                .map { info -> info.firstOrNull { it.type == WindowAreaInfo.Type.TYPE_REAR_FACING } }
                .onEach { info -> windowAreaInfo = info }
                .map { it?.getCapability(operation)?.status ?: WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED }
                .distinctUntilChanged()
                .collect {
                    capabilityStatus = it
                }
        }
    }

### Java

    displayExecutor = ContextCompat.getMainExecutor(this);
    windowAreaController = new WindowAreaControllerCallbackAdapter(WindowAreaController.getOrCreate());
    windowAreaController.addWindowAreaInfoListListener(displayExecutor, this);

    windowAreaController.addWindowAreaInfoListListener(displayExecutor,
      windowAreaInfos -> {
        for(WindowAreaInfo newInfo : windowAreaInfos){
            if(newInfo.getType().equals(WindowAreaInfo.Type.TYPE_REAR_FACING)){
                windowAreaInfo = newInfo;
                capabilityStatus = newInfo.getCapability(presentOperation).getStatus();
                break;
            }
        }
    });

Before starting an operation, check the availability of the particular capability:  

### Kotlin

    when (capabilityStatus) {
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED -> {
          // The selected display mode is not supported on this device.
        }
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE -> {
          // The selected display mode is not available.
        }
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> {
          // The selected display mode is available and can be enabled.
        }
        WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE -> {
          // The selected display mode is already active.
        }
        else -> {
          // The selected display mode status is unknown.
        }
    }

### Java

    if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED)) {
      // The selected display mode is not supported on this device.
    }
    else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE)) {
      // The selected display mode is not available.
    }
    else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) {
      // The selected display mode is available and can be enabled.
    }
    else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE)) {
      // The selected display mode is already active.
    }
    else {
      // The selected display mode status is unknown.
    }

### Dual-screen mode

The following example closes the session if the capability is already active, or otherwise calls the[`presentContentOnWindowArea()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaController#presentContentOnWindowArea(android.os.Binder,android.app.Activity,java.util.concurrent.Executor,androidx.window.area.WindowAreaPresentationSessionCallback))function:  

### Kotlin

    fun toggleDualScreenMode() {
        if (windowAreaSession != null) {
            windowAreaSession?.close()
        }
        else {
            windowAreaInfo?.token?.let { token ->
                windowAreaController.presentContentOnWindowArea(
                    token = token,
                    activity = this,
                    executor = displayExecutor,
                    windowAreaPresentationSessionCallback = this
                )
            }
        }
    }

### Java

    private void toggleDualScreenMode() {
        if(windowAreaSession != null) {
            windowAreaSession.close();
        }
        else {
            Binder token = windowAreaInfo.getToken();
            windowAreaController.presentContentOnWindowArea( token, this, displayExecutor, this);
        }
    }

Notice the use of the app's main activity as the[`WindowAreaPresentationSessionCallback`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaPresentationSessionCallback)argument.

The API uses a listener approach: when you make a request to present the content to the other display of a foldable, you initiate a session that is returned through the listener's[`onSessionStarted()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaPresentationSessionCallback#onSessionStarted(androidx.window.area.WindowAreaSessionPresenter))method. When you close the session, you get a confirmation in the[`onSessionEnded()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaPresentationSessionCallback#onSessionEnded(kotlin.Throwable))method.

To create the listener, implement the`WindowAreaPresentationSessionCallback`interface:  

### Kotlin

    class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback

### Java

    public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback

| **Note:** `WindowAreaPresentationSessionCallback`is a Java API located in the`androidx.window:window`package (rather than`androidx.window:window-java`) to enable Kotlin access.

The listener needs to implement the`onSessionStarted()`,`onSessionEnded(),`and[`onContainerVisibilityChanged()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaPresentationSessionCallback#onContainerVisibilityChanged(kotlin.Boolean))methods. The callback methods notify you of the session status and enable you to update the app accordingly.

The`onSessionStarted()`callback receives a[`WindowAreaSessionPresenter`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaSessionPresenter)as an argument. The argument is the container that lets you access a window area and show content. The presentation can be automatically dismissed by the system when the user leaves the primary application window, or the presentation can be closed by calling[`WindowAreaSessionPresenter#close()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaSession#close()).

For the other callbacks, for simplicity, just check in the function body for any errors, and log the state:  

### Kotlin

    override fun onSessionStarted(session: WindowAreaSessionPresenter) {
        windowAreaSession = session
        val view = TextView(session.context)
        view.text = "Hello world!"
        session.setContentView(view)
    }

    override fun onSessionEnded(t: Throwable?) {
        if(t != null) {
            Log.e(logTag, "Something was broken: ${t.message}")
        }
    }

    override fun onContainerVisibilityChanged(isVisible: Boolean) {
        Log.d(logTag, "onContainerVisibilityChanged. isVisible = $isVisible")
    }

### Java

    @Override
    public void onSessionStarted(@NonNull WindowAreaSessionPresenter session) {
        windowAreaSession = session;
        TextView view = new TextView(session.getContext());
        view.setText("Hello world, from the other screen!");
        session.setContentView(view);
    }

    @Override public void onSessionEnded(@Nullable Throwable t) {
        if(t != null) {
            Log.e(logTag, "Something was broken: ${t.message}");
        }
    }

    @Override public void onContainerVisibilityChanged(boolean isVisible) {
        Log.d(logTag, "onContainerVisibilityChanged. isVisible = " + isVisible);
    }

To maintain consistency across the ecosystem, use the[*Dual Screen*official icon](https://fonts.google.com/icons?query=dua&selected=Material+Symbols+Outlined:dual_screen:FILL@0;wght@400;GRAD@0;opsz@24&icon.query=dual+screen&icon.platform=android)to indicate to users how to enable or disable dual‑screen mode.

For a working sample, see[DualScreenActivity.kt](https://github.com/android/platform-samples/blob/main/samples/user-interface/windowmanager/src/main/java/com/example/platform/ui/windowmanager/DualScreenActivity.kt).

### Rear display mode

Similar to the dual‑screen mode example, the following example of a`toggleRearDisplayMode()`function closes the session if the capability is already active, or otherwise calls the[`transferActivityToWindowArea()`](https://developer.android.com/reference/kotlin/androidx/window/area/WindowAreaController#transferActivityToWindowArea(android.os.Binder,android.app.Activity,java.util.concurrent.Executor,androidx.window.area.WindowAreaSessionCallback))function:  

### Kotlin

    fun toggleRearDisplayMode() {
        if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) {
            if(windowAreaSession == null) {
                windowAreaSession = windowAreaInfo?.getActiveSession(
                    operation
                )
            }
            windowAreaSession?.close()
        } else {
            windowAreaInfo?.token?.let { token ->
                windowAreaController.transferActivityToWindowArea(
                    token = token,
                    activity = this,
                    executor = displayExecutor,
                    windowAreaSessionCallback = this
                )
            }
        }
    }

### Java

    void toggleRearDisplayMode() {
        if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) {
            if(windowAreaSession == null) {
                windowAreaSession = windowAreaInfo.getActiveSession(
                    operation
                )
            }
            windowAreaSession.close();
        }
        else {
            Binder token = windowAreaInfo.getToken();
            windowAreaController.transferActivityToWindowArea(token, this, displayExecutor, this);
        }
    }

In this case, the activity displayed is used as a`WindowAreaSessionCallback`, which is simpler to implement because the callback doesn't receive a presenter that allows showing content on a window area but instead transfers the whole activity to another area:  

### Kotlin

    override fun onSessionStarted() {
        Log.d(logTag, "onSessionStarted")
    }

    override fun onSessionEnded(t: Throwable?) {
        if(t != null) {
            Log.e(logTag, "Something was broken: ${t.message}")
        }
    }

### Java

    @Override public void onSessionStarted(){
        Log.d(logTag, "onSessionStarted");
    }

    @Override public void onSessionEnded(@Nullable Throwable t) {
        if(t != null) {
            Log.e(logTag, "Something was broken: ${t.message}");
        }
    }

To maintain consistency across the ecosystem, use the[*Rear Camera*official icon](https://fonts.google.com/icons?query=dua&selected=Material+Symbols+Outlined:rear_camera:FILL@0;wght@400;GRAD@0;opsz@24&icon.query=rear&icon.platform=android)to indicate to users how to enable or disable rear display mode.

## Additional resources

- [Optimize your camera app on foldable devices with Jetpack WindowManager](https://developer.android.com/codelabs/android-camera-foldables)codelab
- [`androidx.window.area`](https://developer.android.com/reference/androidx/window/area/package-summary)package summary
- Jetpack WindowManager sample code:
  - [DualScreenActivity.kt](https://github.com/android/platform-samples/blob/main/samples/user-interface/windowmanager/src/main/java/com/example/platform/ui/windowmanager/DualScreenActivity.kt)
  - [RearDisplayModeActivity.kt](https://github.com/android/platform-samples/blob/main/samples/user-interface/windowmanager/src/main/java/com/example/platform/ui/windowmanager/RearDisplayModeActivity.kt)