diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h
--- a/compiler-rt/lib/lsan/lsan_common.h
+++ b/compiler-rt/lib/lsan/lsan_common.h
@@ -29,16 +29,13 @@
 // To enable LeakSanitizer on a new architecture, one needs to implement the
 // internal_clone function as well as (probably) adjust the TLS machinery for
 // the new architecture inside the sanitizer library.
-#if (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) &&          \
-    (SANITIZER_WORDSIZE == 64) &&                                        \
+#if (SANITIZER_LINUX || SANITIZER_MAC) && (SANITIZER_WORDSIZE == 64) &&  \
     (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \
      defined(__powerpc64__) || defined(__s390x__))
 #define CAN_SANITIZE_LEAKS 1
-#elif defined(__i386__) && \
-    (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC)
+#elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_MAC)
 #define CAN_SANITIZE_LEAKS 1
-#elif defined(__arm__) && \
-    SANITIZER_LINUX && !SANITIZER_ANDROID
+#elif defined(__arm__) && SANITIZER_LINUX
 #define CAN_SANITIZE_LEAKS 1
 #elif SANITIZER_NETBSD || SANITIZER_FUCHSIA
 #define CAN_SANITIZE_LEAKS 1
diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -28,6 +28,19 @@
 extern "C" const char *__lsan_current_stage = "unknown";
 
 #if CAN_SANITIZE_LEAKS
+
+#if SANITIZER_ANDROID
+#include <android/api-level.h>
+
+// Thread properties API was introduced in 31.
+#if __ANDROID_API__ >= 31
+#include <sys/thread_properties.h>
+#define HAS_ANDROILD_THREAD_PROPERTIES_API 1
+#endif
+#else
+#define HAS_ANDROILD_THREAD_PROPERTIES_API 0
+#endif
+
 namespace __lsan {
 
 // This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
@@ -299,6 +312,17 @@
                                  kReachable);
         }
       }
+#if HAS_ANDROILD_THREAD_PROPERTIES_API
+      // Bionic provides a way to iterate through dynamic-DTLs chunks.
+      auto dtls_visitor = [&](void* dtls_begin,
+                              void* dtls_end,
+                              size_t /*dso_id unused*/,
+                              void* /*arg unused*/))->void {
+        ScanRangeForPointers(dtls_begin, dtls_end, frontier, "DTLS",
+                             kReachable);
+      };
+      __libc_iterate_dynamic_tls(os_id, dtls_visitor, nullptr);
+#else
       if (dtls && !DTLSInDestruction(dtls)) {
         for (uptr j = 0; j < dtls->dtv_size; ++j) {
           uptr dtls_beg = dtls->dtv[j].beg;
@@ -314,6 +338,7 @@
         // this and continue.
         LOG_THREADS("Thread %d has DTLS under destruction.\n", os_id);
       }
+#endif
     }
   }
 }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -64,6 +64,7 @@
 
 #if SANITIZER_ANDROID
 #include <android/api-level.h>
+#include <assert.h>
 #if !defined(CPU_COUNT) && !defined(__aarch64__)
 #include <dirent.h>
 #include <fcntl.h>
@@ -74,7 +75,12 @@
   char           d_name[];
 };
 #endif
+
+// Thread properties API was introduced in 31.
+#if __ANDROID_API__ >= 31
+#include <sys/thread_properties.h>
 #endif
+#endif  // SANITIZER_ANDROID
 
 #if !SANITIZER_ANDROID
 #include <elf.h>
@@ -86,6 +92,23 @@
 SANITIZER_WEAK_ATTRIBUTE int
 real_sigaction(int signum, const void *act, void *oldact);
 
+#if SANITIZER_ANDROID
+
+#if __ANDROID_API__ < 31
+SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **, void **);
+#endif
+
+static bool has_thread_properties_api() {
+  const static int has_impl = &__libc_get_static_tls_bounds != 0;
+#if __ANDROID_API__ >= 31
+  // It really should be there!
+  assert(has_impl &&
+         "No implementation found for __libc_get_static_tls_bounds");
+#endif
+  return has_impl;
+}
+#endif  // SANITIZER_ANDROID
+
 int internal_sigaction(int signum, const void *act, void *oldact) {
 #if !SANITIZER_GO
   if (&real_sigaction)
@@ -427,7 +450,20 @@
 
 #if !SANITIZER_GO
 static void GetTls(uptr *addr, uptr *size) {
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if SANITIZER_ANDROID
+  // Bionic provides an API for querying the current-thread's static TLS.
+  if (has_thread_properties_api()) {
+    uptr start_addr;
+    uptr end_addr;
+    __libc_get_static_tls_bounds(reinterpret_cast<void **>(&start_addr),
+                                 reinterpret_cast<void **>(&end_addr));
+    *addr = start_addr;
+    *size = end_addr - start_addr + 1;
+  } else {
+    *addr = 0;
+    *size = 0;
+  }
+#elif SANITIZER_LINUX && !SANITIZER_ANDROID
 # if defined(__x86_64__) || defined(__i386__) || defined(__s390__)
   *addr = ThreadSelf();
   *size = GetTlsSize();
@@ -471,9 +507,6 @@
 #elif SANITIZER_OPENBSD
   *addr = 0;
   *size = 0;
-#elif SANITIZER_ANDROID
-  *addr = 0;
-  *size = 0;
 #elif SANITIZER_SOLARIS
   // FIXME
   *addr = 0;