1 /* 2 * Copyright (C) 2020 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.internal.protolog; 18 19 import android.annotation.Nullable; 20 import android.util.Slog; 21 22 import org.json.JSONException; 23 import org.json.JSONObject; 24 25 import java.io.BufferedReader; 26 import java.io.FileInputStream; 27 import java.io.FileNotFoundException; 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.InputStreamReader; 31 import java.io.PrintWriter; 32 import java.util.Iterator; 33 import java.util.Map; 34 import java.util.TreeMap; 35 import java.util.zip.GZIPInputStream; 36 37 /** 38 * Handles loading and parsing of ProtoLog viewer configuration. 39 */ 40 public class ProtoLogViewerConfigReader { 41 private static final String TAG = "ProtoLogViewerConfigReader"; 42 private Map<Integer, String> mLogMessageMap = null; 43 44 /** Returns message format string for its hash or null if unavailable. */ getViewerString(int messageHash)45 public synchronized String getViewerString(int messageHash) { 46 if (mLogMessageMap != null) { 47 return mLogMessageMap.get(messageHash); 48 } else { 49 return null; 50 } 51 } 52 53 /** 54 * Reads the specified viewer configuration file. Does nothing if the config is already loaded. 55 */ loadViewerConfig(PrintWriter pw, String viewerConfigFilename)56 public synchronized void loadViewerConfig(PrintWriter pw, String viewerConfigFilename) { 57 try { 58 loadViewerConfig(new GZIPInputStream(new FileInputStream(viewerConfigFilename))); 59 logAndPrintln(pw, "Loaded " + mLogMessageMap.size() 60 + " log definitions from " + viewerConfigFilename); 61 } catch (FileNotFoundException e) { 62 logAndPrintln(pw, "Unable to load log definitions: File " 63 + viewerConfigFilename + " not found." + e); 64 } catch (IOException e) { 65 logAndPrintln(pw, "Unable to load log definitions: IOException while reading " 66 + viewerConfigFilename + ". " + e); 67 } catch (JSONException e) { 68 logAndPrintln(pw, "Unable to load log definitions: JSON parsing exception while reading " 69 + viewerConfigFilename + ". " + e); 70 } 71 } 72 73 /** 74 * Reads the specified viewer configuration input stream. 75 * Does nothing if the config is already loaded. 76 */ loadViewerConfig(InputStream viewerConfigInputStream)77 public synchronized void loadViewerConfig(InputStream viewerConfigInputStream) 78 throws IOException, JSONException { 79 if (mLogMessageMap != null) { 80 return; 81 } 82 InputStreamReader config = new InputStreamReader(viewerConfigInputStream); 83 BufferedReader reader = new BufferedReader(config); 84 StringBuilder builder = new StringBuilder(); 85 String line; 86 while ((line = reader.readLine()) != null) { 87 builder.append(line).append('\n'); 88 } 89 reader.close(); 90 JSONObject json = new JSONObject(builder.toString()); 91 JSONObject messages = json.getJSONObject("messages"); 92 93 mLogMessageMap = new TreeMap<>(); 94 Iterator it = messages.keys(); 95 while (it.hasNext()) { 96 String key = (String) it.next(); 97 try { 98 int hash = Integer.parseInt(key); 99 JSONObject val = messages.getJSONObject(key); 100 String msg = val.getString("message"); 101 mLogMessageMap.put(hash, msg); 102 } catch (NumberFormatException expected) { 103 // Not a messageHash - skip it 104 } 105 } 106 } 107 108 /** 109 * Returns the number of loaded log definitions kept in memory. 110 */ knownViewerStringsNumber()111 public synchronized int knownViewerStringsNumber() { 112 if (mLogMessageMap != null) { 113 return mLogMessageMap.size(); 114 } 115 return 0; 116 } 117 logAndPrintln(@ullable PrintWriter pw, String msg)118 static void logAndPrintln(@Nullable PrintWriter pw, String msg) { 119 Slog.i(TAG, msg); 120 if (pw != null) { 121 pw.println(msg); 122 pw.flush(); 123 } 124 } 125 } 126