Merge "perfboot.py: ignore tags not listed in /system/etc/event-log-tags"
diff --git a/adb/Android.mk b/adb/Android.mk
index 46905b3..e2d0bb1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -22,6 +22,15 @@
     -Wno-missing-field-initializers \
     -DADB_REVISION='"$(adb_version)"' \
 
+# Define windows.h and tchar.h Unicode preprocessor symbols so that
+# CreateFile(), _tfopen(), etc. map to versions that take wchar_t*, breaking the
+# build if you accidentally pass char*. Fix by calling like:
+# CreateFileW(widen(utf8).c_str()).
+ADB_COMMON_windows_CFLAGS := \
+    -DUNICODE=1 -D_UNICODE=1 \
+
+ADB_COMMON_CFLAGS += $(ADB_COMMON_$(HOST_OS)_CFLAGS)
+
 # libadb
 # =========================================================
 
diff --git a/adb/adb.cpp b/adb/adb.cpp
index c5ab7b0..fd46dea 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -580,8 +580,8 @@
                            FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,
                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     if (nul_read == INVALID_HANDLE_VALUE) {
-        fprintf(stderr, "CreateFileW(nul, GENERIC_READ) failure, error %ld\n",
-                GetLastError());
+        fprintf(stderr, "CreateFileW(nul, GENERIC_READ) failed: %s\n",
+                SystemErrorCodeToString(GetLastError()).c_str());
         return -1;
     }
 
@@ -589,8 +589,8 @@
                             FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     if (nul_write == INVALID_HANDLE_VALUE) {
-        fprintf(stderr, "CreateFileW(nul, GENERIC_WRITE) failure, error %ld\n",
-                GetLastError());
+        fprintf(stderr, "CreateFileW(nul, GENERIC_WRITE) failed: %s\n",
+                SystemErrorCodeToString(GetLastError()).c_str());
         CloseHandle(nul_read);
         return -1;
     }
@@ -598,7 +598,8 @@
     /* create pipe, and ensure its read handle isn't inheritable */
     ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
     if (!ret) {
-        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
+        fprintf(stderr, "CreatePipe() failed: %s\n",
+                SystemErrorCodeToString(GetLastError()).c_str());
         CloseHandle(nul_read);
         CloseHandle(nul_write);
         return -1;
@@ -640,8 +641,8 @@
                                              arraysize(program_path));
     if ((module_result == arraysize(program_path)) || (module_result == 0)) {
         // String truncation or some other error.
-        fprintf(stderr, "GetModuleFileNameW() failure, error %ld\n",
-                GetLastError());
+        fprintf(stderr, "GetModuleFileNameW() failed: %s\n",
+                SystemErrorCodeToString(GetLastError()).c_str());
         return -1;
     }
     WCHAR args[64];
@@ -666,7 +667,8 @@
     CloseHandle( pipe_write );
 
     if (!ret) {
-        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
+        fprintf(stderr, "CreateProcess failed: %s\n",
+                SystemErrorCodeToString(GetLastError()).c_str());
         CloseHandle( pipe_read );
         return -1;
     }
@@ -682,7 +684,8 @@
         ret = ReadFile( pipe_read, temp, 3, &count, NULL );
         CloseHandle( pipe_read );
         if ( !ret ) {
-            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
+            fprintf(stderr, "could not read ok from ADB Server, error: %s\n",
+                    SystemErrorCodeToString(GetLastError()).c_str());
             return -1;
         }
         if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 966e61d..e7f82a9 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -305,7 +305,10 @@
     home = getenv("ANDROID_SDK_HOME");
     if (!home) {
         WCHAR path[MAX_PATH];
-        if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path))) {
+        const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
+        if (FAILED(hr)) {
+            D("SHGetFolderPathW failed: %s\n",
+              SystemErrorCodeToString(hr).c_str());
             return -1;
         }
         home_str = narrow(path);
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 08f267b..ec28ccd 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -90,9 +90,9 @@
 
 std::string SystemErrorCodeToString(const DWORD error_code) {
   const int kErrorMessageBufferSize = 256;
-  char msgbuf[kErrorMessageBufferSize];
+  WCHAR msgbuf[kErrorMessageBufferSize];
   DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
-  DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf,
+  DWORD len = FormatMessageW(flags, nullptr, error_code, 0, msgbuf,
                              arraysize(msgbuf), nullptr);
   if (len == 0) {
     return android::base::StringPrintf(
@@ -100,7 +100,8 @@
         error_code);
   }
 
-  std::string msg(msgbuf);
+  // Convert UTF-16 to UTF-8.
+  std::string msg(narrow(msgbuf));
   // Messages returned by the system end with line breaks.
   msg = android::base::Trim(msg);
   // There are many Windows error messages compared to POSIX, so include the
@@ -426,7 +427,8 @@
                 return -1;
 
             default:
-                D( "unknown error: %ld\n", err );
+                D( "unknown error: %s\n",
+                   SystemErrorCodeToString( err ).c_str() );
                 errno = ENOENT;
                 return -1;
         }
@@ -469,7 +471,8 @@
                 return -1;
 
             default:
-                D( "unknown error: %ld\n", err );
+                D( "unknown error: %s\n",
+                   SystemErrorCodeToString( err ).c_str() );
                 errno = ENOENT;
                 return -1;
         }
@@ -803,6 +806,14 @@
     snprintf(port_str, sizeof(port_str), "%d", port);
 
     struct addrinfo* addrinfo_ptr = nullptr;
+
+#if (NTDDI_VERSION >= NTDDI_WINXPSP2) || (_WIN32_WINNT >= _WIN32_WINNT_WS03)
+    // TODO: When the Android SDK tools increases the Windows system
+    // requirements >= WinXP SP2, switch to GetAddrInfoW(widen(host).c_str()).
+#else
+    // Otherwise, keep using getaddrinfo(), or do runtime API detection
+    // with GetProcAddress("GetAddrInfoW").
+#endif
     if (getaddrinfo(host.c_str(), port_str, &hints, &addrinfo_ptr) != 0) {
         *error = SystemErrorCodeToString(WSAGetLastError());
         D("could not resolve host '%s' and port %s: %s\n", host.c_str(),
@@ -2315,7 +2326,7 @@
         memset(input_record, 0, sizeof(*input_record));
         if (!ReadConsoleInputA(console, input_record, 1, &read_count)) {
             D("_get_interesting_input_record_uncached: ReadConsoleInputA() "
-              "failure, error %ld\n", GetLastError());
+              "failed: %s\n", SystemErrorCodeToString(GetLastError()).c_str());
             errno = EIO;
             return false;
         }
@@ -3129,8 +3140,8 @@
         if (!SetConsoleMode(in, _old_console_mode & ~(ENABLE_PROCESSED_INPUT |
             ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))) {
             // This really should not fail.
-            D("stdin_raw_init: SetConsoleMode() failure, error %ld\n",
-                GetLastError());
+            D("stdin_raw_init: SetConsoleMode() failed: %s\n",
+              SystemErrorCodeToString(GetLastError()).c_str());
         }
 
         // Once this is set, it means that stdin has been configured for
@@ -3151,8 +3162,8 @@
 
             if (!SetConsoleMode(in, _old_console_mode)) {
                 // This really should not fail.
-                D("stdin_raw_restore: SetConsoleMode() failure, error %ld\n",
-                    GetLastError());
+                D("stdin_raw_restore: SetConsoleMode() failed: %s\n",
+                  SystemErrorCodeToString(GetLastError()).c_str());
             }
         }
     }
@@ -3237,9 +3248,10 @@
 //
 // The way to output Unicode to a Win32 console window is to call
 // WriteConsoleW() with UTF-16 text. (The user must also choose a proper font
-// such as Lucida Console or Consolas, and in the case of Chinese, must go to
-// the Control Panel and change the "system locale" to Chinese, which allows
-// a Chinese font to be used in console windows.)
+// such as Lucida Console or Consolas, and in the case of East Asian languages
+// (such as Chinese, Japanese, Korean), the user must go to the Control Panel
+// and change the "system locale" to Chinese, etc., which allows a Chinese, etc.
+// font to be used in console windows.)
 //
 // The problem is getting the C Runtime to make fprintf and related APIs call
 // WriteConsoleW() under the covers. The C Runtime API, _setmode() sounds
@@ -3294,6 +3306,10 @@
 // any NULL terminator (if you're passing an explicit size, you probably don't
 // have a NULL terminated string in the first place).
 std::wstring widen(const char* utf8, const int size) {
+    // Note: Do not call SystemErrorCodeToString() from widen() because
+    // SystemErrorCodeToString() calls narrow() which may call fatal() which
+    // calls adb_vfprintf() which calls widen(), potentially causing infinite
+    // recursion.
     const int chars_to_convert = MultiByteToWideChar(CP_UTF8, 0, utf8, size,
                                                      NULL, 0);
     if (chars_to_convert <= 0) {
@@ -3349,11 +3365,14 @@
 
 // Convert from UTF-16 to UTF-8.
 std::string narrow(const wchar_t* utf16) {
+    // Note: Do not call SystemErrorCodeToString() from narrow() because
+    // SystemErrorCodeToString() calls narrows() and we don't want potential
+    // infinite recursion.
     const int chars_required = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL,
                                                    0, NULL, NULL);
     if (chars_required <= 0) {
         // UTF-16 to UTF-8 should be lossless, so we don't expect this to fail.
-        fatal("WideCharToMultiByte failed counting: %d, GetLastError: %d",
+        fatal("WideCharToMultiByte failed counting: %d, GetLastError: %lu",
               chars_required, GetLastError());
     }
 
@@ -3371,7 +3390,7 @@
                                            chars_required, NULL, NULL);
     if (result != chars_required) {
         // UTF-16 to UTF-8 should be lossless, so we don't expect this to fail.
-        fatal("WideCharToMultiByte failed conversion: %d, GetLastError: %d",
+        fatal("WideCharToMultiByte failed conversion: %d, GetLastError: %lu",
               result, GetLastError());
     }
 
@@ -3707,7 +3726,9 @@
 
 // Shadow UTF-8 environment variable name/value pairs that are created from
 // _wenviron the first time that adb_getenv() is called. Note that this is not
-// currently updated if putenv, setenv, unsetenv are called.
+// currently updated if putenv, setenv, unsetenv are called. Note that no
+// thread synchronization is done, but we're called early enough in
+// single-threaded startup that things work ok.
 static std::unordered_map<std::string, char*> g_environ_utf8;
 
 // Make sure that shadow UTF-8 environment variables are setup.
@@ -3744,8 +3765,7 @@
 char* adb_getenv(const char* name) {
     _ensure_env_setup();
 
-    std::unordered_map<std::string, char*>::const_iterator it =
-        g_environ_utf8.find(std::string(name));
+    const auto it = g_environ_utf8.find(std::string(name));
     if (it == g_environ_utf8.end()) {
         return nullptr;
     }
diff --git a/adb/test_device.py b/adb/test_device.py
index 81c4a94..48a3f6c 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -333,107 +333,96 @@
 
     def _test_push(self, local_file, checksum):
         self.device.shell(['rm', '-rf', self.DEVICE_TEMP_FILE])
-        try:
-            self.device.push(
-                local=local_file, remote=self.DEVICE_TEMP_FILE)
-            dev_md5, _ = self.device.shell(
-                [get_md5_prog(self.device), self.DEVICE_TEMP_FILE]).split()
-            self.assertEqual(checksum, dev_md5)
-        finally:
-            self.device.shell(['rm', '-f', self.DEVICE_TEMP_FILE])
+        self.device.push(local=local_file, remote=self.DEVICE_TEMP_FILE)
+        dev_md5, _ = self.device.shell([get_md5_prog(self.device),
+                                       self.DEVICE_TEMP_FILE]).split()
+        self.assertEqual(checksum, dev_md5)
+        self.device.shell(['rm', '-f', self.DEVICE_TEMP_FILE])
 
     def test_push(self):
         """Push a randomly generated file to specified device."""
         kbytes = 512
         tmp = tempfile.NamedTemporaryFile(mode='wb', delete=False)
-        try:
-            rand_str = os.urandom(1024 * kbytes)
-            tmp.write(rand_str)
-            tmp.close()
-            self._test_push(tmp.name, compute_md5(rand_str))
-        finally:
-            os.remove(tmp.name)
+        rand_str = os.urandom(1024 * kbytes)
+        tmp.write(rand_str)
+        tmp.close()
+        self._test_push(tmp.name, compute_md5(rand_str))
+        os.remove(tmp.name)
 
     # TODO: write push directory test.
 
     def _test_pull(self, remote_file, checksum):
         tmp_write = tempfile.NamedTemporaryFile(mode='wb', delete=False)
-        try:
-            tmp_write.close()
-            self.device.pull(remote=remote_file, local=tmp_write.name)
-            with open(tmp_write.name, 'rb') as tmp_read:
-                host_contents = tmp_read.read()
-                host_md5 = compute_md5(host_contents)
-            self.assertEqual(checksum, host_md5)
-        finally:
-            os.remove(tmp_write.name)
+        tmp_write.close()
+        self.device.pull(remote=remote_file, local=tmp_write.name)
+        with open(tmp_write.name, 'rb') as tmp_read:
+            host_contents = tmp_read.read()
+            host_md5 = compute_md5(host_contents)
+        self.assertEqual(checksum, host_md5)
+        os.remove(tmp_write.name)
 
     def test_pull(self):
         """Pull a randomly generated file from specified device."""
         kbytes = 512
         self.device.shell(['rm', '-rf', self.DEVICE_TEMP_FILE])
-        try:
-            cmd = ['dd', 'if=/dev/urandom',
-                   'of={}'.format(self.DEVICE_TEMP_FILE), 'bs=1024',
-                   'count={}'.format(kbytes)]
-            self.device.shell(cmd)
-            dev_md5, _ = self.device.shell(
-                [get_md5_prog(self.device), self.DEVICE_TEMP_FILE]).split()
-            self._test_pull(self.DEVICE_TEMP_FILE, dev_md5)
-        finally:
-            self.device.shell_nocheck(['rm', self.DEVICE_TEMP_FILE])
+        cmd = ['dd', 'if=/dev/urandom',
+               'of={}'.format(self.DEVICE_TEMP_FILE), 'bs=1024',
+               'count={}'.format(kbytes)]
+        self.device.shell(cmd)
+        dev_md5, _ = self.device.shell(
+            [get_md5_prog(self.device), self.DEVICE_TEMP_FILE]).split()
+        self._test_pull(self.DEVICE_TEMP_FILE, dev_md5)
+        self.device.shell_nocheck(['rm', self.DEVICE_TEMP_FILE])
 
     def test_pull_dir(self):
         """Pull a randomly generated directory of files from the device."""
         host_dir = tempfile.mkdtemp()
-        try:
-            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
-            self.device.shell(['mkdir', '-p', self.DEVICE_TEMP_DIR])
+        self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        self.device.shell(['mkdir', '-p', self.DEVICE_TEMP_DIR])
 
-            # Populate device directory with random files.
-            temp_files = make_random_device_files(
-                self.device, in_dir=self.DEVICE_TEMP_DIR, num_files=32)
+        # Populate device directory with random files.
+        temp_files = make_random_device_files(
+            self.device, in_dir=self.DEVICE_TEMP_DIR, num_files=32)
 
-            self.device.pull(remote=self.DEVICE_TEMP_DIR, local=host_dir)
+        self.device.pull(remote=self.DEVICE_TEMP_DIR, local=host_dir)
 
-            for temp_file in temp_files:
-                host_path = os.path.join(host_dir, temp_file.base_name)
-                with open(host_path, 'rb') as host_file:
-                    host_md5 = compute_md5(host_file.read())
-                    self.assertEqual(host_md5, temp_file.checksum)
-        finally:
-            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
-            if host_dir is not None:
-                shutil.rmtree(host_dir)
+        for temp_file in temp_files:
+            host_path = os.path.join(host_dir, temp_file.base_name)
+            with open(host_path, 'rb') as host_file:
+                host_md5 = compute_md5(host_file.read())
+                self.assertEqual(host_md5, temp_file.checksum)
+
+        self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        if host_dir is not None:
+            shutil.rmtree(host_dir)
 
     def test_sync(self):
         """Sync a randomly generated directory of files to specified device."""
         base_dir = tempfile.mkdtemp()
-        try:
-            # Create mirror device directory hierarchy within base_dir.
-            full_dir_path = base_dir + self.DEVICE_TEMP_DIR
-            os.makedirs(full_dir_path)
 
-            # Create 32 random files within the host mirror.
-            temp_files = make_random_host_files(in_dir=full_dir_path,
-                                                num_files=32)
+        # Create mirror device directory hierarchy within base_dir.
+        full_dir_path = base_dir + self.DEVICE_TEMP_DIR
+        os.makedirs(full_dir_path)
 
-            # Clean up any trash on the device.
-            device = adb.get_device(product=base_dir)
-            device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        # Create 32 random files within the host mirror.
+        temp_files = make_random_host_files(in_dir=full_dir_path, num_files=32)
 
-            device.sync('data')
+        # Clean up any trash on the device.
+        device = adb.get_device(product=base_dir)
+        device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
 
-            # Confirm that every file on the device mirrors that on the host.
-            for temp_file in temp_files:
-                device_full_path = posixpath.join(
-                    self.DEVICE_TEMP_DIR, temp_file.base_name)
-                dev_md5, _ = device.shell(
-                    [get_md5_prog(self.device), device_full_path]).split()
-                self.assertEqual(temp_file.checksum, dev_md5)
-        finally:
-            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
-            shutil.rmtree(base_dir + self.DEVICE_TEMP_DIR)
+        device.sync('data')
+
+        # Confirm that every file on the device mirrors that on the host.
+        for temp_file in temp_files:
+            device_full_path = posixpath.join(self.DEVICE_TEMP_DIR,
+                                              temp_file.base_name)
+            dev_md5, _ = device.shell(
+                [get_md5_prog(self.device), device_full_path]).split()
+            self.assertEqual(temp_file.checksum, dev_md5)
+
+        self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        shutil.rmtree(base_dir + self.DEVICE_TEMP_DIR)
 
     def test_unicode_paths(self):
         """Ensure that we can support non-ASCII paths, even on Windows."""