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