1 /*
2  * Copyright (C) 2019 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.systemui.tracing;
18 
19 import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_H;
20 import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_L;
21 
22 import android.content.Context;
23 import android.os.SystemClock;
24 
25 import androidx.annotation.NonNull;
26 
27 import com.android.systemui.Dumpable;
28 import com.android.systemui.dagger.SysUISingleton;
29 import com.android.systemui.dump.DumpManager;
30 import com.android.systemui.shared.tracing.FrameProtoTracer;
31 import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
32 import com.android.systemui.shared.tracing.ProtoTraceable;
33 import com.android.systemui.tracing.nano.SystemUiTraceEntryProto;
34 import com.android.systemui.tracing.nano.SystemUiTraceFileProto;
35 import com.android.systemui.tracing.nano.SystemUiTraceProto;
36 
37 import com.google.protobuf.nano.MessageNano;
38 
39 import java.io.File;
40 import java.io.FileDescriptor;
41 import java.io.PrintWriter;
42 import java.util.ArrayList;
43 import java.util.Queue;
44 
45 import javax.inject.Inject;
46 
47 /**
48  * Controller for coordinating winscope proto tracing.
49  */
50 @SysUISingleton
51 public class ProtoTracer implements
52         Dumpable,
53         ProtoTraceParams<
54                 MessageNano,
55                 SystemUiTraceFileProto,
56                 SystemUiTraceEntryProto,
57                 SystemUiTraceProto> {
58 
59     private static final String TAG = "ProtoTracer";
60     private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
61 
62     private final Context mContext;
63     private final FrameProtoTracer<MessageNano, SystemUiTraceFileProto, SystemUiTraceEntryProto,
64             SystemUiTraceProto> mProtoTracer;
65 
66     @Inject
ProtoTracer(Context context, DumpManager dumpManager)67     public ProtoTracer(Context context, DumpManager dumpManager) {
68         mContext = context;
69         mProtoTracer = new FrameProtoTracer<>(this);
70         dumpManager.registerDumpable(this);
71     }
72 
73     @Override
getTraceFile()74     public File getTraceFile() {
75         return new File(mContext.getFilesDir(), "sysui_trace.pb");
76     }
77 
78     @Override
getEncapsulatingTraceProto()79     public SystemUiTraceFileProto getEncapsulatingTraceProto() {
80         return new SystemUiTraceFileProto();
81     }
82 
83     @Override
updateBufferProto(SystemUiTraceEntryProto reuseObj, ArrayList<ProtoTraceable<SystemUiTraceProto>> traceables)84     public SystemUiTraceEntryProto updateBufferProto(SystemUiTraceEntryProto reuseObj,
85             ArrayList<ProtoTraceable<SystemUiTraceProto>> traceables) {
86         SystemUiTraceEntryProto proto = reuseObj != null
87                 ? reuseObj
88                 : new SystemUiTraceEntryProto();
89         proto.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
90         proto.systemUi = proto.systemUi != null ? proto.systemUi : new SystemUiTraceProto();
91         for (ProtoTraceable t : traceables) {
92             t.writeToProto(proto.systemUi);
93         }
94         return proto;
95     }
96 
97     @Override
serializeEncapsulatingProto(SystemUiTraceFileProto encapsulatingProto, Queue<SystemUiTraceEntryProto> buffer)98     public byte[] serializeEncapsulatingProto(SystemUiTraceFileProto encapsulatingProto,
99             Queue<SystemUiTraceEntryProto> buffer) {
100         encapsulatingProto.magicNumber = MAGIC_NUMBER_VALUE;
101         encapsulatingProto.entry = buffer.toArray(new SystemUiTraceEntryProto[0]);
102         return MessageNano.toByteArray(encapsulatingProto);
103     }
104 
105     @Override
getProtoBytes(MessageNano proto)106     public byte[] getProtoBytes(MessageNano proto) {
107         return MessageNano.toByteArray(proto);
108     }
109 
110     @Override
getProtoSize(MessageNano proto)111     public int getProtoSize(MessageNano proto) {
112         return proto.getCachedSize();
113     }
114 
start()115     public void start() {
116         mProtoTracer.start();
117     }
118 
stop()119     public void stop() {
120         mProtoTracer.stop();
121     }
122 
isEnabled()123     public boolean isEnabled() {
124         return mProtoTracer.isEnabled();
125     }
126 
add(ProtoTraceable<SystemUiTraceProto> traceable)127     public void add(ProtoTraceable<SystemUiTraceProto> traceable) {
128         mProtoTracer.add(traceable);
129     }
130 
remove(ProtoTraceable<SystemUiTraceProto> traceable)131     public void remove(ProtoTraceable<SystemUiTraceProto> traceable) {
132         mProtoTracer.remove(traceable);
133     }
134 
scheduleFrameUpdate()135     public void scheduleFrameUpdate() {
136         mProtoTracer.scheduleFrameUpdate();
137     }
138 
update()139     public void update() {
140         mProtoTracer.update();
141     }
142 
143     @Override
dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)144     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
145         pw.println("ProtoTracer:");
146         pw.print("    "); pw.println("enabled: " + mProtoTracer.isEnabled());
147         pw.print("    "); pw.println("usagePct: " + mProtoTracer.getBufferUsagePct());
148         pw.print("    "); pw.println("file: " + getTraceFile());
149     }
150 }
151