Instrument apk install times

Test: unit tests
Bug: None
Change-Id: I4f941a26aee51657448cc67b8318ca76be1905c4
diff --git a/invocation_interfaces/com/android/tradefed/invoker/logger/InvocationMetricLogger.java b/invocation_interfaces/com/android/tradefed/invoker/logger/InvocationMetricLogger.java
index 09174e1..e78ff30 100644
--- a/invocation_interfaces/com/android/tradefed/invoker/logger/InvocationMetricLogger.java
+++ b/invocation_interfaces/com/android/tradefed/invoker/logger/InvocationMetricLogger.java
@@ -87,6 +87,9 @@
         DELETE_DEVICE_FILE_COUNT("delete_device_file_count", true),
         DOES_FILE_EXISTS_TIME("does_file_exists_time_ms", true),
         DOES_FILE_EXISTS_COUNT("does_file_exists_count", true),
+        // Represents the time and count for installing packages
+        PACKAGE_INSTALL_TIME("package_install_time_ms", true),
+        PACKAGE_INSTALL_COUNT("package_install_count", true),
         // Capture the time spent isolating a retry with reset
         RESET_RETRY_ISOLATION_PAIR("reset_isolation_timestamp_pair", true),
         // Capture the time spent isolating a retry with reboot
diff --git a/src/com/android/tradefed/device/TestDevice.java b/src/com/android/tradefed/device/TestDevice.java
index 7950adc..636d9dd 100644
--- a/src/com/android/tradefed/device/TestDevice.java
+++ b/src/com/android/tradefed/device/TestDevice.java
@@ -24,6 +24,8 @@
 import com.android.ddmlib.SyncException;
 import com.android.ddmlib.TimeoutException;
 import com.android.tradefed.config.GlobalConfiguration;
+import com.android.tradefed.invoker.logger.InvocationMetricLogger;
+import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ByteArrayInputStreamSource;
 import com.android.tradefed.result.FileInputStreamSource;
@@ -431,40 +433,49 @@
     private String internalInstallPackages(
             final List<File> packageFiles, final boolean reinstall, final List<String> extraArgs)
             throws DeviceNotAvailableException {
-        // use array to store response, so it can be returned to caller
-        final String[] response = new String[1];
-        DeviceAction installAction =
-                new DeviceAction() {
-                    @Override
-                    public boolean run() throws InstallException {
-                        try {
-                            getIDevice()
-                                    .installPackages(
-                                            packageFiles,
-                                            reinstall,
-                                            extraArgs,
-                                            INSTALL_TIMEOUT_MINUTES,
-                                            TimeUnit.MINUTES);
-                            response[0] = null;
-                            return true;
-                        } catch (InstallException e) {
-                            response[0] = e.getMessage();
-                            if (response[0] == null) {
-                                response[0] =
-                                        String.format(
-                                                "InstallException: %s",
-                                                StreamUtil.getStackTrace(e));
+        long startTime = System.currentTimeMillis();
+        try {
+            // use array to store response, so it can be returned to caller
+            final String[] response = new String[1];
+            DeviceAction installAction =
+                    new DeviceAction() {
+                        @Override
+                        public boolean run() throws InstallException {
+                            try {
+                                getIDevice()
+                                        .installPackages(
+                                                packageFiles,
+                                                reinstall,
+                                                extraArgs,
+                                                INSTALL_TIMEOUT_MINUTES,
+                                                TimeUnit.MINUTES);
+                                response[0] = null;
+                                return true;
+                            } catch (InstallException e) {
+                                response[0] = e.getMessage();
+                                if (response[0] == null) {
+                                    response[0] =
+                                            String.format(
+                                                    "InstallException: %s",
+                                                    StreamUtil.getStackTrace(e));
+                                }
+                                return false;
                             }
-                            return false;
                         }
-                    }
-                };
-        performDeviceAction(
-                String.format("install %s", packageFiles.toString()),
-                installAction,
-                MAX_RETRY_ATTEMPTS);
-        allowLegacyStorageForApps(packageFiles);
-        return response[0];
+                    };
+            performDeviceAction(
+                    String.format("install %s", packageFiles.toString()),
+                    installAction,
+                    MAX_RETRY_ATTEMPTS);
+            allowLegacyStorageForApps(packageFiles);
+            return response[0];
+        } finally {
+            InvocationMetricLogger.addInvocationMetrics(
+                    InvocationMetricKey.PACKAGE_INSTALL_COUNT, 1);
+            InvocationMetricLogger.addInvocationMetrics(
+                    InvocationMetricKey.PACKAGE_INSTALL_TIME,
+                    System.currentTimeMillis() - startTime);
+        }
     }
 
     /**