Merge "adb: make adb_thread_func_t return void, add adb_thread_exit."
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 474d1b4..8a16e51 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -134,7 +134,7 @@
   return result;
 }
 
-// Given a relative or absolute filepath, create the parent directory hierarchy
+// Given a relative or absolute filepath, create the directory hierarchy
 // as needed. Returns true if the hierarchy is/was setup.
 bool mkdirs(const std::string& path) {
   // TODO: all the callers do unlink && mkdirs && adb_creat ---
@@ -157,12 +157,12 @@
     return true;
   }
 
+  const std::string parent(adb_dirname(path));
+
   // If dirname returned the same path as what we passed in, don't go recursive.
   // This can happen on Windows when walking up the directory hierarchy and not
   // finding anything that already exists (unlike POSIX that will eventually
   // find . or /).
-  const std::string parent(adb_dirname(path));
-
   if (parent == path) {
     errno = ENOENT;
     return false;
@@ -174,14 +174,14 @@
   }
 
   // Now that the parent directory hierarchy of 'path' has been ensured,
-  // create parent itself.
+  // create path itself.
   if (adb_mkdir(path, 0775) == -1) {
-    // Can't just check for errno == EEXIST because it might be a file that
-    // exists.
     const int saved_errno = errno;
-    if (directory_exists(parent)) {
+    // If someone else created the directory, that is ok.
+    if (directory_exists(path)) {
       return true;
     }
+    // There might be a pre-existing file at 'path', or there might have been some other error.
     errno = saved_errno;
     return false;
   }
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index dfe6f20..f1ebaa1 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -112,20 +112,26 @@
 }
 
 void test_mkdirs(const std::string basepath) {
-  EXPECT_TRUE(mkdirs(adb_dirname(basepath)));
-  EXPECT_NE(-1, adb_creat(basepath.c_str(), 0600));
-  EXPECT_FALSE(mkdirs(basepath + "/subdir/"));
+  // Test creating a directory hierarchy.
+  EXPECT_TRUE(mkdirs(basepath));
+  // Test finding an existing directory hierarchy.
+  EXPECT_TRUE(mkdirs(basepath));
+  const std::string filepath = basepath + "/file";
+  // Verify that the hierarchy was created by trying to create a file in it.
+  EXPECT_NE(-1, adb_creat(filepath.c_str(), 0600));
+  // If a file exists where we want a directory, the operation should fail.
+  EXPECT_FALSE(mkdirs(filepath));
 }
 
 TEST(adb_utils, mkdirs) {
   TemporaryDir td;
 
   // Absolute paths.
-  test_mkdirs(std::string(td.path) + "/dir/subdir/file");
+  test_mkdirs(std::string(td.path) + "/dir/subdir");
 
   // Relative paths.
   ASSERT_EQ(0, chdir(td.path)) << strerror(errno);
-  test_mkdirs(std::string("relative/subrel/file"));
+  test_mkdirs(std::string("relative/subrel"));
 }
 
 #if !defined(_WIN32)
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index e6037d7..360eaa7 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2065 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 209ff1c..a7a0713 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -57,7 +57,9 @@
 
 class LibraryNamespaces {
  public:
-  LibraryNamespaces() : initialized_(false) { }
+  LibraryNamespaces() : initialized_(false) {
+    PreloadPublicLibraries();
+  }
 
   android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader,
                                    bool is_shared,
@@ -103,15 +105,16 @@
   }
 
  private:
-  bool InitPublicNamespace(const char* library_path) {
-    // Make sure all the public libraries are loaded
+  void PreloadPublicLibraries() {
+    // android_init_namespaces() expects all the public libraries
+    // to be loaded so that they can be found by soname alone.
     std::vector<std::string> sonames = android::base::Split(kPublicNativeLibraries, ":");
     for (const auto& soname : sonames) {
-      if (dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr) {
-        return false;
-      }
+      dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE);
     }
+  }
 
+  bool InitPublicNamespace(const char* library_path) {
     // Some apps call dlopen from generated code unknown to linker in which
     // case linker uses anonymous namespace. See b/25844435 for details.
     initialized_ = android_init_namespaces(kPublicNativeLibraries, library_path);