Android 8.0 includes support for picture-in-picture (PIP) for Android handheld devices. PIP allows users to resize an app with an ongoing activity into a small window. PIP is especially useful for video apps because content continues to play while the user is free to perform other actions. Users can manipulate this window's position through the SystemUI and interact with the application currently in picture-in-picture with (up to three) app-provided actions.
More information is available in the Android Developer Picture-in-picture documentation.
PIP requires explicit opt-in from applications that support it and works on a
per-activity basis. (A single application can have multiple activities, only one
of which is in PIP.) Activities request to enter picture-in-picture by calling
enterPictureInPictureMode(), and receive activity callbacks in the
Android 8.0 added additional methods, including
setPictureInPictureParams(), which lets activities control their
aspect ratio while in PIP and custom actions, which allow users to interact with
the activity without having to expand it. In PIP, the activity is in a paused,
but rendering, state and does not directly receive touch input or window focus.
Only a single task can be in PIP at a time.
To support PIP, enable the
PackageManager#FEATURE_PICTURE_IN_PICTURE system feature in
Devices that support PIP must have a screen that is larger than 220dp at its
smallest width. Similar to split screen multi-window, PIP allows multiple
activities to run on-screen at the same time. Therefore, devices should have
sufficient CPU and RAM to support this use case.
Modifications to the system should not affect its intrinsic behavior as defined by the Compatibility Test Suite (CTS) tests. The system logic for PIP mainly revolves around the management of tasks and activities within the "pinned" stack. Here is a quick class overview:
ActivityRecord: tracks each activity's picture-in-picture state. To prevent users from entering PIP in certain circumstances, such as from the lock screen or during VR, add cases to
ActivityManagerService: the primary interface from the activity to request entering PIP and the interface to calls from
SystemUIto change the PIP activity state.
ActivityStackSupervisor: called from the
ActivityManagerServiceto move tasks in or out of the pinned stack, updating the
PinnedStackController: reports changes in the system to
SystemUI, such as IME shown/hidden, aspect ratio changed, or actions changed.
BoundsAnimationController: animates the PIP activity windows in a way that does not trigger a configuration change while resizing.
PipSnapAlgorithm: a shared class used in both the system and SystemUI that controls the snapping behaviour of the PIP window near the edges of the screen.
provides a complete implementation of PIP that supports presenting custom
actions to users and general manipulation, such as expansion and dismissal.
Device manufacturers can build upon these changes, as long as they do not affect
the intrinsic behaviours as defined by the CDD. Here is a quick class
SystemUIcomponent that is started with
PipTouchHandler: the touch handler, which controls the gestures that manipulate the PIP. This is only used while the input consumer for the PIP is active (see
InputConsumerController). New gestures can be added here.
PipMotionHelper: a convenience class that tracks the PIP position, and allowable region on-screen. Calls through to
ActivityManagerServiceto update or animate the position and size of the PIP.
PipMenuActivityController: starts an activity that shows the actions provided by the activity currently in PIP. This activity is a task-overlay activity, and removes the overlaying input consumer to allow it to be interactive.
PipMenuActivity: the implementation for the menu activity.
PipMediaController: the listener that updates
SystemUIwhen the media session changes in a way that might affect the default actions on the PIP.
PipNotificationController: the controller that ensures that a notification is active while a user is using the PIP feature.
PipDismissViewController: the overlay shown to users when they start interacting with the PIP to indicate that it can be dismissed.
There are various system resources that control the default placement of the PIP:
config_defaultPictureInPictureGravity: the gravity integer, which controls the corner to place the PIP, such as
config_defaultPictureInPictureScreenEdgeInsets: the offsets from the sides of the screen to place the PIP.
config_pictureInPictureDefaultAspectRatio: the combination of percentage of the screen width and the aspect ratio controls the size of the PIP. The computed default PIP size should not be smaller than
@dimen/default_minimal_size_pip_resizable_task, as defined by CTS and the CDD.
config_pictureInPictureSnapMode: the snapping behaviour as defined in
Device implementations should not change the minimum and maximum aspect ratios that are defined in the CDD and CTS.
Android 8.0 added a per-package "application operation"
master/core/java/android/app/AppOpsManager.java), which allows
users to control PIP on a per-application level through the system settings.
Device implementations need to respect this check when an activity requests to
enter picture-in-picture mode.
To test PIP implementations, run all picture-in-picture related tests found in
the host-side CTS tests under