Work around incorrect dt_needed entries

  This applies for apps targeting sdk<=22 and
  only for lp32 platforms.

Bug: http://b/21364029
Change-Id: I903e81c9ccda2a8beaba1d132d68c77d30a4cdb2
(cherry picked from commit d974e8804689058714dc4fe9adcb57ee9a6996a8)
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 8fafded..8705d9a 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -158,6 +158,8 @@
 }
 
 void android_set_application_target_sdk_version(uint32_t target) {
+  // lock to avoid modification in the middle of dlopen.
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
   set_application_target_sdk_version(target);
 }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f3ca761..e8bebff 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1215,11 +1215,27 @@
   return fd;
 }
 
+static const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
+#if !defined(__LP64__)
+  // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029
+  uint32_t target_sdk_version = get_application_target_sdk_version();
+  if (target_sdk_version != 0 && target_sdk_version <= 22) {
+    const char* bname = basename(dt_needed);
+    if (bname != dt_needed) {
+      DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed);
+    }
+
+    return bname;
+  }
+#endif
+  return dt_needed;
+}
+
 template<typename F>
 static void for_each_dt_needed(const soinfo* si, F action) {
   for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
     if (d->d_tag == DT_NEEDED) {
-      action(si->get_string(d->d_un.d_val));
+      action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
     }
   }
 }