1 /*
2  * Copyright (C) 2016 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 android.graphics.Rect;
20 import android.graphics.Region;
21 import android.os.IBinder;
22 import android.os.Parcel;
23 import android.util.Slog;
24 import android.view.SurfaceControl;
25 
26 import java.io.FileDescriptor;
27 import java.io.FileOutputStream;
28 import java.io.DataOutputStream;
29 
30 // A surface control subclass which logs events to a FD in binary format.
31 // This can be used in our CTS tests to enable a pattern similar to mocking
32 // the surface control.
33 //
34 // See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
35 class RemoteSurfaceTrace extends SurfaceControl {
36     static final String TAG = "RemoteSurfaceTrace";
37 
38     final FileDescriptor mWriteFd;
39     final DataOutputStream mOut;
40 
41     final WindowManagerService mService;
42     final WindowState mWindow;
43 
RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window)44     RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
45         super(wrapped);
46 
47         mWriteFd = fd;
48         mOut = new DataOutputStream(new FileOutputStream(fd, false));
49 
50         mWindow = window;
51         mService = mWindow.mService;
52     }
53 
54     @Override
setAlpha(float alpha)55     public void setAlpha(float alpha) {
56         writeFloatEvent("Alpha", alpha);
57         super.setAlpha(alpha);
58     }
59 
60     @Override
setLayer(int zorder)61     public void setLayer(int zorder) {
62         writeIntEvent("Layer", zorder);
63         super.setLayer(zorder);
64     }
65 
66     @Override
setPosition(float x, float y)67     public void setPosition(float x, float y) {
68         writeFloatEvent("Position", x, y);
69         super.setPosition(x, y);
70     }
71 
72     @Override
setGeometryAppliesWithResize()73     public void setGeometryAppliesWithResize() {
74         writeEvent("GeometryAppliesWithResize");
75         super.setGeometryAppliesWithResize();
76     }
77 
78     @Override
setSize(int w, int h)79     public void setSize(int w, int h) {
80         writeIntEvent("Size", w, h);
81         super.setSize(w, h);
82     }
83 
84     @Override
setWindowCrop(Rect crop)85     public void setWindowCrop(Rect crop) {
86         writeRectEvent("Crop", crop);
87         super.setWindowCrop(crop);
88     }
89 
90     @Override
setFinalCrop(Rect crop)91     public void setFinalCrop(Rect crop) {
92         writeRectEvent("FinalCrop", crop);
93         super.setFinalCrop(crop);
94     }
95 
96     @Override
setLayerStack(int layerStack)97     public void setLayerStack(int layerStack) {
98         writeIntEvent("LayerStack", layerStack);
99         super.setLayerStack(layerStack);
100     }
101 
102     @Override
setMatrix(float dsdx, float dtdx, float dsdy, float dtdy)103     public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
104         writeFloatEvent("Matrix", dsdx, dtdx, dsdy, dtdy);
105         super.setMatrix(dsdx, dtdx, dsdy, dtdy);
106     }
107 
108     @Override
hide()109     public void hide() {
110         writeEvent("Hide");
111         super.hide();
112     }
113 
114     @Override
show()115     public void show() {
116         writeEvent("Show");
117         super.show();
118     }
119 
writeEvent(String tag)120     private void writeEvent(String tag) {
121         try {
122             mOut.writeUTF(tag);
123             mOut.writeUTF(mWindow.getWindowTag().toString());
124             writeSigil();
125         } catch (Exception e) {
126             RemoteEventTrace.logException(e);
127             mService.disableSurfaceTrace();
128         }
129     }
130 
writeIntEvent(String tag, int... values)131     private void writeIntEvent(String tag, int... values) {
132         try {
133             mOut.writeUTF(tag);
134             mOut.writeUTF(mWindow.getWindowTag().toString());
135             for (int value: values) {
136                 mOut.writeInt(value);
137             }
138             writeSigil();
139         } catch (Exception e) {
140             RemoteEventTrace.logException(e);
141             mService.disableSurfaceTrace();
142         }
143     }
144 
writeFloatEvent(String tag, float... values)145     private void writeFloatEvent(String tag, float... values) {
146         try {
147             mOut.writeUTF(tag);
148             mOut.writeUTF(mWindow.getWindowTag().toString());
149             for (float value: values) {
150                 mOut.writeFloat(value);
151             }
152             writeSigil();
153         } catch (Exception e) {
154             RemoteEventTrace.logException(e);
155             mService.disableSurfaceTrace();
156         }
157     }
158 
writeRectEvent(String tag, Rect value)159     private void writeRectEvent(String tag, Rect value) {
160         writeFloatEvent(tag, value.left, value.top, value.right, value.bottom);
161     }
162 
writeSigil()163     private void writeSigil() throws Exception {
164         mOut.write(RemoteEventTrace.sigil, 0, 4);
165     }
166 }
167