Merge changes I975ba933,Ica9d211b am: a9ef4dc7a2
am: 9ece9401a4

Change-Id: I4aceabe7b0d39d0a2cf214577d6764d30fc95858
diff --git a/base/file.cpp b/base/file.cpp
index 32c2439..81b04d7 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -238,8 +238,11 @@
 #endif
 }
 
-std::string Basename(const std::string& path) {
+std::string GetExecutableDirectory() {
+  return Dirname(GetExecutablePath());
+}
 
+std::string Basename(const std::string& path) {
   // Copy path because basename may modify the string passed in.
   std::string result(path);
 
diff --git a/base/file_test.cpp b/base/file_test.cpp
index bbd5037..1021326 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -159,6 +159,14 @@
 #endif
 }
 
+TEST(file, GetExecutableDirectory) {
+  std::string path = android::base::GetExecutableDirectory();
+  ASSERT_NE("", path);
+  ASSERT_NE(android::base::GetExecutablePath(), path);
+  ASSERT_EQ('/', path[0]);
+  ASSERT_NE('/', path[path.size() - 1]);
+}
+
 TEST(file, GetExecutablePath) {
   ASSERT_NE("", android::base::GetExecutablePath());
 }
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index c7e094e..33d1ab3 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -51,6 +51,7 @@
 #endif
 
 std::string GetExecutablePath();
+std::string GetExecutableDirectory();
 
 // Like the regular basename and dirname, but thread-safe on all
 // platforms and capable of correctly handling exotic Windows paths.
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 70ada72..ea606a1 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -23,6 +23,7 @@
     srcs: [
         "BitSet_test.cpp",
         "LruCache_test.cpp",
+        "Singleton_test.cpp",
         "String8_test.cpp",
         "StrongPointer_test.cpp",
         "Unicode_test.cpp",
@@ -42,6 +43,8 @@
                 "liblog",
                 "libcutils",
                 "libutils",
+                "libbase",
+                "libdl",
             ],
         },
         linux: {
@@ -54,13 +57,35 @@
             static_libs: [
                 "libutils",
                 "liblog",
+                "libbase",
             ],
+            host_ldlibs: ["-ldl"],
         },
     },
 
+    required: [
+        "libutils_tests_singleton1",
+        "libutils_tests_singleton2",
+    ],
+
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
     ],
 }
+
+cc_test_library {
+    name: "libutils_tests_singleton1",
+    host_supported: true,
+    relative_install_path: "libutils_tests",
+    srcs: ["Singleton_test1.cpp"],
+}
+
+cc_test_library {
+    name: "libutils_tests_singleton2",
+    host_supported: true,
+    relative_install_path: "libutils_tests",
+    srcs: ["Singleton_test2.cpp"],
+    shared_libs: ["libutils_tests_singleton1"],
+}
diff --git a/libutils/tests/Singleton_test.cpp b/libutils/tests/Singleton_test.cpp
new file mode 100644
index 0000000..9acd3c3
--- /dev/null
+++ b/libutils/tests/Singleton_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Singleton_test"
+
+#include <dlfcn.h>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <utils/Singleton.h>
+
+#include <gtest/gtest.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+TEST(SingletonTest, bug35674422) {
+    std::string path = android::base::GetExecutableDirectory();
+    // libutils_tests_singleton1.so contains the ANDROID_SINGLETON_STATIC_INSTANCE
+    // definition of SingletonTestData, load it first.
+    std::string lib = android::base::StringPrintf("%s/libutils_tests_singleton1.so", path.c_str());
+    void* handle1 = dlopen(lib.c_str(), RTLD_NOW);
+    ASSERT_TRUE(handle1 != nullptr) << dlerror();
+
+    // libutils_tests_singleton2.so references SingletonTestData but should not
+    // have a definition
+    lib = android::base::StringPrintf("%s/libutils_tests_singleton2.so", path.c_str());
+    void* handle2 = dlopen(lib.c_str(), RTLD_NOW);
+    ASSERT_TRUE(handle2 != nullptr) << dlerror();
+
+    using has_fn_t = decltype(&singletonHasInstance);
+    using get_fn_t = decltype(&singletonGetInstanceContents);
+    using set_fn_t = decltype(&singletonSetInstanceContents);
+
+    has_fn_t has1 = reinterpret_cast<has_fn_t>(dlsym(handle1, "singletonHasInstance"));
+    ASSERT_TRUE(has1 != nullptr) << dlerror();
+    has_fn_t has2 = reinterpret_cast<has_fn_t>(dlsym(handle2, "singletonHasInstance"));
+    ASSERT_TRUE(has2 != nullptr) << dlerror();
+    get_fn_t get1 = reinterpret_cast<get_fn_t>(dlsym(handle1, "singletonGetInstanceContents"));
+    ASSERT_TRUE(get1 != nullptr) << dlerror();
+    get_fn_t get2 = reinterpret_cast<get_fn_t>(dlsym(handle2, "singletonGetInstanceContents"));
+    ASSERT_TRUE(get2 != nullptr) << dlerror();
+    set_fn_t set1 = reinterpret_cast<set_fn_t>(dlsym(handle2, "singletonSetInstanceContents"));
+    ASSERT_TRUE(set1 != nullptr) << dlerror();
+
+    EXPECT_FALSE(has1());
+    EXPECT_FALSE(has2());
+    set1(12345678U);
+    EXPECT_TRUE(has1());
+    EXPECT_TRUE(has2());
+    EXPECT_EQ(12345678U, get1());
+    EXPECT_EQ(12345678U, get2());
+}
+
+}
diff --git a/libutils/tests/Singleton_test.h b/libutils/tests/Singleton_test.h
new file mode 100644
index 0000000..c77d9ff
--- /dev/null
+++ b/libutils/tests/Singleton_test.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_TEST_H
+#define ANDROID_UTILS_SINGLETON_TEST_H
+
+#include <sys/cdefs.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+struct SingletonTestData : Singleton<SingletonTestData> {
+    unsigned int contents;
+};
+
+__BEGIN_DECLS
+
+unsigned int singletonGetInstanceContents();
+void singletonSetInstanceContents(unsigned int);
+bool singletonHasInstance();
+
+__END_DECLS
+
+}
+
+#endif // ANDROID_UTILS_SINGLETON_TEST_H
+
diff --git a/libutils/tests/Singleton_test1.cpp b/libutils/tests/Singleton_test1.cpp
new file mode 100644
index 0000000..4a91ec0
--- /dev/null
+++ b/libutils/tests/Singleton_test1.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Singleton.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+// Singleton<SingletonTestStruct> is referenced in Singleton_test1.cpp and
+// Singleton_test2.cpp, but only defined in Singleton_test1.cpp.
+ANDROID_SINGLETON_STATIC_INSTANCE(SingletonTestData);
+
+void singletonSetInstanceContents(unsigned int contents) {
+    SingletonTestData::getInstance().contents = contents;
+}
+
+unsigned int singletonGetInstanceContents() {
+    return SingletonTestData::getInstance().contents;
+}
+
+bool singletonHasInstance() {
+    return SingletonTestData::hasInstance();
+}
+
+}
diff --git a/libutils/tests/Singleton_test2.cpp b/libutils/tests/Singleton_test2.cpp
new file mode 100644
index 0000000..eb2a9df
--- /dev/null
+++ b/libutils/tests/Singleton_test2.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Singleton.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+// Singleton<SingletonTestStruct> is referenced in Singleton_test1.cpp and
+// Singleton_test2.cpp, but only defined in Singleton_test1.cpp.
+
+void singletonSetInstanceContents(unsigned int contents) {
+    SingletonTestData::getInstance().contents = contents;
+}
+
+unsigned int singletonGetInstanceContents() {
+    return SingletonTestData::getInstance().contents;
+}
+
+bool singletonHasInstance() {
+    return SingletonTestData::hasInstance();
+}
+
+}