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.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
20 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
21 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
22 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
23 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
24 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
25 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
26 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
27 
28 import android.os.Bundle;
29 import android.os.IBinder;
30 import android.os.RemoteException;
31 import android.util.Slog;
32 import android.view.DisplayInfo;
33 import android.view.animation.Animation;
34 
35 /**
36  * A token that represents a set of wallpaper windows.
37  */
38 class WallpaperWindowToken extends WindowToken {
39 
40     private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM;
41 
WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit, DisplayContent dc, boolean ownerCanManageAppTokens)42     WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
43             DisplayContent dc, boolean ownerCanManageAppTokens) {
44         super(service, token, TYPE_WALLPAPER, explicit, dc, ownerCanManageAppTokens);
45         dc.mWallpaperController.addWallpaperToken(this);
46     }
47 
48     @Override
setExiting()49     void setExiting() {
50         super.setExiting();
51         mDisplayContent.mWallpaperController.removeWallpaperToken(this);
52     }
53 
hideWallpaperToken(boolean wasDeferred, String reason)54     void hideWallpaperToken(boolean wasDeferred, String reason) {
55         for (int j = mChildren.size() - 1; j >= 0; j--) {
56             final WindowState wallpaper = mChildren.get(j);
57             wallpaper.hideWallpaperWindow(wasDeferred, reason);
58         }
59         hidden = true;
60     }
61 
sendWindowWallpaperCommand( String action, int x, int y, int z, Bundle extras, boolean sync)62     void sendWindowWallpaperCommand(
63             String action, int x, int y, int z, Bundle extras, boolean sync) {
64         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
65             final WindowState wallpaper = mChildren.get(wallpaperNdx);
66             try {
67                 wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
68                 // We only want to be synchronous with one wallpaper.
69                 sync = false;
70             } catch (RemoteException e) {
71             }
72         }
73     }
74 
updateWallpaperOffset(int dw, int dh, boolean sync)75     void updateWallpaperOffset(int dw, int dh, boolean sync) {
76         final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
77         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
78             final WindowState wallpaper = mChildren.get(wallpaperNdx);
79             if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
80                 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
81                 winAnimator.computeShownFrameLocked();
82                 // No need to lay out the windows - we can just set the wallpaper position directly.
83                 winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
84                 // We only want to be synchronous with one wallpaper.
85                 sync = false;
86             }
87         }
88     }
89 
updateWallpaperVisibility(boolean visible)90     void updateWallpaperVisibility(boolean visible) {
91         final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
92         final int dw = displayInfo.logicalWidth;
93         final int dh = displayInfo.logicalHeight;
94 
95         if (hidden == visible) {
96             hidden = !visible;
97             // Need to do a layout to ensure the wallpaper now has the correct size.
98             mDisplayContent.setLayoutNeeded();
99         }
100 
101         final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
102         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
103             final WindowState wallpaper = mChildren.get(wallpaperNdx);
104             if (visible) {
105                 wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
106             }
107 
108             wallpaper.dispatchWallpaperVisibility(visible);
109         }
110     }
111 
112     /**
113      * Starts {@param anim} on all children.
114      */
startAnimation(Animation anim)115     void startAnimation(Animation anim) {
116         for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
117             final WindowState windowState = mChildren.get(ndx);
118             windowState.mWinAnimator.setAnimation(anim);
119         }
120     }
121 
updateWallpaperWindows(boolean visible, int animLayerAdj)122     void updateWallpaperWindows(boolean visible, int animLayerAdj) {
123 
124         if (hidden == visible) {
125             if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
126                     "Wallpaper token " + token + " hidden=" + !visible);
127             hidden = !visible;
128             // Need to do a layout to ensure the wallpaper now has the correct size.
129             mDisplayContent.setLayoutNeeded();
130         }
131 
132         final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
133         final int dw = displayInfo.logicalWidth;
134         final int dh = displayInfo.logicalHeight;
135         final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
136         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
137             final WindowState wallpaper = mChildren.get(wallpaperNdx);
138 
139             if (visible) {
140                 wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
141             }
142 
143             // First, make sure the client has the current visibility state.
144             wallpaper.dispatchWallpaperVisibility(visible);
145 
146             if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
147                     + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
148         }
149     }
150 
hasVisibleNotDrawnWallpaper()151     boolean hasVisibleNotDrawnWallpaper() {
152         for (int j = mChildren.size() - 1; j >= 0; --j) {
153             final WindowState wallpaper = mChildren.get(j);
154             if (wallpaper.hasVisibleNotDrawnWallpaper()) {
155                 return true;
156             }
157         }
158         return false;
159     }
160 
161     @Override
toString()162     public String toString() {
163         if (stringName == null) {
164             StringBuilder sb = new StringBuilder();
165             sb.append("WallpaperWindowToken{");
166             sb.append(Integer.toHexString(System.identityHashCode(this)));
167             sb.append(" token="); sb.append(token); sb.append('}');
168             stringName = sb.toString();
169         }
170         return stringName;
171     }
172 }
173