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