1 /* 2 * Copyright (C) 2015 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.os.Trace.TRACE_TAG_WINDOW_MANAGER; 20 import static android.view.SurfaceControl.METADATA_OWNER_PID; 21 import static android.view.SurfaceControl.METADATA_OWNER_UID; 22 import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; 23 import static android.view.SurfaceControl.getGlobalTransaction; 24 25 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 26 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 27 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 28 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 31 import static com.android.server.wm.WindowSurfaceControllerProto.LAYER; 32 import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN; 33 34 import android.os.Debug; 35 import android.os.Trace; 36 import android.util.EventLog; 37 import android.util.Slog; 38 import android.util.proto.ProtoOutputStream; 39 import android.view.SurfaceControl; 40 import android.view.WindowContentFrameStats; 41 import android.view.WindowManager; 42 43 import com.android.internal.protolog.common.ProtoLog; 44 45 import java.io.PrintWriter; 46 47 class WindowSurfaceController { 48 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfaceController" : TAG_WM; 49 50 final WindowStateAnimator mAnimator; 51 52 SurfaceControl mSurfaceControl; 53 54 // Should only be set from within setShown(). 55 private boolean mSurfaceShown = false; 56 private float mSurfaceX = 0; 57 private float mSurfaceY = 0; 58 59 // Initialize to the identity matrix. 60 private float mLastDsdx = 1; 61 private float mLastDtdx = 0; 62 private float mLastDsdy = 0; 63 private float mLastDtdy = 1; 64 65 private float mSurfaceAlpha = 0; 66 67 private int mSurfaceLayer = 0; 68 69 private final String title; 70 71 private final WindowManagerService mService; 72 73 private final int mWindowType; 74 private final Session mWindowSession; 75 76 // Used to track whether we have called detach children on the way to invisibility. 77 boolean mChildrenDetached; 78 WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator, int windowType)79 WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator, 80 int windowType) { 81 mAnimator = animator; 82 83 title = name; 84 85 mService = animator.mService; 86 final WindowState win = animator.mWin; 87 mWindowType = windowType; 88 mWindowSession = win.mSession; 89 90 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl"); 91 final SurfaceControl.Builder b = win.makeSurface() 92 .setParent(win.getSurfaceControl()) 93 .setName(name) 94 .setFormat(format) 95 .setFlags(flags) 96 .setMetadata(METADATA_WINDOW_TYPE, windowType) 97 .setMetadata(METADATA_OWNER_UID, mWindowSession.mUid) 98 .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid) 99 .setCallsite("WindowSurfaceController"); 100 101 final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags 102 & WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0); 103 104 if (useBLAST) { 105 b.setBLASTLayer(); 106 } 107 108 mSurfaceControl = b.build(); 109 110 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 111 } 112 hide(SurfaceControl.Transaction transaction, String reason)113 void hide(SurfaceControl.Transaction transaction, String reason) { 114 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title); 115 116 if (mSurfaceShown) { 117 hideSurface(transaction); 118 } 119 } 120 hideSurface(SurfaceControl.Transaction transaction)121 private void hideSurface(SurfaceControl.Transaction transaction) { 122 if (mSurfaceControl == null) { 123 return; 124 } 125 setShown(false); 126 try { 127 transaction.hide(mSurfaceControl); 128 if (mAnimator.mIsWallpaper) { 129 final DisplayContent dc = mAnimator.mWin.getDisplayContent(); 130 EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE, 131 dc.mDisplayId, 0 /* request hidden */, 132 String.valueOf(dc.mWallpaperController.getWallpaperTarget())); 133 } 134 } catch (RuntimeException e) { 135 Slog.w(TAG, "Exception hiding surface in " + this); 136 } 137 } 138 destroy(SurfaceControl.Transaction t)139 void destroy(SurfaceControl.Transaction t) { 140 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 141 "Destroying surface %s called by %s", this, Debug.getCallers(8)); 142 try { 143 if (mSurfaceControl != null) { 144 if (mAnimator.mIsWallpaper && !mAnimator.mWin.mWindowRemovalAllowed 145 && !mAnimator.mWin.mRemoveOnExit) { 146 // The wallpaper surface should have the same lifetime as its window. 147 Slog.e(TAG, "Unexpected removing wallpaper surface of " + mAnimator.mWin 148 + " by " + Debug.getCallers(8)); 149 } 150 t.remove(mSurfaceControl); 151 } 152 } catch (RuntimeException e) { 153 Slog.w(TAG, "Error destroying surface in: " + this, e); 154 } finally { 155 setShown(false); 156 mSurfaceControl = null; 157 } 158 } 159 setPosition(SurfaceControl.Transaction t, float left, float top)160 void setPosition(SurfaceControl.Transaction t, float left, float top) { 161 final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; 162 if (!surfaceMoved) { 163 return; 164 } 165 166 mSurfaceX = left; 167 mSurfaceY = top; 168 169 ProtoLog.i(WM_SHOW_TRANSACTIONS, 170 "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title); 171 172 t.setPosition(mSurfaceControl, left, top); 173 } 174 setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy)175 void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy) { 176 final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx || 177 mLastDtdy != dtdy || mLastDsdy != dsdy; 178 if (!matrixChanged) { 179 return; 180 } 181 182 mLastDsdx = dsdx; 183 mLastDtdx = dtdx; 184 mLastDtdy = dtdy; 185 mLastDsdy = dsdy; 186 187 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s", 188 dsdx, dtdx, dtdy, dsdy, title); 189 t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); 190 } 191 prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha)192 boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha) { 193 if (mSurfaceControl == null) { 194 return false; 195 } 196 197 mSurfaceAlpha = alpha; 198 t.setAlpha(mSurfaceControl, alpha); 199 return true; 200 } 201 setOpaque(boolean isOpaque)202 void setOpaque(boolean isOpaque) { 203 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isOpaque=%b: %s", isOpaque, title); 204 205 if (mSurfaceControl == null) { 206 return; 207 } 208 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked"); 209 mService.openSurfaceTransaction(); 210 try { 211 getGlobalTransaction().setOpaque(mSurfaceControl, isOpaque); 212 } finally { 213 mService.closeSurfaceTransaction("setOpaqueLocked"); 214 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked"); 215 } 216 } 217 setSecure(boolean isSecure)218 void setSecure(boolean isSecure) { 219 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title); 220 221 if (mSurfaceControl == null) { 222 return; 223 } 224 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked"); 225 mService.openSurfaceTransaction(); 226 try { 227 getGlobalTransaction().setSecure(mSurfaceControl, isSecure); 228 229 final DisplayContent dc = mAnimator.mWin.mDisplayContent; 230 if (dc != null) { 231 dc.refreshImeSecureFlag(getGlobalTransaction()); 232 } 233 } finally { 234 mService.closeSurfaceTransaction("setSecure"); 235 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked"); 236 } 237 } 238 setColorSpaceAgnostic(SurfaceControl.Transaction t, boolean agnostic)239 void setColorSpaceAgnostic(SurfaceControl.Transaction t, boolean agnostic) { 240 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isColorSpaceAgnostic=%b: %s", agnostic, title); 241 242 if (mSurfaceControl == null) { 243 return; 244 } 245 t.setColorSpaceAgnostic(mSurfaceControl, agnostic); 246 } 247 showRobustly(SurfaceControl.Transaction t)248 void showRobustly(SurfaceControl.Transaction t) { 249 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title); 250 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this 251 + " during relayout"); 252 253 if (mSurfaceShown) { 254 return; 255 } 256 257 setShown(true); 258 t.show(mSurfaceControl); 259 if (mAnimator.mIsWallpaper) { 260 final DisplayContent dc = mAnimator.mWin.getDisplayContent(); 261 EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE, 262 dc.mDisplayId, 1 /* request shown */, 263 String.valueOf(dc.mWallpaperController.getWallpaperTarget())); 264 } 265 } 266 clearWindowContentFrameStats()267 boolean clearWindowContentFrameStats() { 268 if (mSurfaceControl == null) { 269 return false; 270 } 271 return mSurfaceControl.clearContentFrameStats(); 272 } 273 getWindowContentFrameStats(WindowContentFrameStats outStats)274 boolean getWindowContentFrameStats(WindowContentFrameStats outStats) { 275 if (mSurfaceControl == null) { 276 return false; 277 } 278 return mSurfaceControl.getContentFrameStats(outStats); 279 } 280 hasSurface()281 boolean hasSurface() { 282 return mSurfaceControl != null; 283 } 284 getSurfaceControl(SurfaceControl outSurfaceControl)285 void getSurfaceControl(SurfaceControl outSurfaceControl) { 286 outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl"); 287 } 288 getShown()289 boolean getShown() { 290 return mSurfaceShown; 291 } 292 setShown(boolean surfaceShown)293 void setShown(boolean surfaceShown) { 294 mSurfaceShown = surfaceShown; 295 296 mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown); 297 298 mAnimator.mWin.onSurfaceShownChanged(surfaceShown); 299 300 if (mWindowSession != null) { 301 mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType); 302 } 303 } 304 dumpDebug(ProtoOutputStream proto, long fieldId)305 void dumpDebug(ProtoOutputStream proto, long fieldId) { 306 final long token = proto.start(fieldId); 307 proto.write(SHOWN, mSurfaceShown); 308 proto.write(LAYER, mSurfaceLayer); 309 proto.end(token); 310 } 311 dump(PrintWriter pw, String prefix, boolean dumpAll)312 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 313 if (dumpAll) { 314 pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl); 315 } 316 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 317 pw.print(" layer="); pw.print(mSurfaceLayer); 318 pw.print(" alpha="); pw.print(mSurfaceAlpha); 319 pw.print(" rect=("); pw.print(mSurfaceX); 320 pw.print(","); pw.print(mSurfaceY); pw.print(") "); 321 pw.print(" transform=("); pw.print(mLastDsdx); pw.print(", "); 322 pw.print(mLastDtdx); pw.print(", "); pw.print(mLastDsdy); 323 pw.print(", "); pw.print(mLastDtdy); pw.println(")"); 324 } 325 326 @Override toString()327 public String toString() { 328 return mSurfaceControl.toString(); 329 } 330 } 331