1 /* 2 * Copyright (C) 2021 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.cts.verifier; 18 19 import android.os.Environment; 20 import android.util.Log; 21 22 import com.android.compatibility.common.util.ReportLog; 23 import com.android.compatibility.common.util.ResultType; 24 import com.android.compatibility.common.util.ResultUnit; 25 26 import org.json.JSONArray; 27 import org.json.JSONObject; 28 import org.xmlpull.v1.XmlPullParserException; 29 import org.xmlpull.v1.XmlSerializer; 30 31 import java.io.File; 32 import java.io.IOException; 33 import java.io.ObjectInputStream; 34 import java.io.ObjectOutputStream; 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.util.List; 38 39 public class CtsVerifierReportLog extends ReportLog { 40 private static final String TAG = CtsVerifierReportLog.class.getSimpleName(); 41 private static final boolean DEBUG = true; 42 43 private File mJsonFile; 44 private JSONObject mCurrentJson = new JSONObject(); 45 46 private static final String LOG_ERROR_STR = "Could not log metric."; 47 CtsVerifierReportLog(String reportLogName, String streamName)48 public CtsVerifierReportLog(String reportLogName, String streamName) { 49 this(reportLogName, streamName, new File(Environment.getExternalStorageDirectory(), 50 ReportExporter.LOGS_DIRECTORY)); 51 } 52 CtsVerifierReportLog(String reportLogName, String streamName, File logDirectory)53 public CtsVerifierReportLog(String reportLogName, String streamName, File logDirectory) { 54 super(reportLogName, streamName); 55 if (DEBUG) { 56 Log.d(TAG, "CtsVerifierReportLog()"); 57 Log.d(TAG, " reportLogName:" + reportLogName); 58 Log.d(TAG, " streamName:" + streamName); 59 Log.d(TAG, " logDirectory:" + logDirectory); 60 } 61 62 try { 63 // dir value must match the src-dir value configured in ReportLogCollector target 64 // preparer in cts/harness/tools/cts-tradefed/res/config/cts-preconditions.xml 65 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 66 throw new IOException("External storage is not mounted"); 67 } else if ((!logDirectory.exists() && !logDirectory.mkdirs()) 68 || (logDirectory.exists() && !logDirectory.isDirectory())) { 69 throw new IOException("Cannot create directory " + logDirectory 70 + " for device info files"); 71 } else { 72 mJsonFile = new File(logDirectory, mReportLogName + ".reportlog.json"); 73 } 74 } catch (Exception e) { 75 Log.e(TAG, "Could not create report log file.", e); 76 } 77 } 78 isOpen()79 public boolean isOpen() { 80 return mJsonFile != null; 81 } 82 83 /** 84 * Closes report file. Static functions that do not have access to instrumentation can 85 * use this to close report logs. Summary, if present, is not reported to instrumentation, hence 86 * does not appear in the result XML. 87 */ submit()88 public void submit() { 89 if (DEBUG) { 90 Log.d(TAG, "submit()"); 91 } 92 try { 93 Log.d(TAG, "Submit JSON file at " + mJsonFile.getAbsolutePath()); 94 Path path = mJsonFile.toPath(); 95 JSONObject jsonObject; 96 // If the file currently exists, load into the JSONObject. 97 if (mJsonFile.exists()) { 98 String content = new String(Files.readAllBytes(path)); 99 jsonObject = new JSONObject(content); 100 } else { 101 jsonObject = new JSONObject(); 102 } 103 // Put the new JSON object into the existing JSON 104 jsonObject.put(mStreamName, mCurrentJson); 105 // Write as human readable text. 106 String newString = jsonObject.toString(2); 107 if (DEBUG) { 108 Log.d(TAG, "New JSON string:" + newString); 109 } 110 // Write the new JSON back into the file. 111 Files.write(path, newString.getBytes()); 112 } catch (Exception e) { 113 Log.e(TAG, "ReportLog Submit Failed", e); 114 } 115 } 116 117 // 118 // ReportLog overrides 119 // 120 /** 121 * Adds a double array of metrics to the report. 122 */ 123 @Override addValues(String message, double[] values, ResultType type, ResultUnit unit)124 public void addValues(String message, double[] values, ResultType type, ResultUnit unit) { 125 try { 126 mCurrentJson.put(message, new JSONArray(values)); 127 } catch (Exception e) { 128 Log.e(TAG, LOG_ERROR_STR + " (double[]) ", e); 129 } 130 } 131 132 /** 133 * Adds a double array of metrics to the report. 134 */ 135 @Override addValues(String source, String message, double[] values, ResultType type, ResultUnit unit)136 public void addValues(String source, String message, double[] values, ResultType type, 137 ResultUnit unit) { 138 try { 139 mCurrentJson.put(message, new JSONArray(values)); 140 } catch (Exception e) { 141 Log.e(TAG, LOG_ERROR_STR + " (double[]) ", e); 142 } 143 } 144 145 /** 146 * Adds a double metric to the report. 147 */ 148 @Override addValue(String message, double value, ResultType type, ResultUnit unit)149 public void addValue(String message, double value, ResultType type, ResultUnit unit) { 150 try { 151 mCurrentJson.put(message, value); 152 } catch (Exception e) { 153 Log.e(TAG, LOG_ERROR_STR + " (double) ", e); 154 } 155 } 156 157 /** 158 * Adds a double metric to the report. 159 */ 160 @Override addValue(String source, String message, double value, ResultType type, ResultUnit unit)161 public void addValue(String source, String message, double value, ResultType type, 162 ResultUnit unit) { 163 try { 164 mCurrentJson.put(message, value); 165 } catch (Exception e) { 166 Log.e(TAG, LOG_ERROR_STR + " (double) ", e); 167 } 168 } 169 170 /** 171 * Adds an int metric to the report. 172 */ 173 @Override addValue(String message, int value, ResultType type, ResultUnit unit)174 public void addValue(String message, int value, ResultType type, ResultUnit unit) { 175 try { 176 mCurrentJson.put(message, value); 177 } catch (Exception e) { 178 Log.e(TAG, LOG_ERROR_STR + " (int) ", e); 179 } 180 } 181 182 /** 183 * Adds a long metric to the report. 184 */ 185 @Override addValue(String message, long value, ResultType type, ResultUnit unit)186 public void addValue(String message, long value, ResultType type, ResultUnit unit) { 187 try { 188 mCurrentJson.put(message, value); 189 } catch (Exception e) { 190 Log.e(TAG, LOG_ERROR_STR + " (long) ", e); 191 } 192 } 193 194 /** 195 * Adds a float metric to the report. 196 */ 197 @Override addValue(String message, float value, ResultType type, ResultUnit unit)198 public void addValue(String message, float value, ResultType type, ResultUnit unit) { 199 try { 200 mCurrentJson.put(message, value); 201 } catch (Exception e) { 202 Log.e(TAG, LOG_ERROR_STR + " (float) ", e); 203 } 204 } 205 206 /** 207 * Adds a boolean metric to the report. 208 */ 209 @Override addValue(String message, boolean value, ResultType type, ResultUnit unit)210 public void addValue(String message, boolean value, ResultType type, ResultUnit unit) { 211 try { 212 mCurrentJson.put(message, value); 213 } catch (Exception e) { 214 Log.e(TAG, LOG_ERROR_STR + " (boolean) ", e); 215 } 216 } 217 218 /** 219 * Adds a String metric to the report. 220 */ 221 @Override addValue(String message, String value, ResultType type, ResultUnit unit)222 public void addValue(String message, String value, ResultType type, ResultUnit unit) { 223 try { 224 mCurrentJson.put(message, value); 225 } catch (Exception e) { 226 Log.e(TAG, LOG_ERROR_STR + " (String) ", e); 227 } 228 } 229 230 /** 231 * Adds an int array of metrics to the report. 232 */ 233 @Override addValues(String message, int[] values, ResultType type, ResultUnit unit)234 public void addValues(String message, int[] values, ResultType type, ResultUnit unit) { 235 try { 236 mCurrentJson.put(message, new JSONArray(values)); 237 } catch (Exception e) { 238 Log.e(TAG, LOG_ERROR_STR + " (int[]) ", e); 239 } 240 } 241 242 /** 243 * Adds a long array of metrics to the report. 244 */ 245 @Override addValues(String message, long[] values, ResultType type, ResultUnit unit)246 public void addValues(String message, long[] values, ResultType type, ResultUnit unit) { 247 try { 248 mCurrentJson.put(message, new JSONArray(values)); 249 } catch (Exception e) { 250 Log.e(TAG, LOG_ERROR_STR + " (long[]) ", e); 251 } 252 } 253 254 /** 255 * Adds a float array of metrics to the report. 256 */ 257 @Override addValues(String message, float[] values, ResultType type, ResultUnit unit)258 public void addValues(String message, float[] values, ResultType type, ResultUnit unit) { 259 try { 260 mCurrentJson.put(message, new JSONArray(values)); 261 } catch (Exception e) { 262 Log.e(TAG, LOG_ERROR_STR + " (float[]) ", e); 263 } 264 } 265 266 /** 267 * Adds a boolean array of metrics to the report. 268 */ 269 @Override addValues(String message, boolean[] values, ResultType type, ResultUnit unit)270 public void addValues(String message, boolean[] values, ResultType type, ResultUnit unit) { 271 try { 272 mCurrentJson.put(message, new JSONArray(values)); 273 } catch (Exception e) { 274 Log.e(TAG, LOG_ERROR_STR + " (boolean[]) ", e); 275 } 276 } 277 278 /** 279 * Adds a String List of metrics to the report. 280 */ 281 @Override addValues(String message, List<String> values, ResultType type, ResultUnit unit)282 public void addValues(String message, List<String> values, ResultType type, ResultUnit unit) { 283 try { 284 mCurrentJson.put(message, new JSONArray(values)); 285 } catch (Exception e) { 286 Log.e(TAG, LOG_ERROR_STR + " (List<String>) ", e); 287 } 288 } 289 serialize(ReportLog reportlog)290 public static String serialize(ReportLog reportlog) throws XmlPullParserException, 291 IllegalArgumentException, IllegalStateException, IOException { 292 Log.e(TAG, "No implementation for serialize(ReportLog)"); 293 return ""; 294 } 295 serialize(XmlSerializer serializer, ReportLog reportLog)296 public static void serialize(XmlSerializer serializer, ReportLog reportLog) 297 throws IOException { 298 Log.e(TAG, "No implementation for serialize(XmlSerializer, ReportLog)"); 299 } 300 301 // 302 // It is not understood why these methods are called (through reflection), but an 303 // exception is thrown if they are not implemented. 304 // 305 // Serializable readObject readObject(ObjectInputStream inputStream)306 private void readObject(ObjectInputStream inputStream) throws ClassNotFoundException, 307 IOException { 308 } 309 310 // Serializable writeObject writeObject(ObjectOutputStream outputStream)311 private void writeObject(ObjectOutputStream outputStream) throws IOException { 312 } 313 314 /** 315 * Adds a JSONArray metric to the report. 316 */ addValues(String message, JSONArray values)317 public void addValues(String message, JSONArray values) { 318 try { 319 mCurrentJson.put(message, values); 320 } catch (Exception e) { 321 Log.e(TAG, LOG_ERROR_STR + " (JSONArray) ", e); 322 } 323 } 324 } 325