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.graphics.Region; 35 import android.os.Debug; 36 import android.os.Trace; 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 w, int h, int format, int flags, WindowStateAnimator animator, int windowType)79 WindowSurfaceController(String name, int w, int h, int format, 80 int flags, WindowStateAnimator animator, 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 .setBufferSize(w, h) 95 .setFormat(format) 96 .setFlags(flags) 97 .setMetadata(METADATA_WINDOW_TYPE, windowType) 98 .setMetadata(METADATA_OWNER_UID, mWindowSession.mUid) 99 .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid) 100 .setCallsite("WindowSurfaceController"); 101 102 final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags 103 & WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0); 104 105 if (useBLAST) { 106 b.setBLASTLayer(); 107 } 108 109 mSurfaceControl = b.build(); 110 111 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 112 } 113 hide(SurfaceControl.Transaction transaction, String reason)114 void hide(SurfaceControl.Transaction transaction, String reason) { 115 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title); 116 117 if (mSurfaceShown) { 118 hideSurface(transaction); 119 } 120 } 121 hideSurface(SurfaceControl.Transaction transaction)122 private void hideSurface(SurfaceControl.Transaction transaction) { 123 if (mSurfaceControl == null) { 124 return; 125 } 126 setShown(false); 127 try { 128 transaction.hide(mSurfaceControl); 129 } catch (RuntimeException e) { 130 Slog.w(TAG, "Exception hiding surface in " + this); 131 } 132 } 133 destroy(SurfaceControl.Transaction t)134 void destroy(SurfaceControl.Transaction t) { 135 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 136 "Destroying surface %s called by %s", this, Debug.getCallers(8)); 137 try { 138 if (mSurfaceControl != null) { 139 t.remove(mSurfaceControl); 140 } 141 } catch (RuntimeException e) { 142 Slog.w(TAG, "Error destroying surface in: " + this, e); 143 } finally { 144 setShown(false); 145 mSurfaceControl = null; 146 } 147 } 148 setPosition(SurfaceControl.Transaction t, float left, float top)149 void setPosition(SurfaceControl.Transaction t, float left, float top) { 150 final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; 151 if (!surfaceMoved) { 152 return; 153 } 154 155 mSurfaceX = left; 156 mSurfaceY = top; 157 158 ProtoLog.i(WM_SHOW_TRANSACTIONS, 159 "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title); 160 161 t.setPosition(mSurfaceControl, left, top); 162 } 163 setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy)164 void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy) { 165 final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx || 166 mLastDtdy != dtdy || mLastDsdy != dsdy; 167 if (!matrixChanged) { 168 return; 169 } 170 171 mLastDsdx = dsdx; 172 mLastDtdx = dtdx; 173 mLastDtdy = dtdy; 174 mLastDsdy = dsdy; 175 176 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s", 177 dsdx, dtdx, dtdy, dsdy, title); 178 t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); 179 } 180 prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha)181 boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha) { 182 if (mSurfaceControl == null) { 183 return false; 184 } 185 186 mSurfaceAlpha = alpha; 187 t.setAlpha(mSurfaceControl, alpha); 188 return true; 189 } 190 setOpaque(boolean isOpaque)191 void setOpaque(boolean isOpaque) { 192 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isOpaque=%b: %s", isOpaque, title); 193 194 if (mSurfaceControl == null) { 195 return; 196 } 197 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked"); 198 mService.openSurfaceTransaction(); 199 try { 200 getGlobalTransaction().setOpaque(mSurfaceControl, isOpaque); 201 } finally { 202 mService.closeSurfaceTransaction("setOpaqueLocked"); 203 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked"); 204 } 205 } 206 setSecure(boolean isSecure)207 void setSecure(boolean isSecure) { 208 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title); 209 210 if (mSurfaceControl == null) { 211 return; 212 } 213 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked"); 214 mService.openSurfaceTransaction(); 215 try { 216 getGlobalTransaction().setSecure(mSurfaceControl, isSecure); 217 } finally { 218 mService.closeSurfaceTransaction("setSecure"); 219 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked"); 220 } 221 } 222 setColorSpaceAgnostic(boolean agnostic)223 void setColorSpaceAgnostic(boolean agnostic) { 224 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isColorSpaceAgnostic=%b: %s", agnostic, title); 225 226 if (mSurfaceControl == null) { 227 return; 228 } 229 if (SHOW_LIGHT_TRANSACTIONS) { 230 Slog.i(TAG, ">>> OPEN TRANSACTION setColorSpaceAgnosticLocked"); 231 } 232 mService.openSurfaceTransaction(); 233 try { 234 getGlobalTransaction().setColorSpaceAgnostic(mSurfaceControl, agnostic); 235 } finally { 236 mService.closeSurfaceTransaction("setColorSpaceAgnostic"); 237 if (SHOW_LIGHT_TRANSACTIONS) { 238 Slog.i(TAG, "<<< CLOSE TRANSACTION setColorSpaceAgnosticLocked"); 239 } 240 } 241 } 242 showRobustly(SurfaceControl.Transaction t)243 boolean showRobustly(SurfaceControl.Transaction t) { 244 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title); 245 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this 246 + " during relayout"); 247 248 if (mSurfaceShown) { 249 return true; 250 } 251 252 setShown(true); 253 t.show(mSurfaceControl); 254 return true; 255 } 256 clearWindowContentFrameStats()257 boolean clearWindowContentFrameStats() { 258 if (mSurfaceControl == null) { 259 return false; 260 } 261 return mSurfaceControl.clearContentFrameStats(); 262 } 263 getWindowContentFrameStats(WindowContentFrameStats outStats)264 boolean getWindowContentFrameStats(WindowContentFrameStats outStats) { 265 if (mSurfaceControl == null) { 266 return false; 267 } 268 return mSurfaceControl.getContentFrameStats(outStats); 269 } 270 hasSurface()271 boolean hasSurface() { 272 return mSurfaceControl != null; 273 } 274 getSurfaceControl(SurfaceControl outSurfaceControl)275 void getSurfaceControl(SurfaceControl outSurfaceControl) { 276 outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl"); 277 } 278 getShown()279 boolean getShown() { 280 return mSurfaceShown; 281 } 282 setShown(boolean surfaceShown)283 void setShown(boolean surfaceShown) { 284 mSurfaceShown = surfaceShown; 285 286 mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown); 287 288 mAnimator.mWin.onSurfaceShownChanged(surfaceShown); 289 290 if (mWindowSession != null) { 291 mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType); 292 } 293 } 294 dumpDebug(ProtoOutputStream proto, long fieldId)295 void dumpDebug(ProtoOutputStream proto, long fieldId) { 296 final long token = proto.start(fieldId); 297 proto.write(SHOWN, mSurfaceShown); 298 proto.write(LAYER, mSurfaceLayer); 299 proto.end(token); 300 } 301 dump(PrintWriter pw, String prefix, boolean dumpAll)302 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 303 if (dumpAll) { 304 pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl); 305 } 306 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 307 pw.print(" layer="); pw.print(mSurfaceLayer); 308 pw.print(" alpha="); pw.print(mSurfaceAlpha); 309 pw.print(" rect=("); pw.print(mSurfaceX); 310 pw.print(","); pw.print(mSurfaceY); pw.print(") "); 311 pw.print(" transform=("); pw.print(mLastDsdx); pw.print(", "); 312 pw.print(mLastDtdx); pw.print(", "); pw.print(mLastDsdy); 313 pw.print(", "); pw.print(mLastDtdy); pw.println(")"); 314 } 315 316 @Override toString()317 public String toString() { 318 return mSurfaceControl.toString(); 319 } 320 } 321