Home | History | Annotate | Download | only in libnativeloader
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "nativeloader/native_loader.h"
     18 #include <nativehelper/ScopedUtfChars.h>
     19 
     20 #include <dlfcn.h>
     21 #ifdef __ANDROID__
     22 #define LOG_TAG "libnativeloader"
     23 #include "nativeloader/dlext_namespaces.h"
     24 #include "cutils/properties.h"
     25 #include "log/log.h"
     26 #endif
     27 #include "nativebridge/native_bridge.h"
     28 
     29 #include <algorithm>
     30 #include <vector>
     31 #include <string>
     32 #include <mutex>
     33 
     34 #include <android-base/file.h>
     35 #include <android-base/macros.h>
     36 #include <android-base/strings.h>
     37 
     38 #define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\
     39                                              "%s:%d: %s CHECK '" #predicate "' failed.",\
     40                                              __FILE__, __LINE__, __FUNCTION__)
     41 
     42 namespace android {
     43 
     44 #if defined(__ANDROID__)
     45 class NativeLoaderNamespace {
     46  public:
     47   NativeLoaderNamespace()
     48       : android_ns_(nullptr), native_bridge_ns_(nullptr) { }
     49 
     50   explicit NativeLoaderNamespace(android_namespace_t* ns)
     51       : android_ns_(ns), native_bridge_ns_(nullptr) { }
     52 
     53   explicit NativeLoaderNamespace(native_bridge_namespace_t* ns)
     54       : android_ns_(nullptr), native_bridge_ns_(ns) { }
     55 
     56   NativeLoaderNamespace(NativeLoaderNamespace&& that) = default;
     57   NativeLoaderNamespace(const NativeLoaderNamespace& that) = default;
     58 
     59   NativeLoaderNamespace& operator=(const NativeLoaderNamespace& that) = default;
     60 
     61   android_namespace_t* get_android_ns() const {
     62     CHECK(native_bridge_ns_ == nullptr);
     63     return android_ns_;
     64   }
     65 
     66   native_bridge_namespace_t* get_native_bridge_ns() const {
     67     CHECK(android_ns_ == nullptr);
     68     return native_bridge_ns_;
     69   }
     70 
     71   bool is_android_namespace() const {
     72     return native_bridge_ns_ == nullptr;
     73   }
     74 
     75  private:
     76   // Only one of them can be not null
     77   android_namespace_t* android_ns_;
     78   native_bridge_namespace_t* native_bridge_ns_;
     79 };
     80 
     81 static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot =
     82                                   "/etc/public.libraries.txt";
     83 static constexpr const char* kPublicNativeLibrariesVendorConfig =
     84                                   "/vendor/etc/public.libraries.txt";
     85 static constexpr const char* kLlndkNativeLibrariesSystemConfigPathFromRoot =
     86                                   "/etc/llndk.libraries.txt";
     87 static constexpr const char* kVndkspNativeLibrariesSystemConfigPathFromRoot =
     88                                   "/etc/vndksp.libraries.txt";
     89 
     90 
     91 // The device may be configured to have the vendor libraries loaded to a separate namespace.
     92 // For historical reasons this namespace was named sphal but effectively it is intended
     93 // to use to load vendor libraries to separate namespace with controlled interface between
     94 // vendor and system namespaces.
     95 static constexpr const char* kVendorNamespaceName = "sphal";
     96 
     97 static constexpr const char* kVndkNamespaceName = "vndk";
     98 
     99 static constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
    100 static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
    101 
    102 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling
    103 // System.load() with an absolute path which is outside of the classloader library search path.
    104 // This list includes all directories app is allowed to access this way.
    105 static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
    106 
    107 static bool is_debuggable() {
    108   char debuggable[PROP_VALUE_MAX];
    109   property_get("ro.debuggable", debuggable, "0");
    110   return std::string(debuggable) == "1";
    111 }
    112 
    113 class LibraryNamespaces {
    114  public:
    115   LibraryNamespaces() : initialized_(false) { }
    116 
    117   bool Create(JNIEnv* env,
    118               uint32_t target_sdk_version,
    119               jobject class_loader,
    120               bool is_shared,
    121               bool is_for_vendor,
    122               jstring java_library_path,
    123               jstring java_permitted_path,
    124               NativeLoaderNamespace* ns,
    125               std::string* error_msg) {
    126     std::string library_path; // empty string by default.
    127 
    128     if (java_library_path != nullptr) {
    129       ScopedUtfChars library_path_utf_chars(env, java_library_path);
    130       library_path = library_path_utf_chars.c_str();
    131     }
    132 
    133     // (http://b/27588281) This is a workaround for apps using custom
    134     // classloaders and calling System.load() with an absolute path which
    135     // is outside of the classloader library search path.
    136     //
    137     // This part effectively allows such a classloader to access anything
    138     // under /data and /mnt/expand
    139     std::string permitted_path = kWhitelistedDirectories;
    140 
    141     if (java_permitted_path != nullptr) {
    142       ScopedUtfChars path(env, java_permitted_path);
    143       if (path.c_str() != nullptr && path.size() > 0) {
    144         permitted_path = permitted_path + ":" + path.c_str();
    145       }
    146     }
    147 
    148     if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) {
    149       return false;
    150     }
    151 
    152     bool found = FindNamespaceByClassLoader(env, class_loader, nullptr);
    153 
    154     LOG_ALWAYS_FATAL_IF(found,
    155                         "There is already a namespace associated with this classloader");
    156 
    157     uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED;
    158     if (is_shared) {
    159       namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
    160     }
    161 
    162     if (target_sdk_version < 24) {
    163       namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
    164     }
    165 
    166     NativeLoaderNamespace parent_ns;
    167     bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns);
    168 
    169     bool is_native_bridge = false;
    170 
    171     if (found_parent_namespace) {
    172       is_native_bridge = !parent_ns.is_android_namespace();
    173     } else if (!library_path.empty()) {
    174       is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str());
    175     }
    176 
    177     std::string system_exposed_libraries = system_public_libraries_;
    178     const char* namespace_name = kClassloaderNamespaceName;
    179     android_namespace_t* vndk_ns = nullptr;
    180     if (is_for_vendor && !is_shared) {
    181       LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture");
    182 
    183       // For vendor apks, give access to the vendor lib even though
    184       // they are treated as unbundled; the libs and apks are still bundled
    185       // together in the vendor partition.
    186 #if defined(__LP64__)
    187       std::string vendor_lib_path = "/vendor/lib64";
    188 #else
    189       std::string vendor_lib_path = "/vendor/lib";
    190 #endif
    191       library_path = library_path + ":" + vendor_lib_path.c_str();
    192       permitted_path = permitted_path + ":" + vendor_lib_path.c_str();
    193 
    194       // Also give access to LLNDK libraries since they are available to vendors
    195       system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str();
    196 
    197       // Give access to VNDK-SP libraries from the 'vndk' namespace.
    198       vndk_ns = android_get_exported_namespace(kVndkNamespaceName);
    199       LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr,
    200                           "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName);
    201 
    202       // Different name is useful for debugging
    203       namespace_name = kVendorClassloaderNamespaceName;
    204       ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str());
    205     }
    206 
    207     NativeLoaderNamespace native_loader_ns;
    208     if (!is_native_bridge) {
    209       android_namespace_t* ns = android_create_namespace(namespace_name,
    210                                                          nullptr,
    211                                                          library_path.c_str(),
    212                                                          namespace_type,
    213                                                          permitted_path.c_str(),
    214                                                          parent_ns.get_android_ns());
    215       if (ns == nullptr) {
    216         *error_msg = dlerror();
    217         return false;
    218       }
    219 
    220       // Note that when vendor_ns is not configured this function will return nullptr
    221       // and it will result in linking vendor_public_libraries_ to the default namespace
    222       // which is expected behavior in this case.
    223       android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
    224 
    225       if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) {
    226         *error_msg = dlerror();
    227         return false;
    228       }
    229 
    230       if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) {
    231         // vendor apks are allowed to use VNDK-SP libraries.
    232         if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) {
    233           *error_msg = dlerror();
    234           return false;
    235         }
    236       }
    237 
    238       if (!vendor_public_libraries_.empty()) {
    239         if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
    240           *error_msg = dlerror();
    241           return false;
    242         }
    243       }
    244 
    245       native_loader_ns = NativeLoaderNamespace(ns);
    246     } else {
    247       native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name,
    248                                                                   nullptr,
    249                                                                   library_path.c_str(),
    250                                                                   namespace_type,
    251                                                                   permitted_path.c_str(),
    252                                                                   parent_ns.get_native_bridge_ns());
    253 
    254       if (ns == nullptr) {
    255         *error_msg = NativeBridgeGetError();
    256         return false;
    257       }
    258 
    259       native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
    260 
    261       if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) {
    262         *error_msg = NativeBridgeGetError();
    263         return false;
    264       }
    265 
    266       if (!vendor_public_libraries_.empty()) {
    267         if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
    268           *error_msg = NativeBridgeGetError();
    269           return false;
    270         }
    271       }
    272 
    273       native_loader_ns = NativeLoaderNamespace(ns);
    274     }
    275 
    276     namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns));
    277 
    278     *ns = native_loader_ns;
    279     return true;
    280   }
    281 
    282   bool FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader, NativeLoaderNamespace* ns) {
    283     auto it = std::find_if(namespaces_.begin(), namespaces_.end(),
    284                 [&](const std::pair<jweak, NativeLoaderNamespace>& value) {
    285                   return env->IsSameObject(value.first, class_loader);
    286                 });
    287     if (it != namespaces_.end()) {
    288       if (ns != nullptr) {
    289         *ns = it->second;
    290       }
    291 
    292       return true;
    293     }
    294 
    295     return false;
    296   }
    297 
    298   void Initialize() {
    299     // Once public namespace is initialized there is no
    300     // point in running this code - it will have no effect
    301     // on the current list of public libraries.
    302     if (initialized_) {
    303       return;
    304     }
    305 
    306     std::vector<std::string> sonames;
    307     const char* android_root_env = getenv("ANDROID_ROOT");
    308     std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";
    309     std::string public_native_libraries_system_config =
    310             root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot;
    311     std::string llndk_native_libraries_system_config =
    312             root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot;
    313     std::string vndksp_native_libraries_system_config =
    314             root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot;
    315 
    316     std::string error_msg;
    317     LOG_ALWAYS_FATAL_IF(!ReadConfig(public_native_libraries_system_config, &sonames, &error_msg),
    318                         "Error reading public native library list from \"%s\": %s",
    319                         public_native_libraries_system_config.c_str(), error_msg.c_str());
    320 
    321     // For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment
    322     // variable to add libraries to the list. This is intended for platform tests only.
    323     if (is_debuggable()) {
    324       const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
    325       if (additional_libs != nullptr && additional_libs[0] != '\0') {
    326         std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":");
    327         std::copy(additional_libs_vector.begin(),
    328                   additional_libs_vector.end(),
    329                   std::back_inserter(sonames));
    330       }
    331     }
    332 
    333     // android_init_namespaces() expects all the public libraries
    334     // to be loaded so that they can be found by soname alone.
    335     //
    336     // TODO(dimitry): this is a bit misleading since we do not know
    337     // if the vendor public library is going to be opened from /vendor/lib
    338     // we might as well end up loading them from /system/lib
    339     // For now we rely on CTS test to catch things like this but
    340     // it should probably be addressed in the future.
    341     for (const auto& soname : sonames) {
    342       LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
    343                           "Error preloading public library %s: %s",
    344                           soname.c_str(), dlerror());
    345     }
    346 
    347     system_public_libraries_ = base::Join(sonames, ':');
    348 
    349     sonames.clear();
    350     ReadConfig(kLlndkNativeLibrariesSystemConfigPathFromRoot, &sonames);
    351     system_llndk_libraries_ = base::Join(sonames, ':');
    352 
    353     sonames.clear();
    354     ReadConfig(kVndkspNativeLibrariesSystemConfigPathFromRoot, &sonames);
    355     system_vndksp_libraries_ = base::Join(sonames, ':');
    356 
    357     sonames.clear();
    358     // This file is optional, quietly ignore if the file does not exist.
    359     ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
    360 
    361     vendor_public_libraries_ = base::Join(sonames, ':');
    362   }
    363 
    364   void Reset() {
    365     namespaces_.clear();
    366   }
    367 
    368  private:
    369   bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
    370                   std::string* error_msg = nullptr) {
    371     // Read list of public native libraries from the config file.
    372     std::string file_content;
    373     if(!base::ReadFileToString(configFile, &file_content)) {
    374       if (error_msg) *error_msg = strerror(errno);
    375       return false;
    376     }
    377 
    378     std::vector<std::string> lines = base::Split(file_content, "\n");
    379 
    380     for (auto& line : lines) {
    381       auto trimmed_line = base::Trim(line);
    382       if (trimmed_line[0] == '#' || trimmed_line.empty()) {
    383         continue;
    384       }
    385       size_t space_pos = trimmed_line.rfind(' ');
    386       if (space_pos != std::string::npos) {
    387         std::string type = trimmed_line.substr(space_pos + 1);
    388         if (type != "32" && type != "64") {
    389           if (error_msg) *error_msg = "Malformed line: " + line;
    390           return false;
    391         }
    392 #if defined(__LP64__)
    393         // Skip 32 bit public library.
    394         if (type == "32") {
    395           continue;
    396         }
    397 #else
    398         // Skip 64 bit public library.
    399         if (type == "64") {
    400           continue;
    401         }
    402 #endif
    403         trimmed_line.resize(space_pos);
    404       }
    405 
    406       sonames->push_back(trimmed_line);
    407     }
    408 
    409     return true;
    410   }
    411 
    412   bool InitPublicNamespace(const char* library_path, std::string* error_msg) {
    413     // Ask native bride if this apps library path should be handled by it
    414     bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
    415 
    416     // (http://b/25844435) - Some apps call dlopen from generated code (mono jited
    417     // code is one example) unknown to linker in which  case linker uses anonymous
    418     // namespace. The second argument specifies the search path for the anonymous
    419     // namespace which is the library_path of the classloader.
    420     initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(),
    421                                                     is_native_bridge ? nullptr : library_path);
    422     if (!initialized_) {
    423       *error_msg = dlerror();
    424       return false;
    425     }
    426 
    427     // and now initialize native bridge namespaces if necessary.
    428     if (NativeBridgeInitialized()) {
    429       initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(),
    430                                                         is_native_bridge ? library_path : nullptr);
    431       if (!initialized_) {
    432         *error_msg = NativeBridgeGetError();
    433       }
    434     }
    435 
    436     return initialized_;
    437   }
    438 
    439   jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
    440     jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
    441     jmethodID get_parent = env->GetMethodID(class_loader_class,
    442                                             "getParent",
    443                                             "()Ljava/lang/ClassLoader;");
    444 
    445     return env->CallObjectMethod(class_loader, get_parent);
    446   }
    447 
    448   bool FindParentNamespaceByClassLoader(JNIEnv* env,
    449                                         jobject class_loader,
    450                                         NativeLoaderNamespace* ns) {
    451     jobject parent_class_loader = GetParentClassLoader(env, class_loader);
    452 
    453     while (parent_class_loader != nullptr) {
    454       if (FindNamespaceByClassLoader(env, parent_class_loader, ns)) {
    455         return true;
    456       }
    457 
    458       parent_class_loader = GetParentClassLoader(env, parent_class_loader);
    459     }
    460 
    461     return false;
    462   }
    463 
    464   bool initialized_;
    465   std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
    466   std::string system_public_libraries_;
    467   std::string vendor_public_libraries_;
    468   std::string system_llndk_libraries_;
    469   std::string system_vndksp_libraries_;
    470 
    471   DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
    472 };
    473 
    474 static std::mutex g_namespaces_mutex;
    475 static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
    476 #endif
    477 
    478 void InitializeNativeLoader() {
    479 #if defined(__ANDROID__)
    480   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
    481   g_namespaces->Initialize();
    482 #endif
    483 }
    484 
    485 void ResetNativeLoader() {
    486 #if defined(__ANDROID__)
    487   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
    488   g_namespaces->Reset();
    489 #endif
    490 }
    491 
    492 jstring CreateClassLoaderNamespace(JNIEnv* env,
    493                                    int32_t target_sdk_version,
    494                                    jobject class_loader,
    495                                    bool is_shared,
    496                                    bool is_for_vendor,
    497                                    jstring library_path,
    498                                    jstring permitted_path) {
    499 #if defined(__ANDROID__)
    500   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
    501 
    502   std::string error_msg;
    503   NativeLoaderNamespace ns;
    504   bool success = g_namespaces->Create(env,
    505                                       target_sdk_version,
    506                                       class_loader,
    507                                       is_shared,
    508                                       is_for_vendor,
    509                                       library_path,
    510                                       permitted_path,
    511                                       &ns,
    512                                       &error_msg);
    513   if (!success) {
    514     return env->NewStringUTF(error_msg.c_str());
    515   }
    516 #else
    517   UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor,
    518          library_path, permitted_path);
    519 #endif
    520   return nullptr;
    521 }
    522 
    523 void* OpenNativeLibrary(JNIEnv* env,
    524                         int32_t target_sdk_version,
    525                         const char* path,
    526                         jobject class_loader,
    527                         jstring library_path,
    528                         bool* needs_native_bridge,
    529                         std::string* error_msg) {
    530 #if defined(__ANDROID__)
    531   UNUSED(target_sdk_version);
    532   if (class_loader == nullptr) {
    533     *needs_native_bridge = false;
    534     return dlopen(path, RTLD_NOW);
    535   }
    536 
    537   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
    538   NativeLoaderNamespace ns;
    539 
    540   if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
    541     // This is the case where the classloader was not created by ApplicationLoaders
    542     // In this case we create an isolated not-shared namespace for it.
    543     if (!g_namespaces->Create(env,
    544                               target_sdk_version,
    545                               class_loader,
    546                               false /* is_shared */,
    547                               false /* is_for_vendor */,
    548                               library_path,
    549                               nullptr,
    550                               &ns,
    551                               error_msg)) {
    552       return nullptr;
    553     }
    554   }
    555 
    556   if (ns.is_android_namespace()) {
    557     android_dlextinfo extinfo;
    558     extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
    559     extinfo.library_namespace = ns.get_android_ns();
    560 
    561     void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
    562     if (handle == nullptr) {
    563       *error_msg = dlerror();
    564     }
    565     *needs_native_bridge = false;
    566     return handle;
    567   } else {
    568     void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns.get_native_bridge_ns());
    569     if (handle == nullptr) {
    570       *error_msg = NativeBridgeGetError();
    571     }
    572     *needs_native_bridge = true;
    573     return handle;
    574   }
    575 #else
    576   UNUSED(env, target_sdk_version, class_loader, library_path);
    577   *needs_native_bridge = false;
    578   void* handle = dlopen(path, RTLD_NOW);
    579   if (handle == nullptr) {
    580     if (NativeBridgeIsSupported(path)) {
    581       *needs_native_bridge = true;
    582       handle = NativeBridgeLoadLibrary(path, RTLD_NOW);
    583       if (handle == nullptr) {
    584         *error_msg = NativeBridgeGetError();
    585       }
    586     } else {
    587       *needs_native_bridge = false;
    588       *error_msg = dlerror();
    589     }
    590   }
    591   return handle;
    592 #endif
    593 }
    594 
    595 bool CloseNativeLibrary(void* handle, const bool needs_native_bridge) {
    596     return needs_native_bridge ? NativeBridgeUnloadLibrary(handle) :
    597                                  dlclose(handle);
    598 }
    599 
    600 #if defined(__ANDROID__)
    601 // native_bridge_namespaces are not supported for callers of this function.
    602 // This function will return nullptr in the case when application is running
    603 // on native bridge.
    604 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
    605   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
    606   NativeLoaderNamespace ns;
    607   if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
    608     return ns.is_android_namespace() ? ns.get_android_ns() : nullptr;
    609   }
    610 
    611   return nullptr;
    612 }
    613 #endif
    614 
    615 }; //  android namespace
    616