• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
20 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
21 
22 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
23 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
24 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
25 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
26 
27 import android.annotation.Nullable;
28 import android.os.Bundle;
29 import android.os.IBinder;
30 import android.os.RemoteException;
31 import android.view.animation.Animation;
32 
33 import com.android.internal.protolog.common.ProtoLog;
34 
35 import java.util.function.Consumer;
36 
37 /**
38  * A token that represents a set of wallpaper windows.
39  */
40 class WallpaperWindowToken extends WindowToken {
41 
42     private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM;
43 
44     private boolean mVisibleRequested = false;
45 
WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit, DisplayContent dc, boolean ownerCanManageAppTokens)46     WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
47             DisplayContent dc, boolean ownerCanManageAppTokens) {
48         this(service, token, explicit, dc, ownerCanManageAppTokens, null /* options */);
49     }
50 
WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit, DisplayContent dc, boolean ownerCanManageAppTokens, @Nullable Bundle options)51     WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
52             DisplayContent dc, boolean ownerCanManageAppTokens, @Nullable Bundle options) {
53         super(service, token, TYPE_WALLPAPER, explicit, dc, ownerCanManageAppTokens,
54                 false /* roundedCornerOverlay */, false /* fromClientToken */, options);
55         dc.mWallpaperController.addWallpaperToken(this);
56         setWindowingMode(WINDOWING_MODE_FULLSCREEN);
57     }
58 
59     @Override
asWallpaperToken()60     WallpaperWindowToken asWallpaperToken() {
61         return this;
62     }
63 
64     @Override
setExiting(boolean animateExit)65     void setExiting(boolean animateExit) {
66         super.setExiting(animateExit);
67         mDisplayContent.mWallpaperController.removeWallpaperToken(this);
68     }
69 
sendWindowWallpaperCommand( String action, int x, int y, int z, Bundle extras, boolean sync)70     void sendWindowWallpaperCommand(
71             String action, int x, int y, int z, Bundle extras, boolean sync) {
72         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
73             final WindowState wallpaper = mChildren.get(wallpaperNdx);
74             try {
75                 wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
76                 // We only want to be synchronous with one wallpaper.
77                 sync = false;
78             } catch (RemoteException e) {
79             }
80         }
81     }
82 
updateWallpaperOffset(boolean sync)83     void updateWallpaperOffset(boolean sync) {
84         final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
85         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
86             final WindowState wallpaper = mChildren.get(wallpaperNdx);
87             if (wallpaperController.updateWallpaperOffset(wallpaper, sync)) {
88                 // We only want to be synchronous with one wallpaper.
89                 sync = false;
90             }
91         }
92     }
93 
94     /**
95      * Starts {@param anim} on all children.
96      */
startAnimation(Animation anim)97     void startAnimation(Animation anim) {
98         for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
99             final WindowState windowState = mChildren.get(ndx);
100             windowState.startAnimation(anim);
101         }
102     }
103 
104     /** Returns {@code true} if visibility is changed. */
updateWallpaperWindows(boolean visible)105     boolean updateWallpaperWindows(boolean visible) {
106         boolean changed = false;
107         if (mVisibleRequested != visible) {
108             ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
109                     token, visible);
110             setVisibility(visible);
111             changed = true;
112         }
113         if (mTransitionController.isShellTransitionsEnabled()) {
114             // Apply legacy fixed rotation to wallpaper if it is becoming visible
115             if (!mTransitionController.useShellTransitionsRotation() && changed && visible) {
116                 final WindowState wallpaperTarget =
117                         mDisplayContent.mWallpaperController.getWallpaperTarget();
118                 if (wallpaperTarget != null && wallpaperTarget.mToken.hasFixedRotationTransform()) {
119                     linkFixedRotationTransform(wallpaperTarget.mToken);
120                 }
121             }
122             return changed;
123         }
124 
125         final WindowState wallpaperTarget =
126                 mDisplayContent.mWallpaperController.getWallpaperTarget();
127 
128         if (visible && wallpaperTarget != null) {
129             final RecentsAnimationController recentsAnimationController =
130                     mWmService.getRecentsAnimationController();
131             final BackNaviAnimationController bac = mWmService.getBackNaviAnimationController();
132             if (recentsAnimationController != null
133                     && recentsAnimationController.isAnimatingTask(wallpaperTarget.getTask())) {
134                 // If the Recents animation is running, and the wallpaper target is the animating
135                 // task we want the wallpaper to be rotated in the same orientation as the
136                 // RecentsAnimation's target (e.g the launcher)
137                 recentsAnimationController.linkFixedRotationTransformIfNeeded(this);
138             } else if (bac != null && bac.isAnimatingTask(wallpaperTarget.getTask())) {
139                 bac.linkFixedRotationTransformIfNeeded(this);
140             } else if ((wallpaperTarget.mActivityRecord == null
141                     // Ignore invisible activity because it may be moving to background.
142                     || wallpaperTarget.mActivityRecord.isVisibleRequested())
143                     && wallpaperTarget.mToken.hasFixedRotationTransform()) {
144                 // If the wallpaper target has a fixed rotation, we want the wallpaper to follow its
145                 // rotation
146                 linkFixedRotationTransform(wallpaperTarget.mToken);
147             }
148         }
149 
150         setVisible(visible);
151         return changed;
152     }
153 
setVisible(boolean visible)154     private void setVisible(boolean visible) {
155         final boolean wasClientVisible = isClientVisible();
156         setClientVisible(visible);
157         if (visible && !wasClientVisible) {
158             for (int i = mChildren.size() - 1; i >= 0; i--) {
159                 final WindowState wallpaper = mChildren.get(i);
160                 wallpaper.requestUpdateWallpaperIfNeeded();
161             }
162         }
163     }
164 
165     /**
166      * Sets the requested visibility of this token. The visibility may not be if this is part of a
167      * transition. In that situation, make sure to call {@link #commitVisibility} when done.
168      */
setVisibility(boolean visible)169     void setVisibility(boolean visible) {
170         if (mVisibleRequested != visible) {
171             // Before setting mVisibleRequested so we can track changes.
172             mTransitionController.collect(this);
173 
174             setVisibleRequested(visible);
175         }
176 
177         // If in a transition, defer commits for activities that are going invisible
178         if (!visible && (mTransitionController.inTransition()
179                 || getDisplayContent().mAppTransition.isRunning())) {
180             return;
181         }
182 
183         commitVisibility(visible);
184     }
185 
186     /**
187      * Commits the visibility of this token. This will directly update the visibility without
188      * regard for other state (like being in a transition).
189      */
commitVisibility(boolean visible)190     void commitVisibility(boolean visible) {
191         if (visible == isVisible()) return;
192 
193         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
194                 "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
195                 isVisible(), mVisibleRequested);
196 
197         setVisibleRequested(visible);
198         setVisible(visible);
199     }
200 
hasVisibleNotDrawnWallpaper()201     boolean hasVisibleNotDrawnWallpaper() {
202         if (!isVisible()) return false;
203         for (int j = mChildren.size() - 1; j >= 0; --j) {
204             final WindowState wallpaper = mChildren.get(j);
205             if (!wallpaper.isDrawn() && wallpaper.isVisible()) {
206                 return true;
207             }
208         }
209         return false;
210     }
211 
212     @Override
forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback)213     void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
214         callback.accept(this);
215     }
216 
217     @Override
fillsParent()218     boolean fillsParent() {
219         return true;
220     }
221 
222     @Override
showWallpaper()223     boolean showWallpaper() {
224         return false;
225     }
226 
setVisibleRequested(boolean visible)227     void setVisibleRequested(boolean visible) {
228         if (mVisibleRequested == visible) return;
229         mVisibleRequested = visible;
230         setInsetsFrozen(!visible);
231     }
232 
233     @Override
isVisibleRequested()234     boolean isVisibleRequested() {
235         return mVisibleRequested;
236     }
237 
238     @Override
isVisible()239     boolean isVisible() {
240         return isClientVisible();
241     }
242 
243     @Override
toString()244     public String toString() {
245         if (stringName == null) {
246             StringBuilder sb = new StringBuilder();
247             sb.append("WallpaperWindowToken{");
248             sb.append(Integer.toHexString(System.identityHashCode(this)));
249             sb.append(" token="); sb.append(token); sb.append('}');
250             stringName = sb.toString();
251         }
252         return stringName;
253     }
254 }
255