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