1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.photopicker.features.preview 18 19 import android.os.Bundle 20 import android.provider.ICloudMediaSurfaceController 21 import android.view.Surface 22 23 /** 24 * A wrapper class around [ICloudMediaSurfaceController]. 25 * 26 * This class just proxies all calls through to the wrapped controller. 27 * Additionally, this Controller provides methods for the UI for obtaining 28 * surfaceId's and manages calling the [onPlayerCreate] and [onPlayerRelease] 29 * based on the number of active surfaces. 30 * 31 * @property wrapped the [ICloudMediaSurfaceController] to wrap. 32 */ 33 class RemoteSurfaceController(private val wrapped: ICloudMediaSurfaceController) : 34 ICloudMediaSurfaceController.Stub() { 35 36 /** The next unique surface id for this controller */ 37 private var nextSurfaceId: Int = 0 38 39 /** 40 * The total number of active surfaces for this controller. 41 * This count is increased during [onSurfaceCreated] and decreased 42 * during [onSurfaceDestroyed]. 43 */ 44 private var activeSurfaceCount: Int = 0 45 46 /** Get a new surfaceId for a new player surface */ getNextSurfaceIdnull47 fun getNextSurfaceId(): Int { 48 return ++nextSurfaceId 49 } 50 51 /** 52 * Pass through of the Surface's [onSurfaceChanged] lifecycle. 53 * 54 * Additionally, this method manages creating the player if it is required. 55 */ onSurfaceCreatednull56 override fun onSurfaceCreated(surfaceId: Int, surface: Surface, mediaId: String) { 57 58 if (activeSurfaceCount == 0) { 59 // If this is the first surface being created for this controller, 60 // the player needs to be initialized. 61 onPlayerCreate() 62 } 63 64 activeSurfaceCount++ 65 wrapped.onSurfaceCreated(surfaceId, surface, mediaId) 66 } 67 68 /** 69 * Pass through of the Surface's [onSurfaceChanged] lifecycle. 70 */ onSurfaceChangednull71 override fun onSurfaceChanged(surfaceId: Int, format: Int, width: Int, height: Int) { 72 wrapped.onSurfaceChanged(surfaceId, format, width, height) 73 } 74 75 /** 76 * Pass through of the Surface's [onSurfaceDestroyed] lifecycle. 77 */ onSurfaceDestroyednull78 override fun onSurfaceDestroyed(surfaceId: Int) { 79 wrapped.onSurfaceDestroyed(surfaceId) 80 81 if (--activeSurfaceCount == 0) { 82 // If there are no active surfaces left, release the player. 83 onPlayerRelease() 84 } 85 } 86 onMediaPlaynull87 override fun onMediaPlay(surfaceId: Int) { 88 wrapped.onMediaPlay(surfaceId) 89 } 90 onMediaPausenull91 override fun onMediaPause(surfaceId: Int) { 92 wrapped.onMediaPause(surfaceId) 93 } 94 onMediaSeekTonull95 override fun onMediaSeekTo(surfaceId: Int, timestampMillis: Long) { 96 wrapped.onMediaSeekTo(surfaceId, timestampMillis) 97 } 98 onConfigChangenull99 override fun onConfigChange(bundle: Bundle) { 100 wrapped.onConfigChange(bundle) 101 } 102 onDestroynull103 override fun onDestroy() { 104 wrapped.onDestroy() 105 } 106 onPlayerCreatenull107 override fun onPlayerCreate() { 108 wrapped.onPlayerCreate() 109 } onPlayerReleasenull110 override fun onPlayerRelease() { 111 wrapped.onPlayerRelease() 112 } 113 } 114