PerfData.java revision bc7a04b88db83b6bb91c2c50a4cd8b6bafabac06
1/* 2 * Copyright (C) 2017 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 */ 16package com.android.statsd.loadtest; 17 18import android.annotation.Nullable; 19import android.app.Activity; 20import android.app.AlarmManager; 21import android.app.PendingIntent; 22import android.content.BroadcastReceiver; 23import android.content.Context; 24import android.content.Intent; 25import android.os.Bundle; 26import android.os.Environment; 27import android.util.Log; 28import android.os.Debug; 29 30import java.io.BufferedReader; 31import java.io.Closeable; 32import java.io.File; 33import java.io.FileInputStream; 34import java.io.FileOutputStream; 35import java.io.FileWriter; 36import java.io.InputStream; 37import java.io.InputStreamReader; 38import java.io.IOException; 39import java.text.SimpleDateFormat; 40import java.util.Date; 41 42/** Prints some information about the device via Dumpsys in order to evaluate health metrics. */ 43public class PerfData { 44 45 private static final String TAG = "PerfData"; 46 private static final String DUMP_FILENAME = TAG + "_dump.tmp"; 47 48 public void resetData(Context context) { 49 runDumpsysStats(context, "batterystats", "--reset"); 50 } 51 52 public void publishData(Context context, boolean placebo, int replication, long bucketMins, 53 long periodSecs, int burst) { 54 publishBatteryData(context, placebo, replication, bucketMins, periodSecs, burst); 55 } 56 57 private void publishBatteryData(Context context, boolean placebo, int replication, 58 long bucketMins, long periodSecs, int burst) { 59 // Don't use --checkin. 60 runDumpsysStats(context, "batterystats"); 61 writeBatteryData(context, placebo, replication, bucketMins, periodSecs, burst); 62 } 63 64 private void runDumpsysStats(Context context, String cmd, String... args) { 65 boolean success = false; 66 // Call dumpsys Dump statistics to a file. 67 FileOutputStream fo = null; 68 try { 69 fo = context.openFileOutput(DUMP_FILENAME, Context.MODE_PRIVATE); 70 if (!Debug.dumpService(cmd, fo.getFD(), args)) { 71 Log.w(TAG, "Dumpsys failed."); 72 } 73 success = true; 74 } catch (IOException | SecurityException | NullPointerException e) { 75 // SecurityException may occur when trying to dump multi-user info. 76 // NPE can occur during dumpService (root cause unknown). 77 throw new RuntimeException(e); 78 } finally { 79 closeQuietly(fo); 80 } 81 } 82 83 private String readDumpFile(Context context) { 84 StringBuilder sb = new StringBuilder(); 85 FileInputStream fi = null; 86 BufferedReader br = null; 87 try { 88 fi = context.openFileInput(DUMP_FILENAME); 89 br = new BufferedReader(new InputStreamReader(fi)); 90 String line = br.readLine(); 91 while (line != null) { 92 sb.append(line); 93 sb.append(System.lineSeparator()); 94 line = br.readLine(); 95 } 96 } catch (IOException e) { 97 throw new RuntimeException(e); 98 } finally { 99 closeQuietly(br); 100 } 101 return sb.toString(); 102 } 103 104 private static void closeQuietly(@Nullable Closeable c) { 105 if (c != null) { 106 try { 107 c.close(); 108 } catch (IOException ignore) { 109 } 110 } 111 } 112 113 public void writeBatteryData(Context context, boolean placebo, int replication, long bucketMins, 114 long periodSecs, int burst) { 115 BatteryStatsParser parser = new BatteryStatsParser(); 116 FileInputStream fi = null; 117 BufferedReader br = null; 118 String suffix = new SimpleDateFormat("YYYY_MM_dd_HH_mm_ss").format(new Date()); 119 File batteryDataFile = new File(getStorageDir(), "battery_" + suffix + ".csv"); 120 Log.d(TAG, "Writing battery data to " + batteryDataFile.getAbsolutePath()); 121 122 FileWriter writer = null; 123 try { 124 fi = context.openFileInput(DUMP_FILENAME); 125 writer = new FileWriter(batteryDataFile); 126 writer.append("time,battery_level" 127 + getColumnName(placebo, replication, bucketMins, periodSecs, burst) + "\n"); 128 br = new BufferedReader(new InputStreamReader(fi)); 129 String line = br.readLine(); 130 while (line != null) { 131 String recordLine = parser.parseLine(line); 132 if (recordLine != null) { 133 writer.append(recordLine); 134 } 135 line = br.readLine(); 136 } 137 writer.flush(); 138 } catch (IOException e) { 139 throw new RuntimeException(e); 140 } finally { 141 closeQuietly(writer); 142 closeQuietly(br); 143 } 144 } 145 146 private File getStorageDir() { 147 File file = new File(Environment.getExternalStoragePublicDirectory( 148 Environment.DIRECTORY_DOCUMENTS), "loadtest"); 149 if (!file.mkdirs()) { 150 Log.e(TAG, "Directory not created"); 151 } 152 return file; 153 } 154 155 private String getColumnName(boolean placebo, int replication, long bucketMins, long periodSecs, 156 int burst) { 157 if (placebo) { 158 return "_placebo_p=" + periodSecs; 159 } 160 return "_r=" + replication + "_bkt=" + bucketMins + "_p=" + periodSecs + "_bst=" + burst; 161 } 162} 163