Apps for foldable and multi-screen devices
Generally, apps should not rely on static identifiers or logic that depends on some display IDs. In most cases, apps should resize and work on different displays and the system should control where to locate apps. For example, to build a new and unique experience for foldable devices and launch a special app on the external screen when the device is folded.
In this case, SystemUI (or another system component) should detect the fold, determine if it's appropriate to perform an action, and then launch the target activity and specify an external display ID as the launch target. Apps shouldn't detect this action or perform any action in response and then perform the launch on a specific display. In other words, do not assume that what works on one device will work on other devices. In short, device-specific code increases fragmentation.
Restrict access to displays
If the device configuration requires the restriction of access to one or more
displays, the recommendation is to use the Display#FLAG_PRIVATE
flag
to designate such displays as private. Doing so restricts all but the
owner from adding content to the display. Any attempt to launch an activity or to
add a window by anyone but the owner results in a SecurityException
.
If the system owns the display, the system can add windows and launch activities.
In addition, entities placed on a display can always access that display. If the owner launches an activity on a display, then the activity can launch other activities on this display. As a result, the owner is responsible for restricting access and allowing trusted apps only.
In addition, more restrictions are added to virtual displays because any app can
create one without making it visible to the user. If the virtual display isn't
owned by the system, then only activities with
allowEmbedded
are permitted and the caller should have the ACTIVITY_EMBEDDING
permission.
For more information, see:
ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()
ActivityDisplay#isUidPresent()
DisplayManagerService#isUidPresentOnDisplay()
To conditionally control activity launches, use LaunchParamsController
,
which intercepts all activity launches and allows a system component to modify the
parameters used for launch. This is available in system_server
.
Configure display windowing settings and system decorations
System decorations can
be configured per display in DisplayWindowSettings
. A device
implementation can provide a default configuration in
/data/system/display_settings.xml
.
This value determines whether system decorations (launcher, wallpaper,
navigation bar, and other decor windows) and the IME appear on a display.
For details, see DisplayWindowSettings#shouldShowSystemDecorsLocked()
and DisplayWindowSettings#shouldShowImeLocked()
.
To identify the display, use either a unique ID (this default uses
DisplayInfo#uniqueId
) or a physical port ID for hardware
displays (see DisplayInfo#address
).
For example, the following display config example enables system decorations and the IME on a simulated display:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="0" /> <display name="overlay:1" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
In the example above, uniqueId
is used for display identification
in the name attribute, which for a simulated display is overlay:1
.
For a built-in display, a sample value may be "local:45354385242535243453"
.
Another option is to use hardware port information and set identifier="1"
to correspond to DisplayWindowSettings#IDENTIFIER_PORT
and then update the
name to use the "port:<port_id>"
format:
<?xmlversion='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="1" /> <display name="port:12345" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
For details, see Static display identifiers.
For more information, see: