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 
24 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
25 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
29 import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN;
30 
31 import android.os.Debug;
32 import android.os.Trace;
33 import android.util.EventLog;
34 import android.util.Slog;
35 import android.util.proto.ProtoOutputStream;
36 import android.view.SurfaceControl;
37 import android.view.WindowContentFrameStats;
38 
39 import com.android.internal.protolog.common.ProtoLog;
40 
41 import java.io.PrintWriter;
42 
43 class WindowSurfaceController {
44     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfaceController" : TAG_WM;
45 
46     final WindowStateAnimator mAnimator;
47 
48     SurfaceControl mSurfaceControl;
49 
50     // Should only be set from within setShown().
51     private boolean mSurfaceShown = false;
52 
53     private final String title;
54 
55     private final WindowManagerService mService;
56 
57     private final int mWindowType;
58     private final Session mWindowSession;
59 
60 
WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator, int windowType)61     WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
62             int windowType) {
63         mAnimator = animator;
64 
65         title = name;
66 
67         mService = animator.mService;
68         final WindowState win = animator.mWin;
69         mWindowType = windowType;
70         mWindowSession = win.mSession;
71 
72         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
73         mSurfaceControl = win.makeSurface()
74                 .setParent(win.getSurfaceControl())
75                 .setName(name)
76                 .setFormat(format)
77                 .setFlags(flags)
78                 .setMetadata(METADATA_WINDOW_TYPE, windowType)
79                 .setMetadata(METADATA_OWNER_UID, mWindowSession.mUid)
80                 .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
81                 .setCallsite("WindowSurfaceController")
82                 .setBLASTLayer().build();
83 
84         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
85     }
86 
hide(SurfaceControl.Transaction transaction, String reason)87     void hide(SurfaceControl.Transaction transaction, String reason) {
88         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title);
89 
90         if (mSurfaceShown) {
91             hideSurface(transaction);
92         }
93     }
94 
hideSurface(SurfaceControl.Transaction transaction)95     private void hideSurface(SurfaceControl.Transaction transaction) {
96         if (mSurfaceControl == null) {
97             return;
98         }
99         setShown(false);
100         try {
101             transaction.hide(mSurfaceControl);
102             if (mAnimator.mIsWallpaper) {
103                 final DisplayContent dc = mAnimator.mWin.getDisplayContent();
104                 EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,
105                         dc.mDisplayId, 0 /* request hidden */,
106                         String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
107             }
108         } catch (RuntimeException e) {
109             Slog.w(TAG, "Exception hiding surface in " + this);
110         }
111     }
112 
destroy(SurfaceControl.Transaction t)113     void destroy(SurfaceControl.Transaction t) {
114         ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
115                 "Destroying surface %s called by %s", this, Debug.getCallers(8));
116         try {
117             if (mSurfaceControl != null) {
118                 if (mAnimator.mIsWallpaper && !mAnimator.mWin.mWindowRemovalAllowed
119                         && !mAnimator.mWin.mRemoveOnExit) {
120                     // The wallpaper surface should have the same lifetime as its window.
121                     Slog.e(TAG, "Unexpected removing wallpaper surface of " + mAnimator.mWin
122                             + " by " + Debug.getCallers(8));
123                 }
124                 t.remove(mSurfaceControl);
125             }
126         } catch (RuntimeException e) {
127             Slog.w(TAG, "Error destroying surface in: " + this, e);
128         } finally {
129             setShown(false);
130             mSurfaceControl = null;
131         }
132     }
133 
prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha)134     boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha) {
135         if (mSurfaceControl == null) {
136             return false;
137         }
138 
139         t.setAlpha(mSurfaceControl, alpha);
140         return true;
141     }
142 
setOpaque(boolean isOpaque)143     void setOpaque(boolean isOpaque) {
144         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isOpaque=%b: %s", isOpaque, title);
145 
146         if (mSurfaceControl == null) {
147             return;
148         }
149 
150         mAnimator.mWin.getPendingTransaction().setOpaque(mSurfaceControl, isOpaque);
151         mService.scheduleAnimationLocked();
152     }
153 
setColorSpaceAgnostic(SurfaceControl.Transaction t, boolean agnostic)154     void setColorSpaceAgnostic(SurfaceControl.Transaction t, boolean agnostic) {
155         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isColorSpaceAgnostic=%b: %s", agnostic, title);
156 
157         if (mSurfaceControl == null) {
158             return;
159         }
160         t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
161     }
162 
showRobustly(SurfaceControl.Transaction t)163     void showRobustly(SurfaceControl.Transaction t) {
164         ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
165         if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
166                 + " during relayout");
167 
168         if (mSurfaceShown) {
169             return;
170         }
171 
172         setShown(true);
173         t.show(mSurfaceControl);
174         if (mAnimator.mIsWallpaper) {
175             final DisplayContent dc = mAnimator.mWin.getDisplayContent();
176             EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,
177                     dc.mDisplayId, 1 /* request shown */,
178                     String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
179         }
180     }
181 
clearWindowContentFrameStats()182     boolean clearWindowContentFrameStats() {
183         if (mSurfaceControl == null) {
184             return false;
185         }
186         return mSurfaceControl.clearContentFrameStats();
187     }
188 
getWindowContentFrameStats(WindowContentFrameStats outStats)189     boolean getWindowContentFrameStats(WindowContentFrameStats outStats) {
190         if (mSurfaceControl == null) {
191             return false;
192         }
193         return mSurfaceControl.getContentFrameStats(outStats);
194     }
195 
hasSurface()196     boolean hasSurface() {
197         return mSurfaceControl != null;
198     }
199 
getSurfaceControl(SurfaceControl outSurfaceControl)200     void getSurfaceControl(SurfaceControl outSurfaceControl) {
201         outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");
202     }
203 
getShown()204     boolean getShown() {
205         return mSurfaceShown;
206     }
207 
setShown(boolean surfaceShown)208     void setShown(boolean surfaceShown) {
209         mSurfaceShown = surfaceShown;
210 
211         mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown);
212 
213         mAnimator.mWin.onSurfaceShownChanged(surfaceShown);
214 
215         if (mWindowSession != null) {
216             mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
217         }
218     }
219 
dumpDebug(ProtoOutputStream proto, long fieldId)220     void dumpDebug(ProtoOutputStream proto, long fieldId) {
221         final long token = proto.start(fieldId);
222         proto.write(SHOWN, mSurfaceShown);
223         proto.end(token);
224     }
225 
dump(PrintWriter pw, String prefix, boolean dumpAll)226     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
227         if (dumpAll) {
228             pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
229         }
230         pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
231     }
232 
233     @Override
toString()234     public String toString() {
235         return mSurfaceControl.toString();
236     }
237 }
238