WallpaperWindowToken.java revision 879ff721bed9999540c0b03acf4843886b7c3a75
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 17package com.android.server.wm; 18 19import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 20import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 21import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 22import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 25import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 27 28import android.os.Bundle; 29import android.os.IBinder; 30import android.os.RemoteException; 31import android.util.Slog; 32import android.view.DisplayInfo; 33import android.view.animation.Animation; 34 35/** 36 * A token that represents a set of wallpaper windows. 37 */ 38class WallpaperWindowToken extends WindowToken { 39 40 private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM; 41 42 WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit, 43 DisplayContent dc) { 44 super(service, token, TYPE_WALLPAPER, explicit, dc); 45 dc.mWallpaperController.addWallpaperToken(this); 46 } 47 48 @Override 49 void setExiting() { 50 super.setExiting(); 51 mDisplayContent.mWallpaperController.removeWallpaperToken(this); 52 } 53 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 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 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 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 */ 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 122 boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList, 123 WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh, 124 int wallpaperAnimLayerAdj) { 125 126 boolean changed = false; 127 if (hidden == visible) { 128 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 129 "Wallpaper token " + token + " hidden=" + !visible); 130 hidden = !visible; 131 // Need to do a layout to ensure the wallpaper now has the correct size. 132 mDisplayContent.setLayoutNeeded(); 133 } 134 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 wallpaper.adjustAnimLayer(wallpaperAnimLayerAdj); 146 147 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 148 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 149 150 // First, if this window is at the current index, then all is well. 151 if (wallpaper == wallpaperTarget) { 152 wallpaperTargetIndex--; 153 wallpaperTarget = wallpaperTargetIndex > 0 154 ? windowList.get(wallpaperTargetIndex - 1) : null; 155 continue; 156 } 157 158 // The window didn't match... the current wallpaper window, 159 // wherever it is, is in the wrong place, so make sure it is not in the list. 160 int oldIndex = windowList.indexOf(wallpaper); 161 if (oldIndex >= 0) { 162 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 163 "Wallpaper removing at " + oldIndex + ": " + wallpaper); 164 mDisplayContent.removeFromWindowList(wallpaper); 165 if (oldIndex < wallpaperTargetIndex) { 166 wallpaperTargetIndex--; 167 } 168 } 169 170 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 171 // layer. For keyguard over wallpaper put the wallpaper under the lowest window that 172 // is currently on screen, i.e. not hidden by policy. 173 int insertionIndex = 0; 174 if (visible && wallpaperTarget != null) { 175 final int privateFlags = wallpaperTarget.mAttrs.privateFlags; 176 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 177 insertionIndex = Math.min(windowList.indexOf(wallpaperTarget), 178 findLowestWindowOnScreen(windowList)); 179 } 180 } 181 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT 182 || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG, 183 "Moving wallpaper " + wallpaper + " from " + oldIndex + " to " + insertionIndex); 184 185 mDisplayContent.addToWindowList(wallpaper, insertionIndex); 186 changed = true; 187 } 188 189 return changed; 190 } 191 192 /** 193 * @return The index in {@param windows} of the lowest window that is currently on screen and 194 * not hidden by the policy. 195 */ 196 private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) { 197 final int size = windowList.size(); 198 for (int index = 0; index < size; index++) { 199 final WindowState win = windowList.get(index); 200 if (win.isOnScreen()) { 201 return index; 202 } 203 } 204 return Integer.MAX_VALUE; 205 } 206 207 boolean hasVisibleNotDrawnWallpaper() { 208 for (int j = mChildren.size() - 1; j >= 0; --j) { 209 final WindowState wallpaper = mChildren.get(j); 210 if (wallpaper.hasVisibleNotDrawnWallpaper()) { 211 return true; 212 } 213 } 214 return false; 215 } 216 217 @Override 218 public String toString() { 219 if (stringName == null) { 220 StringBuilder sb = new StringBuilder(); 221 sb.append("WallpaperWindowToken{"); 222 sb.append(Integer.toHexString(System.identityHashCode(this))); 223 sb.append(" token="); sb.append(token); sb.append('}'); 224 stringName = sb.toString(); 225 } 226 return stringName; 227 } 228} 229