Loading cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java +44 −5 Original line number Diff line number Diff line Loading @@ -17,16 +17,23 @@ package com.android.statsd.shelltools; import com.android.os.StatsLog.ConfigMetricsReportList; import com.google.common.io.Files; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Utilities for local use of statsd. Loading Loading @@ -80,7 +87,8 @@ public class Utils { * @throws InterruptedException */ public static ConfigMetricsReportList getReportList(long configId, boolean clearData, boolean useShellUid, Logger logger) throws IOException, InterruptedException { boolean useShellUid, Logger logger, String deviceSerial) throws IOException, InterruptedException { try { File outputFile = File.createTempFile("statsdret", ".bin"); outputFile.deleteOnExit(); Loading @@ -88,6 +96,8 @@ public class Utils { outputFile, logger, "adb", "-s", deviceSerial, "shell", CMD_DUMP_REPORT, useShellUid ? SHELL_UID : "", Loading Loading @@ -117,12 +127,14 @@ public class Utils { * @throws IOException * @throws InterruptedException */ public static void logAppBreadcrumb(int label, int state, Logger logger) public static void logAppBreadcrumb(int label, int state, Logger logger, String deviceSerial) throws IOException, InterruptedException { runCommand( null, logger, "adb", "-s", deviceSerial, "shell", CMD_LOG_APP_BREADCRUMB, String.valueOf(label), Loading @@ -145,13 +157,14 @@ public class Utils { * Algorithm: true if (sdk >= minSdk) || (sdk == minSdk-1 && codeName.startsWith(minCodeName)) * If all else fails, assume it will work (letting future commands deal with any errors). */ public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename) { public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename, String deviceSerial) { BufferedReader in = null; try { File outFileSdk = File.createTempFile("shelltools_sdk", "tmp"); outFileSdk.deleteOnExit(); runCommand(outFileSdk, logger, "adb", "shell", "getprop", "ro.build.version.sdk"); "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.sdk"); in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileSdk))); // If NullPointerException/NumberFormatException/etc., just catch and return true. int sdk = Integer.parseInt(in.readLine().trim()); Loading @@ -162,7 +175,7 @@ public class Utils { File outFileCode = File.createTempFile("shelltools_codename", "tmp"); outFileCode.deleteOnExit(); runCommand(outFileCode, logger, "adb", "shell", "getprop", "ro.build.version.codename"); "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.codename"); in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileCode))); return in.readLine().startsWith(minCodename); } else { Loading Loading @@ -190,4 +203,30 @@ public class Utils { return record.getMessage() + "\n"; } } /** * Parse the result of "adb devices" to return the list of connected devices. * @param logger Logger to log error messages * @return List of the serial numbers of the connected devices. */ public static List<String> getDeviceSerials(Logger logger) { try { ArrayList<String> devices = new ArrayList<>(); File outFile = File.createTempFile("device_serial", "tmp"); outFile.deleteOnExit(); Utils.runCommand(outFile, logger, "adb", "devices"); List<String> outputLines = Files.readLines(outFile, Charset.defaultCharset()); Pattern regex = Pattern.compile("^(.*)\tdevice$"); for (String line : outputLines) { Matcher m = regex.matcher(line); if (m.find()) { devices.add(m.group(1)); } } return devices; } catch (Exception ex) { logger.log(Level.SEVERE, "Failed to list connected devices: " + ex.getMessage()); } return null; } } cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java +71 −35 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ import com.google.protobuf.TextFormat; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** Loading @@ -49,7 +51,7 @@ public class LocalDrive { public static final String HELP_STRING = "Usage:\n\n" + "statsd_localdrive upload CONFIG_FILE [CONFIG_ID] [--binary]\n" + "statsd_localdrive [-s DEVICE_SERIAL] upload CONFIG_FILE [CONFIG_ID] [--binary]\n" + " Uploads the given statsd config file (in binary or human-readable-text format).\n" + " If a config with this id already exists, removes it first.\n" + " CONFIG_FILE Location of config file on host.\n" + Loading @@ -59,12 +61,12 @@ public class LocalDrive { // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID "\n" + "statsd_localdrive update CONFIG_FILE [CONFIG_ID] [--binary]\n" + "statsd_localdrive [-s DEVICE_SERIAL] update CONFIG_FILE [CONFIG_ID] [--binary]\n" + " Same as upload, but does not remove the old config first (if it already exists).\n" + // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID "\n" + "statsd_localdrive get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" + "statsd_localdrive [-s DEVICE_SERIAL] get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" + " Prints the output statslog data (in binary or human-readable-text format).\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + " --binary Output should be in binary, instead of default human-readable text.\n" + Loading @@ -75,13 +77,13 @@ public class LocalDrive { // --include_current_bucket --proto "\n" + "statsd_localdrive remove [CONFIG_ID]\n" + "statsd_localdrive [-s DEVICE_SERIAL] remove [CONFIG_ID]\n" + " Removes the config.\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + // Equivalent to: adb shell cmd stats config remove SHELL_UID CONFIG_ID "\n" + "statsd_localdrive clear [CONFIG_ID]\n" + "statsd_localdrive [-s DEVICE_SERIAL] clear [CONFIG_ID]\n" + " Clears the data associated with the config.\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + // Similar to: adb shell cmd stats dump-report SHELL_UID CONFIG_ID Loading @@ -94,29 +96,59 @@ public class LocalDrive { /** Usage: make statsd_localdrive && statsd_localdrive */ public static void main(String[] args) { Utils.setUpLogger(sLogger, DEBUG); if (args.length == 0) { printHelp(); return; } int remainingArgsLength = args.length; String deviceSerial = null; if (args[0].equals("-s")) { if (args.length == 1) { printHelp(); } deviceSerial = args[1]; remainingArgsLength -= 2; } List<String> connectedDevices = Utils.getDeviceSerials(sLogger); if (connectedDevices == null || connectedDevices.size() == 0) { sLogger.log(Level.SEVERE, "No device connected."); return; } if (connectedDevices.size() == 1 && deviceSerial == null) { deviceSerial = connectedDevices.get(0); } if (deviceSerial == null) { sLogger.log(Level.SEVERE, "More than one devices connected. Please specify" + " with -s DEVICE_SERIAL"); return; } if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME)) { if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME, deviceSerial)) { sLogger.severe("LocalDrive only works with statsd versions for Android " + MIN_CODENAME + " or higher."); return; } if (args.length > 0) { switch (args[0]) { int idx = args.length - remainingArgsLength; if (remainingArgsLength > 0) { switch (args[idx]) { case "clear": cmdClear(args); cmdClear(args, idx, deviceSerial); return; case "get-data": cmdGetData(args); cmdGetData(args, idx, deviceSerial); return; case "remove": cmdRemove(args); cmdRemove(args, idx); return; case "update": cmdUpdate(args); cmdUpdate(args, idx, deviceSerial); return; case "upload": cmdUpload(args); cmdUpload(args, idx, deviceSerial); return; } } Loading @@ -128,17 +160,18 @@ public class LocalDrive { } // upload CONFIG_FILE [CONFIG_ID] [--binary] private static boolean cmdUpload(String[] args) { return updateConfig(args, true); private static boolean cmdUpload(String[] args, int idx, String deviceSerial) { return updateConfig(args, idx, true, deviceSerial); } // update CONFIG_FILE [CONFIG_ID] [--binary] private static boolean cmdUpdate(String[] args) { return updateConfig(args, false); private static boolean cmdUpdate(String[] args, int idx, String deviceSerial) { return updateConfig(args, idx, false, deviceSerial); } private static boolean updateConfig(String[] args, boolean removeOldConfig) { int argCount = args.length - 1; // Used up one for upload/update. private static boolean updateConfig(String[] args, int idx, boolean removeOldConfig, String deviceSerial) { int argCount = args.length - 1 - idx; // Used up one for upload/update. // Get CONFIG_FILE if (argCount < 1) { Loading @@ -146,7 +179,7 @@ public class LocalDrive { printHelp(); return false; } final String origConfigLocation = args[1]; final String origConfigLocation = args[idx + 1]; if (!new File(origConfigLocation).exists()) { sLogger.severe("Error - Cannot find the provided config file: " + origConfigLocation); return false; Loading @@ -154,13 +187,13 @@ public class LocalDrive { argCount--; // Get --binary boolean binary = contains(args, 2, BINARY_FLAG); boolean binary = contains(args, idx + 2, BINARY_FLAG); if (binary) argCount --; // Get CONFIG_ID long configId; try { configId = getConfigId(argCount < 1, args, 2); configId = getConfigId(argCount < 1, args, idx + 2); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -174,7 +207,8 @@ public class LocalDrive { try { Utils.runCommand(null, sLogger, "adb", "shell", Utils.CMD_REMOVE_CONFIG, Utils.SHELL_UID, String.valueOf(configId)); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger, deviceSerial); } catch (InterruptedException | IOException e) { sLogger.severe("Failed to remove config: " + e.getMessage()); return false; Loading Loading @@ -218,19 +252,19 @@ public class LocalDrive { } // get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map] private static boolean cmdGetData(String[] args) { boolean binary = contains(args, 1, BINARY_FLAG); boolean noUidMap = contains(args, 1, NO_UID_MAP_FLAG); boolean clearData = contains(args, 1, CLEAR_DATA); private static boolean cmdGetData(String[] args, int idx, String deviceSerial) { boolean binary = contains(args, idx + 1, BINARY_FLAG); boolean noUidMap = contains(args, idx + 1, NO_UID_MAP_FLAG); boolean clearData = contains(args, idx + 1, CLEAR_DATA); // Get CONFIG_ID int argCount = args.length - 1; // Used up one for get-data. int argCount = args.length - 1 - idx; // Used up one for get-data. if (binary) argCount--; if (noUidMap) argCount--; if (clearData) argCount--; long configId; try { configId = getConfigId(argCount < 1, args, 1); configId = getConfigId(argCount < 1, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -243,7 +277,8 @@ public class LocalDrive { // Even if the args request no modifications, we still parse it to make sure it's valid. ConfigMetricsReportList reportList; try { reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger); reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger, deviceSerial); } catch (IOException | InterruptedException e) { sLogger.severe("Failed to get report list: " + e.getMessage()); return false; Loading Loading @@ -274,11 +309,11 @@ public class LocalDrive { } // clear [CONFIG_ID] private static boolean cmdClear(String[] args) { private static boolean cmdClear(String[] args, int idx, String deviceSerial) { // Get CONFIG_ID long configId; try { configId = getConfigId(false, args, 1); configId = getConfigId(false, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -287,7 +322,8 @@ public class LocalDrive { sLogger.fine(String.format("cmdClear with %d", configId)); try { Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger, deviceSerial); } catch (IOException | InterruptedException e) { sLogger.severe("Failed to get report list: " + e.getMessage()); return false; Loading @@ -296,11 +332,11 @@ public class LocalDrive { } // remove [CONFIG_ID] private static boolean cmdRemove(String[] args) { private static boolean cmdRemove(String[] args, int idx) { // Get CONFIG_ID long configId; try { configId = getConfigId(false, args, 1); configId = getConfigId(false, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java +47 −15 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; Loading Loading @@ -71,6 +72,7 @@ public class TestDrive { private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName()); private String mAdditionalAllowedPackage; private String mDeviceSerial; private final Set<Long> mTrackedMetrics = new HashSet<>(); public static void main(String[] args) { Loading @@ -81,15 +83,41 @@ public class TestDrive { if (args.length < 1) { LOGGER.log(Level.SEVERE, "Usage: ./test_drive [-p additional_allowed_package] " + "[-s DEVICE_SERIAL_NUMBER]" + "<atomId1> <atomId2> ... <atomIdN>"); return; } if (args.length >= 3 && args[0].equals("-p")) { testDrive.mAdditionalAllowedPackage = args[1]; List<String> connectedDevices = Utils.getDeviceSerials(LOGGER); if (connectedDevices == null || connectedDevices.size() == 0) { LOGGER.log(Level.SEVERE, "No device connected."); return; } int arg_index = 0; while (arg_index < args.length) { String arg = args[arg_index]; if (arg.equals("-p")) { testDrive.mAdditionalAllowedPackage = args[++arg_index]; } else if (arg.equals("-s")) { testDrive.mDeviceSerial = args[++arg_index]; } else { break; } arg_index++; } if (connectedDevices.size() == 1 && testDrive.mDeviceSerial == null) { testDrive.mDeviceSerial = connectedDevices.get(0); } for (int i = testDrive.mAdditionalAllowedPackage == null ? 0 : 2; i < args.length; i++) { if (testDrive.mDeviceSerial == null) { LOGGER.log(Level.SEVERE, "More than one devices connected. Please specify" + " with -s DEVICE_SERIAL"); return; } for (int i = arg_index; i < args.length; i++) { try { int atomId = Integer.valueOf(args[i]); if (Atom.getDescriptor().findFieldByNumber(atomId) == null) { Loading @@ -109,7 +137,7 @@ public class TestDrive { LOGGER.log(Level.SEVERE, "Failed to create valid config."); return; } remoteConfigPath = testDrive.pushConfig(config); remoteConfigPath = testDrive.pushConfig(config, testDrive.mDeviceSerial); LOGGER.info("Pushed the following config to statsd:"); LOGGER.info(config.toString()); if (!hasPulledAtom(trackedAtoms)) { Loading @@ -120,17 +148,18 @@ public class TestDrive { } else { LOGGER.info("Now wait for 1.5 minutes ..."); Thread.sleep(15_000); Utils.logAppBreadcrumb(0, 0, LOGGER); Utils.logAppBreadcrumb(0, 0, LOGGER, testDrive.mDeviceSerial); Thread.sleep(75_000); } testDrive.dumpMetrics(); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to test drive: " + e.getMessage(), e); } finally { testDrive.removeConfig(); testDrive.removeConfig(testDrive.mDeviceSerial); if (remoteConfigPath != null) { try { Utils.runCommand(null, LOGGER, "adb", "shell", "rm", remoteConfigPath); Utils.runCommand(null, LOGGER, "adb", "-s", testDrive.mDeviceSerial, "shell", "rm", remoteConfigPath); } catch (Exception e) { LOGGER.log(Level.WARNING, "Unable to remove remote config file: " + remoteConfigPath, e); Loading @@ -140,7 +169,8 @@ public class TestDrive { } private void dumpMetrics() throws Exception { ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER); ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER, mDeviceSerial); // We may get multiple reports. Take the last one. ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1); for (StatsLogReport statsLog : report.getMetricsList()) { Loading Loading @@ -216,22 +246,24 @@ public class TestDrive { return atomMatcherBuilder.build(); } private static String pushConfig(StatsdConfig config) throws IOException, InterruptedException { private static String pushConfig(StatsdConfig config, String deviceSerial) throws IOException, InterruptedException { File configFile = File.createTempFile("statsdconfig", ".config"); configFile.deleteOnExit(); Files.write(config.toByteArray(), configFile); String remotePath = "/data/local/tmp/" + configFile.getName(); Utils.runCommand(null, LOGGER, "adb", "push", configFile.getAbsolutePath(), remotePath); Utils.runCommand(null, LOGGER, "adb", "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG, Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "push", configFile.getAbsolutePath(), remotePath); Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG, String.valueOf(CONFIG_ID)); return remotePath; } private static void removeConfig() { private static void removeConfig(String deviceSerial) { try { Utils.runCommand(null, LOGGER, "adb", "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID)); Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID)); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to remove config: " + e.getMessage()); } Loading Loading
cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java +44 −5 Original line number Diff line number Diff line Loading @@ -17,16 +17,23 @@ package com.android.statsd.shelltools; import com.android.os.StatsLog.ConfigMetricsReportList; import com.google.common.io.Files; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Utilities for local use of statsd. Loading Loading @@ -80,7 +87,8 @@ public class Utils { * @throws InterruptedException */ public static ConfigMetricsReportList getReportList(long configId, boolean clearData, boolean useShellUid, Logger logger) throws IOException, InterruptedException { boolean useShellUid, Logger logger, String deviceSerial) throws IOException, InterruptedException { try { File outputFile = File.createTempFile("statsdret", ".bin"); outputFile.deleteOnExit(); Loading @@ -88,6 +96,8 @@ public class Utils { outputFile, logger, "adb", "-s", deviceSerial, "shell", CMD_DUMP_REPORT, useShellUid ? SHELL_UID : "", Loading Loading @@ -117,12 +127,14 @@ public class Utils { * @throws IOException * @throws InterruptedException */ public static void logAppBreadcrumb(int label, int state, Logger logger) public static void logAppBreadcrumb(int label, int state, Logger logger, String deviceSerial) throws IOException, InterruptedException { runCommand( null, logger, "adb", "-s", deviceSerial, "shell", CMD_LOG_APP_BREADCRUMB, String.valueOf(label), Loading @@ -145,13 +157,14 @@ public class Utils { * Algorithm: true if (sdk >= minSdk) || (sdk == minSdk-1 && codeName.startsWith(minCodeName)) * If all else fails, assume it will work (letting future commands deal with any errors). */ public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename) { public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename, String deviceSerial) { BufferedReader in = null; try { File outFileSdk = File.createTempFile("shelltools_sdk", "tmp"); outFileSdk.deleteOnExit(); runCommand(outFileSdk, logger, "adb", "shell", "getprop", "ro.build.version.sdk"); "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.sdk"); in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileSdk))); // If NullPointerException/NumberFormatException/etc., just catch and return true. int sdk = Integer.parseInt(in.readLine().trim()); Loading @@ -162,7 +175,7 @@ public class Utils { File outFileCode = File.createTempFile("shelltools_codename", "tmp"); outFileCode.deleteOnExit(); runCommand(outFileCode, logger, "adb", "shell", "getprop", "ro.build.version.codename"); "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.codename"); in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileCode))); return in.readLine().startsWith(minCodename); } else { Loading Loading @@ -190,4 +203,30 @@ public class Utils { return record.getMessage() + "\n"; } } /** * Parse the result of "adb devices" to return the list of connected devices. * @param logger Logger to log error messages * @return List of the serial numbers of the connected devices. */ public static List<String> getDeviceSerials(Logger logger) { try { ArrayList<String> devices = new ArrayList<>(); File outFile = File.createTempFile("device_serial", "tmp"); outFile.deleteOnExit(); Utils.runCommand(outFile, logger, "adb", "devices"); List<String> outputLines = Files.readLines(outFile, Charset.defaultCharset()); Pattern regex = Pattern.compile("^(.*)\tdevice$"); for (String line : outputLines) { Matcher m = regex.matcher(line); if (m.find()) { devices.add(m.group(1)); } } return devices; } catch (Exception ex) { logger.log(Level.SEVERE, "Failed to list connected devices: " + ex.getMessage()); } return null; } }
cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java +71 −35 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ import com.google.protobuf.TextFormat; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** Loading @@ -49,7 +51,7 @@ public class LocalDrive { public static final String HELP_STRING = "Usage:\n\n" + "statsd_localdrive upload CONFIG_FILE [CONFIG_ID] [--binary]\n" + "statsd_localdrive [-s DEVICE_SERIAL] upload CONFIG_FILE [CONFIG_ID] [--binary]\n" + " Uploads the given statsd config file (in binary or human-readable-text format).\n" + " If a config with this id already exists, removes it first.\n" + " CONFIG_FILE Location of config file on host.\n" + Loading @@ -59,12 +61,12 @@ public class LocalDrive { // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID "\n" + "statsd_localdrive update CONFIG_FILE [CONFIG_ID] [--binary]\n" + "statsd_localdrive [-s DEVICE_SERIAL] update CONFIG_FILE [CONFIG_ID] [--binary]\n" + " Same as upload, but does not remove the old config first (if it already exists).\n" + // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID "\n" + "statsd_localdrive get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" + "statsd_localdrive [-s DEVICE_SERIAL] get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" + " Prints the output statslog data (in binary or human-readable-text format).\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + " --binary Output should be in binary, instead of default human-readable text.\n" + Loading @@ -75,13 +77,13 @@ public class LocalDrive { // --include_current_bucket --proto "\n" + "statsd_localdrive remove [CONFIG_ID]\n" + "statsd_localdrive [-s DEVICE_SERIAL] remove [CONFIG_ID]\n" + " Removes the config.\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + // Equivalent to: adb shell cmd stats config remove SHELL_UID CONFIG_ID "\n" + "statsd_localdrive clear [CONFIG_ID]\n" + "statsd_localdrive [-s DEVICE_SERIAL] clear [CONFIG_ID]\n" + " Clears the data associated with the config.\n" + " CONFIG_ID Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" + // Similar to: adb shell cmd stats dump-report SHELL_UID CONFIG_ID Loading @@ -94,29 +96,59 @@ public class LocalDrive { /** Usage: make statsd_localdrive && statsd_localdrive */ public static void main(String[] args) { Utils.setUpLogger(sLogger, DEBUG); if (args.length == 0) { printHelp(); return; } int remainingArgsLength = args.length; String deviceSerial = null; if (args[0].equals("-s")) { if (args.length == 1) { printHelp(); } deviceSerial = args[1]; remainingArgsLength -= 2; } List<String> connectedDevices = Utils.getDeviceSerials(sLogger); if (connectedDevices == null || connectedDevices.size() == 0) { sLogger.log(Level.SEVERE, "No device connected."); return; } if (connectedDevices.size() == 1 && deviceSerial == null) { deviceSerial = connectedDevices.get(0); } if (deviceSerial == null) { sLogger.log(Level.SEVERE, "More than one devices connected. Please specify" + " with -s DEVICE_SERIAL"); return; } if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME)) { if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME, deviceSerial)) { sLogger.severe("LocalDrive only works with statsd versions for Android " + MIN_CODENAME + " or higher."); return; } if (args.length > 0) { switch (args[0]) { int idx = args.length - remainingArgsLength; if (remainingArgsLength > 0) { switch (args[idx]) { case "clear": cmdClear(args); cmdClear(args, idx, deviceSerial); return; case "get-data": cmdGetData(args); cmdGetData(args, idx, deviceSerial); return; case "remove": cmdRemove(args); cmdRemove(args, idx); return; case "update": cmdUpdate(args); cmdUpdate(args, idx, deviceSerial); return; case "upload": cmdUpload(args); cmdUpload(args, idx, deviceSerial); return; } } Loading @@ -128,17 +160,18 @@ public class LocalDrive { } // upload CONFIG_FILE [CONFIG_ID] [--binary] private static boolean cmdUpload(String[] args) { return updateConfig(args, true); private static boolean cmdUpload(String[] args, int idx, String deviceSerial) { return updateConfig(args, idx, true, deviceSerial); } // update CONFIG_FILE [CONFIG_ID] [--binary] private static boolean cmdUpdate(String[] args) { return updateConfig(args, false); private static boolean cmdUpdate(String[] args, int idx, String deviceSerial) { return updateConfig(args, idx, false, deviceSerial); } private static boolean updateConfig(String[] args, boolean removeOldConfig) { int argCount = args.length - 1; // Used up one for upload/update. private static boolean updateConfig(String[] args, int idx, boolean removeOldConfig, String deviceSerial) { int argCount = args.length - 1 - idx; // Used up one for upload/update. // Get CONFIG_FILE if (argCount < 1) { Loading @@ -146,7 +179,7 @@ public class LocalDrive { printHelp(); return false; } final String origConfigLocation = args[1]; final String origConfigLocation = args[idx + 1]; if (!new File(origConfigLocation).exists()) { sLogger.severe("Error - Cannot find the provided config file: " + origConfigLocation); return false; Loading @@ -154,13 +187,13 @@ public class LocalDrive { argCount--; // Get --binary boolean binary = contains(args, 2, BINARY_FLAG); boolean binary = contains(args, idx + 2, BINARY_FLAG); if (binary) argCount --; // Get CONFIG_ID long configId; try { configId = getConfigId(argCount < 1, args, 2); configId = getConfigId(argCount < 1, args, idx + 2); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -174,7 +207,8 @@ public class LocalDrive { try { Utils.runCommand(null, sLogger, "adb", "shell", Utils.CMD_REMOVE_CONFIG, Utils.SHELL_UID, String.valueOf(configId)); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger, deviceSerial); } catch (InterruptedException | IOException e) { sLogger.severe("Failed to remove config: " + e.getMessage()); return false; Loading Loading @@ -218,19 +252,19 @@ public class LocalDrive { } // get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map] private static boolean cmdGetData(String[] args) { boolean binary = contains(args, 1, BINARY_FLAG); boolean noUidMap = contains(args, 1, NO_UID_MAP_FLAG); boolean clearData = contains(args, 1, CLEAR_DATA); private static boolean cmdGetData(String[] args, int idx, String deviceSerial) { boolean binary = contains(args, idx + 1, BINARY_FLAG); boolean noUidMap = contains(args, idx + 1, NO_UID_MAP_FLAG); boolean clearData = contains(args, idx + 1, CLEAR_DATA); // Get CONFIG_ID int argCount = args.length - 1; // Used up one for get-data. int argCount = args.length - 1 - idx; // Used up one for get-data. if (binary) argCount--; if (noUidMap) argCount--; if (clearData) argCount--; long configId; try { configId = getConfigId(argCount < 1, args, 1); configId = getConfigId(argCount < 1, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -243,7 +277,8 @@ public class LocalDrive { // Even if the args request no modifications, we still parse it to make sure it's valid. ConfigMetricsReportList reportList; try { reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger); reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger, deviceSerial); } catch (IOException | InterruptedException e) { sLogger.severe("Failed to get report list: " + e.getMessage()); return false; Loading Loading @@ -274,11 +309,11 @@ public class LocalDrive { } // clear [CONFIG_ID] private static boolean cmdClear(String[] args) { private static boolean cmdClear(String[] args, int idx, String deviceSerial) { // Get CONFIG_ID long configId; try { configId = getConfigId(false, args, 1); configId = getConfigId(false, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading @@ -287,7 +322,8 @@ public class LocalDrive { sLogger.fine(String.format("cmdClear with %d", configId)); try { Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger); Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger, deviceSerial); } catch (IOException | InterruptedException e) { sLogger.severe("Failed to get report list: " + e.getMessage()); return false; Loading @@ -296,11 +332,11 @@ public class LocalDrive { } // remove [CONFIG_ID] private static boolean cmdRemove(String[] args) { private static boolean cmdRemove(String[] args, int idx) { // Get CONFIG_ID long configId; try { configId = getConfigId(false, args, 1); configId = getConfigId(false, args, idx + 1); } catch (NumberFormatException e) { sLogger.severe("Invalid config id provided."); printHelp(); Loading
cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java +47 −15 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; Loading Loading @@ -71,6 +72,7 @@ public class TestDrive { private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName()); private String mAdditionalAllowedPackage; private String mDeviceSerial; private final Set<Long> mTrackedMetrics = new HashSet<>(); public static void main(String[] args) { Loading @@ -81,15 +83,41 @@ public class TestDrive { if (args.length < 1) { LOGGER.log(Level.SEVERE, "Usage: ./test_drive [-p additional_allowed_package] " + "[-s DEVICE_SERIAL_NUMBER]" + "<atomId1> <atomId2> ... <atomIdN>"); return; } if (args.length >= 3 && args[0].equals("-p")) { testDrive.mAdditionalAllowedPackage = args[1]; List<String> connectedDevices = Utils.getDeviceSerials(LOGGER); if (connectedDevices == null || connectedDevices.size() == 0) { LOGGER.log(Level.SEVERE, "No device connected."); return; } int arg_index = 0; while (arg_index < args.length) { String arg = args[arg_index]; if (arg.equals("-p")) { testDrive.mAdditionalAllowedPackage = args[++arg_index]; } else if (arg.equals("-s")) { testDrive.mDeviceSerial = args[++arg_index]; } else { break; } arg_index++; } if (connectedDevices.size() == 1 && testDrive.mDeviceSerial == null) { testDrive.mDeviceSerial = connectedDevices.get(0); } for (int i = testDrive.mAdditionalAllowedPackage == null ? 0 : 2; i < args.length; i++) { if (testDrive.mDeviceSerial == null) { LOGGER.log(Level.SEVERE, "More than one devices connected. Please specify" + " with -s DEVICE_SERIAL"); return; } for (int i = arg_index; i < args.length; i++) { try { int atomId = Integer.valueOf(args[i]); if (Atom.getDescriptor().findFieldByNumber(atomId) == null) { Loading @@ -109,7 +137,7 @@ public class TestDrive { LOGGER.log(Level.SEVERE, "Failed to create valid config."); return; } remoteConfigPath = testDrive.pushConfig(config); remoteConfigPath = testDrive.pushConfig(config, testDrive.mDeviceSerial); LOGGER.info("Pushed the following config to statsd:"); LOGGER.info(config.toString()); if (!hasPulledAtom(trackedAtoms)) { Loading @@ -120,17 +148,18 @@ public class TestDrive { } else { LOGGER.info("Now wait for 1.5 minutes ..."); Thread.sleep(15_000); Utils.logAppBreadcrumb(0, 0, LOGGER); Utils.logAppBreadcrumb(0, 0, LOGGER, testDrive.mDeviceSerial); Thread.sleep(75_000); } testDrive.dumpMetrics(); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to test drive: " + e.getMessage(), e); } finally { testDrive.removeConfig(); testDrive.removeConfig(testDrive.mDeviceSerial); if (remoteConfigPath != null) { try { Utils.runCommand(null, LOGGER, "adb", "shell", "rm", remoteConfigPath); Utils.runCommand(null, LOGGER, "adb", "-s", testDrive.mDeviceSerial, "shell", "rm", remoteConfigPath); } catch (Exception e) { LOGGER.log(Level.WARNING, "Unable to remove remote config file: " + remoteConfigPath, e); Loading @@ -140,7 +169,8 @@ public class TestDrive { } private void dumpMetrics() throws Exception { ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER); ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER, mDeviceSerial); // We may get multiple reports. Take the last one. ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1); for (StatsLogReport statsLog : report.getMetricsList()) { Loading Loading @@ -216,22 +246,24 @@ public class TestDrive { return atomMatcherBuilder.build(); } private static String pushConfig(StatsdConfig config) throws IOException, InterruptedException { private static String pushConfig(StatsdConfig config, String deviceSerial) throws IOException, InterruptedException { File configFile = File.createTempFile("statsdconfig", ".config"); configFile.deleteOnExit(); Files.write(config.toByteArray(), configFile); String remotePath = "/data/local/tmp/" + configFile.getName(); Utils.runCommand(null, LOGGER, "adb", "push", configFile.getAbsolutePath(), remotePath); Utils.runCommand(null, LOGGER, "adb", "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG, Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "push", configFile.getAbsolutePath(), remotePath); Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG, String.valueOf(CONFIG_ID)); return remotePath; } private static void removeConfig() { private static void removeConfig(String deviceSerial) { try { Utils.runCommand(null, LOGGER, "adb", "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID)); Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial, "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID)); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to remove config: " + e.getMessage()); } Loading