Merge "adb: fix killing of old version of adb process"
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index 34b54e7..17c8d0a 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -48,7 +48,7 @@
   DWORD cch = arraysize(profiles_dir);
 
   // On typical Windows 7, returns C:\Users
-  ASSERT_TRUE(GetProfilesDirectory(profiles_dir, &cch));
+  ASSERT_TRUE(GetProfilesDirectoryA(profiles_dir, &cch));
 
   ASSERT_TRUE(directory_exists(profiles_dir));
 
diff --git a/adb/device.py b/adb/device.py
index b6eaad6..a15675b 100644
--- a/adb/device.py
+++ b/adb/device.py
@@ -170,8 +170,12 @@
         out, _ = p.communicate()
         return self._parse_shell_output(out)
 
-    def install(self, filename):
-        return self._simple_call(['install', filename])
+    def install(self, filename, replace=False):
+        cmd = ['install']
+        if replace:
+            cmd.append('-r')
+        cmd.append(filename)
+        return self._simple_call(cmd)
 
     def push(self, local, remote):
         return self._simple_call(['push', local, remote])
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index af65130..939f319 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -34,6 +34,10 @@
 
 #define  DBG   D
 
+// There's no strerror equivalent for the errors returned by IOKit.
+// https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Handling_Errors/AH_Handling_Errors.html
+// Search the web for "IOReturn.h" to find a complete up to date list.
+
 static IONotificationPortRef    notificationPort = 0;
 static io_iterator_t            notificationIterator;
 
@@ -362,7 +366,7 @@
 
             handle->zero_mask = maxPacketSize - 1;
         } else {
-            DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
+            DBG("ERR: FindDeviceInterface - could not get pipe properties (%08x)\n", kr);
             goto err_get_pipe_props;
         }
     }
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 2158421..77b9268 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -78,38 +78,21 @@
   EXPECT_EQ("abc", s);
 }
 
-TEST(file, ReadFully) {
-#ifdef _WIN32
-  VersionFile ver;
-  ASSERT_NE(ver.filename, nullptr);
-  const char* filename = ver.filename;
-  // Note that ReadFully() does CR/LF translation, so we expect \n, not \r\n.
-  const char expected[] = "\nMicrosoft Windows";
-#else
-  const char* filename = "/proc/version";
-  const char expected[] = "Linux";
-#endif
-  int fd = open(filename, O_RDONLY);
-  ASSERT_NE(-1, fd) << strerror(errno);
-
-  char buf[1024];
-  memset(buf, 0, sizeof(buf));
-  ASSERT_TRUE(android::base::ReadFully(fd, buf, sizeof(expected) - 1));
-  ASSERT_STREQ(expected, buf);
-
-  ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
-
-  ASSERT_FALSE(android::base::ReadFully(fd, buf, sizeof(buf)));
-
-  close(fd);
-}
-
 TEST(file, WriteFully) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
   ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
+
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
+
   std::string s;
-  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s))
+  s.resize(3);
+  ASSERT_TRUE(android::base::ReadFully(tf.fd, &s[0], s.size()))
     << strerror(errno);
   EXPECT_EQ("abc", s);
+
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
+
+  s.resize(1024);
+  ASSERT_FALSE(android::base::ReadFully(tf.fd, &s[0], s.size()));
 }
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index a959566..1c7eff0 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -210,7 +210,7 @@
                     handle->zero_mask = maxPacketSize - 1;
                 }
             } else {
-                ERR("could not get pipe properties\n");
+                ERR("could not get pipe properties (%08x)\n", kr);
             }
 
             if (handle->info.has_bulk_in && handle->info.has_bulk_out) {
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 46173db..9402614 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -58,7 +58,6 @@
     ALREADY_EXISTS      = -EEXIST,
     DEAD_OBJECT         = -EPIPE,
     FAILED_TRANSACTION  = (UNKNOWN_ERROR + 2),
-    JPARKS_BROKE_IT     = -EPIPE,
 #if !defined(HAVE_MS_C_RUNTIME)
     BAD_INDEX           = -EOVERFLOW,
     NOT_ENOUGH_DATA     = -ENODATA,
diff --git a/init/perfboot.py b/init/perfboot.py
index 583d640..b0efb11 100755
--- a/init/perfboot.py
+++ b/init/perfboot.py
@@ -40,6 +40,7 @@
 import argparse
 import atexit
 import cStringIO
+import glob
 import inspect
 import logging
 import math
@@ -408,9 +409,17 @@
                         'event tags are read. Every line contains one event '
                         'tag and the last event tag is used to detect that '
                         'the device has finished booting.')
+    parser.add_argument('--apk-dir', help='Specify the directory which contains '
+                        'APK files to be installed before measuring boot time.')
     return parser.parse_args()
 
 
+def install_apks(device, apk_dir):
+    for apk in glob.glob(os.path.join(apk_dir, '*.apk')):
+        print 'Installing: ' + apk
+        device.install(apk, replace=True)
+
+
 def main():
     args = parse_args()
     if args.verbose:
@@ -425,6 +434,9 @@
             device.get_prop('ro.build.version.incremental'))
     check_dm_verity_settings(device)
 
+    if args.apk_dir:
+        install_apks(device, args.apk_dir)
+
     record_list = []
     event_tags = filter_event_tags(read_event_tags(args.tags), device)
     init_perf(device, args.output, record_list, event_tags)