• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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