OSDN Git Service

Merge remote-tracking branch 'x86/nougat-x86' into oreo-x86
[android-x86/device-generic-common.git] / nativebridge / src / libnb.cpp
1 /*
2  * Copyright (C) 2015-2017 The Android-x86 Open Source Project
3  *
4  * by Chih-Wei Huang <cwhuang@linux.org.tw>
5  *
6  * Licensed under the GNU General Public License Version 2 or later.
7  * You may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.gnu.org/licenses/gpl.html
11  *
12  */
13
14 #define LOG_TAG "libnb"
15
16 #include <dlfcn.h>
17 #include <cutils/log.h>
18 #include <cutils/properties.h>
19 #include "nativebridge/native_bridge.h"
20
21 #define DBG 0
22 #if DBG
23 #define LOGV ALOGD
24 #else
25 #define LOGV ALOGV
26 #endif
27
28 namespace android {
29
30 static void *native_handle = nullptr;
31
32 static bool is_native_bridge_enabled()
33 {
34     return property_get_bool("persist.sys.nativebridge", 0);
35 }
36
37 static NativeBridgeCallbacks *get_callbacks()
38 {
39     static NativeBridgeCallbacks *callbacks = nullptr;
40
41     if (!callbacks) {
42         const char *libnb = "/system/lib"
43 #ifdef __LP64__
44                 "64"
45 #endif
46                 "/libhoudini.so";
47         if (!native_handle) {
48             native_handle = dlopen(libnb, RTLD_LAZY);
49             if (!native_handle) {
50                 ALOGE("Unable to open %s", libnb);
51                 return nullptr;
52             }
53         }
54         callbacks = reinterpret_cast<NativeBridgeCallbacks *>(dlsym(native_handle, "NativeBridgeItf"));
55         ALOGI("Found %s version %u", libnb, callbacks ? callbacks->version : 0);
56     }
57     return callbacks;
58 }
59
60 // NativeBridgeCallbacks implementations
61 static bool native_bridge2_initialize(const NativeBridgeRuntimeCallbacks *art_cbs,
62                                       const char *app_code_cache_dir,
63                                       const char *isa)
64 {
65     LOGV("enter native_bridge2_initialize %s %s", app_code_cache_dir, isa);
66     if (is_native_bridge_enabled()) {
67         if (NativeBridgeCallbacks *cb = get_callbacks()) {
68             return cb->initialize(art_cbs, app_code_cache_dir, isa);
69         }
70         ALOGW("Native bridge is enabled but callbacks not found");
71     } else {
72         ALOGW("Native bridge is disabled");
73     }
74     return false;
75 }
76
77 static void *native_bridge2_loadLibrary(const char *libpath, int flag)
78 {
79     LOGV("enter native_bridge2_loadLibrary %s", libpath);
80     NativeBridgeCallbacks *cb = get_callbacks();
81     return cb ? cb->loadLibrary(libpath, flag) : nullptr;
82 }
83
84 static void *native_bridge2_getTrampoline(void *handle, const char *name,
85                                           const char* shorty, uint32_t len)
86 {
87     LOGV("enter native_bridge2_getTrampoline %s", name);
88     NativeBridgeCallbacks *cb = get_callbacks();
89     return cb ? cb->getTrampoline(handle, name, shorty, len) : nullptr;
90 }
91
92 static bool native_bridge2_isSupported(const char *libpath)
93 {
94     LOGV("enter native_bridge2_isSupported %s", libpath);
95     NativeBridgeCallbacks *cb = get_callbacks();
96     return cb ? cb->isSupported(libpath) : false;
97 }
98
99 static const struct NativeBridgeRuntimeValues *native_bridge2_getAppEnv(const char *abi)
100 {
101     LOGV("enter native_bridge2_getAppEnv %s", abi);
102     NativeBridgeCallbacks *cb = get_callbacks();
103     return cb ? cb->getAppEnv(abi) : nullptr;
104 }
105
106 static bool native_bridge2_isCompatibleWith(uint32_t version)
107 {
108     static uint32_t my_version = 0;
109     LOGV("enter native_bridge2_isCompatibleWith %u", version);
110     if (my_version == 0 && is_native_bridge_enabled()) {
111         if (NativeBridgeCallbacks *cb = get_callbacks()) {
112             my_version = cb->version;
113         }
114     }
115     // We have to claim a valid version before loading the real callbacks,
116     // otherwise native bridge will be disabled entirely
117     return version <= (my_version ? my_version : 3);
118 }
119
120 static NativeBridgeSignalHandlerFn native_bridge2_getSignalHandler(int signal)
121 {
122     LOGV("enter native_bridge2_getSignalHandler %d", signal);
123     NativeBridgeCallbacks *cb = get_callbacks();
124     return cb ? cb->getSignalHandler(signal) : nullptr;
125 }
126
127 static int native_bridge3_unloadLibrary(void *handle)
128 {
129     LOGV("enter native_bridge3_unloadLibrary %p", handle);
130     NativeBridgeCallbacks *cb = get_callbacks();
131     return cb ? cb->unloadLibrary(handle) : -1;
132 }
133
134 static const char *native_bridge3_getError()
135 {
136     LOGV("enter native_bridge3_getError");
137     NativeBridgeCallbacks *cb = get_callbacks();
138     return cb ? cb->getError() : "unknown";
139 }
140
141 static bool native_bridge3_isPathSupported(const char *path)
142 {
143     LOGV("enter native_bridge3_isPathSupported %s", path);
144     NativeBridgeCallbacks *cb = get_callbacks();
145     return cb && cb->isPathSupported(path);
146 }
147
148 static bool native_bridge3_initAnonymousNamespace(const char *public_ns_sonames,
149                                                   const char *anon_ns_library_path)
150 {
151     LOGV("enter native_bridge3_initAnonymousNamespace %s, %s", public_ns_sonames, anon_ns_library_path);
152     NativeBridgeCallbacks *cb = get_callbacks();
153     return cb && cb->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
154 }
155
156 static native_bridge_namespace_t *
157 native_bridge3_createNamespace(const char *name,
158                                const char *ld_library_path,
159                                const char *default_library_path,
160                                uint64_t type,
161                                const char *permitted_when_isolated_path,
162                                native_bridge_namespace_t *parent_ns)
163 {
164     LOGV("enter native_bridge3_createNamespace %s, %s, %s, %s", name, ld_library_path, default_library_path, permitted_when_isolated_path);
165     NativeBridgeCallbacks *cb = get_callbacks();
166     return cb ? cb->createNamespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent_ns) : nullptr;
167 }
168
169 static bool native_bridge3_linkNamespaces(native_bridge_namespace_t *from,
170                                           native_bridge_namespace_t *to,
171                                           const char *shared_libs_soname)
172 {
173     LOGV("enter native_bridge3_linkNamespaces %s", shared_libs_soname);
174     NativeBridgeCallbacks *cb = get_callbacks();
175     return cb && cb->linkNamespaces(from, to, shared_libs_soname);
176 }
177
178 static void *native_bridge3_loadLibraryExt(const char *libpath,
179                                            int flag,
180                                            native_bridge_namespace_t *ns)
181 {
182     LOGV("enter native_bridge3_loadLibraryExt %s, %d, %p", libpath, flag, ns);
183     NativeBridgeCallbacks *cb = get_callbacks();
184     void *result = cb ? cb->loadLibraryExt(libpath, flag, ns) : nullptr;
185 //  void *result = cb ? cb->loadLibrary(libpath, flag) : nullptr;
186     LOGV("native_bridge3_loadLibraryExt: %p", result);
187     return result;
188 }
189
190 static native_bridge_namespace_t *native_bridge4_getVendorNamespace()
191 {
192     LOGV("enter native_bridge4_getVendorNamespace");
193     NativeBridgeCallbacks *cb = get_callbacks();
194     return cb ? cb->getVendorNamespace() : nullptr;
195 }
196
197 static void __attribute__ ((destructor)) on_dlclose()
198 {
199     if (native_handle) {
200         dlclose(native_handle);
201         native_handle = nullptr;
202     }
203 }
204
205 extern "C" {
206
207 NativeBridgeCallbacks NativeBridgeItf = {
208     // v1
209     .version = 4,
210     .initialize = native_bridge2_initialize,
211     .loadLibrary = native_bridge2_loadLibrary,
212     .getTrampoline = native_bridge2_getTrampoline,
213     .isSupported = native_bridge2_isSupported,
214     .getAppEnv = native_bridge2_getAppEnv,
215     // v2
216     .isCompatibleWith = native_bridge2_isCompatibleWith,
217     .getSignalHandler = native_bridge2_getSignalHandler,
218     // v3
219     .unloadLibrary = native_bridge3_unloadLibrary,
220     .getError = native_bridge3_getError,
221     .isPathSupported = native_bridge3_isPathSupported,
222     .initAnonymousNamespace = native_bridge3_initAnonymousNamespace,
223     .createNamespace = native_bridge3_createNamespace,
224     .linkNamespaces = native_bridge3_linkNamespaces,
225     .loadLibraryExt = native_bridge3_loadLibraryExt,
226     // v4
227     .getVendorNamespace = native_bridge4_getVendorNamespace,
228 };
229
230 } // extern "C"
231 } // namespace android