PIP 모드

Android 휴대기기의 PIP(picture-in-picture) 기능을 사용하면 활동을 지속 중인 앱을 작은 창으로 전환할 수 있습니다. PIP가 동영상 앱에 특히 유용한 이유는 콘텐츠가 계속해서 재생해는 동안에도 사용자가 자유롭게 다른 작업을 수행할 수 있기 때문입니다. 사용자는 SystemUI를 통해 이 창의 위치를 변경하고 현재 앱에서 제공하는 작업(최대 3개)을 수행 중인 PIP 모드의 애플리케이션과 상호작용할 수 있습니다.

PIP에는 해당 기능을 지원하고 활동별 기준으로 작동하는 애플리케이션의 명시적인 선택이 요구됩니다. 한 애플리케이션에는 여러 개의 활동이 포함될 수 있으며, 여기서 하나만 PIP입니다. 활동은 enterPictureInPictureMode()를 호출하여 PIP 전환을 요청하며, onPictureInPictureModeChanged() 형식의 활동 콜백을 수신합니다.

setPictureInPictureParams() 메서드는 활동이 PIP 및 맞춤 작업 상태에서 가로 세로 비율을 제어할 수 있게 해주며, 덕분에 사용자는 확장 없이 활동과 상호작용할 수 있습니다. PIP에서는 활동이 일시중지 상태이지만 계속해서 렌더링되며, 터치 입력 또는 창 포커스를 직접적으로 수신하지 않습니다. 한 번에 하나의 작업만 PIP 모드일 수 있습니다.

자세한 내용은 Android 개발자 PIP(Picture-in-picture) 문서를 참고하세요.

기기 요구사항

PIP를 지원하려면 /android/frameworks/base/core/java/android/content/pm/PackageManager.java에서 PackageManager#FEATURE_PICTURE_IN_PICTURE 시스템 기능을 사용 설정합니다. PIP를 지원하는 기기에는 가장 작은 너비가 200dp를 초과하는 큰 화면이 있어야 합니다. 화면 분할 멀티 윈도우처럼 PIP는 화면에서 여러 활동을 동시에 실행할 수 있게 해줍니다. 따라서 기기의 CPU 및 RAM은 이러한 사용 사례를 지원할 수 있을 만큼 충분해야 합니다.

구현

활동 수명 주기 관리의 대부분은 시스템에서 ActivityManagerWindowManager 사이에 실행됩니다. 참조 UI 구현은 SystemUI 패키지에 있습니다.

시스템 수정사항은 호환성 테스트 모음(CTS) 테스트에 의해 정의된 것처럼 시스템의 근본적인 동작에 영향을 미치면 안 됩니다. PIP의 시스템 논리는 기본적으로 '고정된' 스택 내의 작업 및 활동 관리를 중심으로 이루어집니다. 다음은 간단한 클래스 개요입니다.

  • ActivityRecord: 활동의 PIP(picture-in-picture) 상태를 추적합니다. 특정 상황에서 사용자가 PIP 모드로 전환되지 않도록 하려면(예: 잠금 화면 또는 VR 도중) checkEnterPictureInPictureState()에 사례를 추가합니다.
  • ActivityManagerService: PIP 모드로의 전환을 요청하기 위한 활동의 기본 인터페이스, 그리고 PIP 활동 상태를 변경하기 위한 WindowManagerSystemUI의 호출 인터페이스입니다.
  • ActivityStackSupervisor: ActivityManagerService에서 호출되어 고정된 스택 안팎으로 태스크를 이동하고, 필요에 따라 WindowManager를 업데이트합니다.
  • PinnedStackWindowController: ActivityManagerWindowManager 인터페이스입니다.
  • PinnedStackController: 시스템의 변경사항을 SystemUI에 보고합니다(표시된/숨겨진 IME, 변경된 가로 세로 비율 또는 변경된 작업 등).
  • BoundsAnimationController: 크기 변경 도중 구성 변경을 트리거하지 않는 방식으로 PIP 활동 창에 애니메이션을 적용합니다.
  • PipSnapAlgorithm: 시스템 및 SystemUI에 사용되는 공유된 클래스입니다. 화면 가장자리 근처 PIP 창의 맞추기 동작을 제어합니다.

참조 SystemUI는 확장 및 해제처럼 사용자 및 일반 변경에 대한 맞춤 작업 표시를 지원하는 온전한 PIP 구현을 제공합니다. 이 변경사항이 CDD에 의해 정의되는 근본적인 동작에 영향을 미치지 않는 한, 기기 제조업체는 이 변경사항을 기반으로 할 수 있습니다. 다음은 간단한 클래스 개요입니다.

  • PipManager: SystemUI로 시작하는 SystemUI 구성요소입니다.
  • PipTouchHandler: PIP를 조작하는 동작을 제어하는 터치 핸들러입니다. PIP의 입력 소비자가 활성 상태인 경우에만 사용됩니다(InputConsumerController 참조). 여기에서 새 동작을 추가할 수 있습니다.
  • PipMotionHelper: PIP 위치와 화면의 허용되는 부분을 추적하는 편의성 클래스입니다. ActivityManagerService를 통해 호출하여 PIP 위치 및 크기를 업데이트하거나 애니메이션을 적용합니다.
  • PipMenuActivityController: 현재 PIP의 활동에 의해 제공되는 작업을 표시하는 활동을 시작합니다. 이 활동은 작업 오버레이 활동이며, 오버레이된 입력 소비자를 제거하여 상호작용을 허용합니다.
  • PipMenuActivity: 메뉴 활동의 구현입니다.
  • PipMediaController: PIP의 기본 작업에 영향을 줄 수 있는 방식으로 미디어 세션이 변경될 때 SystemUI를 업데이트하는 리스너입니다.
  • PipNotificationController: 사용자가 PIP 기능을 사용하는 동안 알림이 활성화되도록 하는 컨트롤러입니다.
  • PipDismissViewController: 사용자가 PIP와 상호작용을 시작하면 사용자가 PIP를 해제할 수 있다고 표시하기 위해 표시되는 오버레이입니다.

기본 게재위치

PIP의 기본 게재위치를 제어하는 다양한 시스템 리소스가 있습니다.

  • config_defaultPictureInPictureGravity: PIP를 배치할 모서리를 제어하는 중력 정수입니다(예: BOTTOM|RIGHT).
  • config_defaultPictureInPictureScreenEdgeInsets: PIP 배치를 위한 화면 측면의 오프셋입니다.
  • config_pictureInPictureDefaultSizePercentconfig_pictureInPictureDefaultAspectRatio: 화면 너비 및 가로 세로 비율의 조합은 PIP 크기를 제어합니다. 계산된 기본 PIP 크기는 CTS 및 CDD에 의해 정의된 @dimen/default_minimal_size_pip_resizable_task보다 작을 수 없습니다.
  • config_pictureInPictureSnapMode: PipSnapAlgorithm에 정의된 맞추기 동작입니다.

기기 구현은 CDD 및 CTS에 정의된 최소 및 최대 가로 세로 비율을 변경하면 안 됩니다.

권한

AppOpsManager(master/core/java/android/app/AppOpsManager.java)의 패키지별 '애플리케이션 작업'(OP_PICTURE_IN_PICTURE)을 사용하면 사용자가 시스템 설정을 통해 애플리케이션별로 PIP를 제어할 수 있습니다. 기기 구현은 활동이 PIP 모드 전환을 요청할 때 이러한 확인 내용을 적용해야 합니다.

테스트

PIP 구현을 테스트하려면 /cts/hostsidetests/services/activitymanager 아래에서, 특히 ActivityManagerPinnedStackTests.java에서 호스트 측 CTS 테스트에 있는 모든 PIP 관련 테스트를 실행합니다.