1 /* 2 * Copyright (C) 2022 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.server.wm; 18 19 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONTENT_RECORDING; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.view.ContentRecordingSession; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.internal.protolog.common.ProtoLog; 27 28 /** 29 * Orchestrates the handoff between displays if the recording session changes, and keeps track of 30 * the current recording session state. Only supports one content recording session on the device at 31 * once. 32 */ 33 final class ContentRecordingController { 34 35 /** 36 * The current recording session. 37 */ 38 @Nullable 39 private ContentRecordingSession mSession = null; 40 41 @Nullable 42 private DisplayContent mDisplayContent = null; 43 44 /** 45 * Returns the current recording session. If returns {@code null}, then recording is not taking 46 * place. 47 */ 48 @Nullable 49 @VisibleForTesting getContentRecordingSessionLocked()50 ContentRecordingSession getContentRecordingSessionLocked() { 51 // Copy out the session, to allow it to be modified without updating this reference. 52 return mSession; 53 } 54 55 /** 56 * Updates the current recording session. If a new display is taking over recording, then 57 * stops the prior display from recording. 58 * 59 * @param incomingSession the new recording session. Should either have a {@code null} token, to 60 * stop the current session, or a session on a new/different display 61 * than the current session. 62 * @param wmService the window manager service 63 */ setContentRecordingSessionLocked(@ullable ContentRecordingSession incomingSession, @NonNull WindowManagerService wmService)64 void setContentRecordingSessionLocked(@Nullable ContentRecordingSession incomingSession, 65 @NonNull WindowManagerService wmService) { 66 if (incomingSession != null && (!ContentRecordingSession.isValid(incomingSession) 67 || ContentRecordingSession.isSameDisplay(mSession, incomingSession))) { 68 // Ignore an invalid session, or a session for the same display as currently recording. 69 return; 70 } 71 DisplayContent incomingDisplayContent = null; 72 if (incomingSession != null) { 73 // Recording will start on a new display, possibly taking over from a current session. 74 ProtoLog.v(WM_DEBUG_CONTENT_RECORDING, 75 "Handle incoming session on display %d, with a pre-existing session %s", 76 incomingSession.getDisplayId(), 77 mSession == null ? null : mSession.getDisplayId()); 78 incomingDisplayContent = wmService.mRoot.getDisplayContentOrCreate( 79 incomingSession.getDisplayId()); 80 incomingDisplayContent.setContentRecordingSession(incomingSession); 81 } 82 if (mSession != null) { 83 // Update the pre-existing display about the new session. 84 ProtoLog.v(WM_DEBUG_CONTENT_RECORDING, "Pause the recording session on display %s", 85 mDisplayContent.getDisplayId()); 86 mDisplayContent.pauseRecording(); 87 mDisplayContent.setContentRecordingSession(null); 88 } 89 // Update the cached states. 90 mDisplayContent = incomingDisplayContent; 91 mSession = incomingSession; 92 } 93 } 94