1 package com.android.internal.protolog;
2 
3 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
4 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
5 import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
6 
7 import android.util.ArrayMap;
8 import android.util.proto.ProtoInputStream;
9 
10 import com.android.internal.protolog.common.ILogger;
11 
12 import java.io.IOException;
13 import java.util.Map;
14 
15 public class ProtoLogViewerConfigReader {
16     private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
17     private Map<Long, String> mLogMessageMap = null;
18 
ProtoLogViewerConfigReader( ViewerConfigInputStreamProvider viewerConfigInputStreamProvider)19     public ProtoLogViewerConfigReader(
20             ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) {
21         this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
22     }
23 
24     /**
25      * Returns message format string for its hash or null if unavailable
26      * or the viewer config is not loaded into memory.
27      */
getViewerString(long messageHash)28     public synchronized String getViewerString(long messageHash) {
29         if (mLogMessageMap != null) {
30             return mLogMessageMap.get(messageHash);
31         } else {
32             return null;
33         }
34     }
35 
36     /**
37      * Loads the viewer config into memory. No-op if already loaded in memory.
38      */
loadViewerConfig(ILogger logger)39     public synchronized void loadViewerConfig(ILogger logger) {
40         if (mLogMessageMap != null) {
41             return;
42         }
43 
44         try {
45             doLoadViewerConfig();
46             logger.log("Loaded " + mLogMessageMap.size() + " log definitions");
47         } catch (IOException e) {
48             logger.log("Unable to load log definitions: "
49                     + "IOException while processing viewer config" + e);
50         }
51     }
52 
53     /**
54      * Unload the viewer config from memory.
55      */
unloadViewerConfig()56     public synchronized void unloadViewerConfig() {
57         mLogMessageMap = null;
58     }
59 
doLoadViewerConfig()60     private void doLoadViewerConfig() throws IOException {
61         mLogMessageMap = new ArrayMap<>();
62         final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
63 
64         while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
65             if (pis.getFieldNumber() == (int) MESSAGES) {
66                 final long inMessageToken = pis.start(MESSAGES);
67 
68                 long messageId = 0;
69                 String message = null;
70                 while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
71                     switch (pis.getFieldNumber()) {
72                         case (int) MESSAGE_ID:
73                             messageId = pis.readLong(MESSAGE_ID);
74                             break;
75                         case (int) MESSAGE:
76                             message = pis.readString(MESSAGE);
77                             break;
78                     }
79                 }
80 
81                 if (messageId == 0) {
82                     throw new IOException("Failed to get message id");
83                 }
84 
85                 if (message == null) {
86                     throw new IOException("Failed to get message string");
87                 }
88 
89                 mLogMessageMap.put(messageId, message);
90 
91                 pis.end(inMessageToken);
92             }
93         }
94     }
95 }
96