• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.view.WindowManager.TRANSIT_CHANGE;
20 
21 import static com.android.internal.R.bool.config_unfoldTransitionEnabled;
22 import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
23 
24 import android.animation.ValueAnimator;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.graphics.Rect;
28 import android.window.DisplayAreaInfo;
29 import android.window.TransitionRequestInfo;
30 import android.window.WindowContainerTransaction;
31 
32 public class PhysicalDisplaySwitchTransitionLauncher {
33 
34     private final DisplayContent mDisplayContent;
35     private final WindowManagerService mService;
36     private final TransitionController mTransitionController;
37 
38     /**
39      * If on a foldable device represents whether the device is folded or not
40      */
41     private boolean mIsFolded;
42     private Transition mTransition;
43 
PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent, TransitionController transitionController)44     public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent,
45             TransitionController transitionController) {
46         mDisplayContent = displayContent;
47         mService = displayContent.mWmService;
48         mTransitionController = transitionController;
49     }
50 
51     /**
52      *   Called by the DeviceStateManager callback when the state changes.
53      */
foldStateChanged(DeviceStateController.DeviceState newDeviceState)54     void foldStateChanged(DeviceStateController.DeviceState newDeviceState) {
55         // Ignore transitions to/from half-folded.
56         if (newDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) return;
57         mIsFolded = newDeviceState == DeviceStateController.DeviceState.FOLDED;
58     }
59 
60     /**
61      * Requests to start a transition for the physical display switch
62      */
requestDisplaySwitchTransitionIfNeeded(int displayId, int oldDisplayWidth, int oldDisplayHeight, int newDisplayWidth, int newDisplayHeight)63     public void requestDisplaySwitchTransitionIfNeeded(int displayId, int oldDisplayWidth,
64             int oldDisplayHeight, int newDisplayWidth, int newDisplayHeight) {
65         if (!mTransitionController.isShellTransitionsEnabled()) return;
66         if (!mDisplayContent.getLastHasContent()) return;
67 
68         boolean shouldRequestUnfoldTransition = !mIsFolded
69                 && mService.mContext.getResources().getBoolean(config_unfoldTransitionEnabled)
70                 && ValueAnimator.areAnimatorsEnabled();
71 
72         if (!shouldRequestUnfoldTransition) {
73             return;
74         }
75 
76         final TransitionRequestInfo.DisplayChange displayChange =
77                 new TransitionRequestInfo.DisplayChange(displayId);
78 
79         final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight);
80         displayChange.setStartAbsBounds(startAbsBounds);
81         final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight);
82         displayChange.setEndAbsBounds(endAbsBounds);
83         displayChange.setPhysicalDisplayChanged(true);
84 
85         final Transition t = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE,
86                 0 /* flags */,
87                 mDisplayContent, mDisplayContent, null /* remoteTransition */,
88                 displayChange);
89 
90         if (t != null) {
91             mDisplayContent.mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
92             mTransition = t;
93         }
94     }
95 
96     /**
97      * Called when physical display is getting updated, this could happen e.g. on foldable
98      * devices when the physical underlying display is replaced.
99      *
100      * @param fromRotation rotation before the display change
101      * @param toRotation rotation after the display change
102      * @param newDisplayAreaInfo display area info after the display change
103      */
onDisplayUpdated(int fromRotation, int toRotation, @NonNull DisplayAreaInfo newDisplayAreaInfo)104     public void onDisplayUpdated(int fromRotation, int toRotation,
105             @NonNull DisplayAreaInfo newDisplayAreaInfo) {
106         if (mTransition == null) return;
107 
108         final boolean started = mDisplayContent.mRemoteDisplayChangeController
109                 .performRemoteDisplayChange(fromRotation, toRotation, newDisplayAreaInfo,
110                         this::continueDisplayUpdate);
111 
112         if (!started) {
113             markTransitionAsReady();
114         }
115     }
116 
continueDisplayUpdate(@ullable WindowContainerTransaction transaction)117     private void continueDisplayUpdate(@Nullable WindowContainerTransaction transaction) {
118         if (mTransition == null) return;
119 
120         if (transaction != null) {
121             mService.mAtmService.mWindowOrganizerController.applyTransaction(transaction);
122         }
123 
124         markTransitionAsReady();
125     }
126 
markTransitionAsReady()127     private void markTransitionAsReady() {
128         if (mTransition == null) return;
129 
130         mTransition.setAllReady();
131         mTransition = null;
132     }
133 
134 }
135