14914fcd91bcd75400c0e023974158912f077464cCalin Juravle/* 24914fcd91bcd75400c0e023974158912f077464cCalin Juravle * Copyright (C) 2014 The Android Open Source Project 34914fcd91bcd75400c0e023974158912f077464cCalin Juravle * 44914fcd91bcd75400c0e023974158912f077464cCalin Juravle * Licensed under the Apache License, Version 2.0 (the "License"); 54914fcd91bcd75400c0e023974158912f077464cCalin Juravle * you may not use this file except in compliance with the License. 64914fcd91bcd75400c0e023974158912f077464cCalin Juravle * You may obtain a copy of the License at 74914fcd91bcd75400c0e023974158912f077464cCalin Juravle * 84914fcd91bcd75400c0e023974158912f077464cCalin Juravle * http://www.apache.org/licenses/LICENSE-2.0 94914fcd91bcd75400c0e023974158912f077464cCalin Juravle * 104914fcd91bcd75400c0e023974158912f077464cCalin Juravle * Unless required by applicable law or agreed to in writing, software 114914fcd91bcd75400c0e023974158912f077464cCalin Juravle * distributed under the License is distributed on an "AS IS" BASIS, 124914fcd91bcd75400c0e023974158912f077464cCalin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134914fcd91bcd75400c0e023974158912f077464cCalin Juravle * See the License for the specific language governing permissions and 144914fcd91bcd75400c0e023974158912f077464cCalin Juravle * limitations under the License. 154914fcd91bcd75400c0e023974158912f077464cCalin Juravle */ 164914fcd91bcd75400c0e023974158912f077464cCalin Juravle 174914fcd91bcd75400c0e023974158912f077464cCalin Juravle#include "nativebridge/native_bridge.h" 184914fcd91bcd75400c0e023974158912f077464cCalin Juravle 19b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#include <cstring> 20cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe#include <cutils/log.h> 214914fcd91bcd75400c0e023974158912f077464cCalin Juravle#include <dlfcn.h> 22b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#include <errno.h> 23b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#include <fcntl.h> 244914fcd91bcd75400c0e023974158912f077464cCalin Juravle#include <stdio.h> 25b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#include <sys/mount.h> 26b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#include <sys/stat.h> 274914fcd91bcd75400c0e023974158912f077464cCalin Juravle 284914fcd91bcd75400c0e023974158912f077464cCalin Juravle 294914fcd91bcd75400c0e023974158912f077464cCalin Juravlenamespace android { 304914fcd91bcd75400c0e023974158912f077464cCalin Juravle 31b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu// Environment values required by the apps running with native bridge. 32b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustruct NativeBridgeRuntimeValues { 33b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu const char* os_arch; 34b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu const char* cpu_abi; 35b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu const char* cpu_abi2; 36b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu const char* *supported_abis; 37b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu int32_t abi_count; 38b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu}; 39b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 404914fcd91bcd75400c0e023974158912f077464cCalin Juravle// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks. 414914fcd91bcd75400c0e023974158912f077464cCalin Juravlestatic constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf"; 424914fcd91bcd75400c0e023974158912f077464cCalin Juravle 4341df668c7be461f461b3d70951dee7634ded868fAndreas Gampeenum class NativeBridgeState { 4441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe kNotSetup, // Initial state. 4541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe kOpened, // After successful dlopen. 461402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle kPreInitialized, // After successful pre-initialization. 4741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe kInitialized, // After successful initialization. 4841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe kClosed // Closed or errors. 4941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe}; 5041df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 511402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kNotSetupString = "kNotSetup"; 521402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kOpenedString = "kOpened"; 531402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kPreInitializedString = "kPreInitialized"; 541402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kInitializedString = "kInitialized"; 551402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kClosedString = "kClosed"; 5641df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 5741df668c7be461f461b3d70951dee7634ded868fAndreas Gampestatic const char* GetNativeBridgeStateString(NativeBridgeState state) { 5841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe switch (state) { 5941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kNotSetup: 6041df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return kNotSetupString; 6141df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 6241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kOpened: 6341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return kOpenedString; 6441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 651402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle case NativeBridgeState::kPreInitialized: 661402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return kPreInitializedString; 671402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 6841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kInitialized: 6941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return kInitializedString; 7041df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 7141df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kClosed: 7241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return kClosedString; 7341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe } 7441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe} 7541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 7641df668c7be461f461b3d70951dee7634ded868fAndreas Gampe// Current state of the native bridge. 7741df668c7be461f461b3d70951dee7634ded868fAndreas Gampestatic NativeBridgeState state = NativeBridgeState::kNotSetup; 784914fcd91bcd75400c0e023974158912f077464cCalin Juravle 79cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// Whether we had an error at some point. 80cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampestatic bool had_error = false; 814914fcd91bcd75400c0e023974158912f077464cCalin Juravle 8241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe// Handle of the loaded library. 8341df668c7be461f461b3d70951dee7634ded868fAndreas Gampestatic void* native_bridge_handle = nullptr; 8441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized 8541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe// later. 864914fcd91bcd75400c0e023974158912f077464cCalin Juravlestatic NativeBridgeCallbacks* callbacks = nullptr; 8741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe// Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge. 884914fcd91bcd75400c0e023974158912f077464cCalin Juravlestatic const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr; 894914fcd91bcd75400c0e023974158912f077464cCalin Juravle 901402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle// The app's code cache directory. 911402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic char* app_code_cache_dir = nullptr; 921402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 931402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle// Code cache directory (relative to the application private directory) 941402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle// Ideally we'd like to call into framework to retrieve this name. However that's considered an 951402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle// implementation detail and will require either hacks or consistent refactorings. We compromise 961402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle// and hard code the directory name again here. 971402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic constexpr const char* kCodeCacheDir = "code_cache"; 98b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 99b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic constexpr uint32_t kNativeBridgeCallbackVersion = 1; 100b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 101cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// Characters allowed in a native bridge filename. The first character must 102cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-]. 103cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampestatic bool CharacterAllowed(char c, bool first) { 104cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe if (first) { 105cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 106cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } else { 107cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || 108cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe (c == '.') || (c == '_') || (c == '-'); 109cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 110cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe} 111cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 112cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// We only allow simple names for the library. It is supposed to be a file in 113cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// /system/lib or /vendor/lib. Only allow a small range of characters, that is 114cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe// names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z]. 115cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampebool NativeBridgeNameAcceptable(const char* nb_library_filename) { 116cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe const char* ptr = nb_library_filename; 117cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe if (*ptr == 0) { 118cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // Emptry string. Allowed, means no native bridge. 119cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return true; 120cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } else { 121cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // First character must be [a-zA-Z]. 122cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe if (!CharacterAllowed(*ptr, true)) { 123cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // Found an invalid fist character, don't accept. 124cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe ALOGE("Native bridge library %s has been rejected for first character %c", nb_library_filename, *ptr); 125cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return false; 126cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } else { 127cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // For the rest, be more liberal. 128cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe ptr++; 129cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe while (*ptr != 0) { 130cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe if (!CharacterAllowed(*ptr, false)) { 131cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // Found an invalid character, don't accept. 132cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr); 133cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return false; 134cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 135cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe ptr++; 136cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 137cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 138cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return true; 139cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 140cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe} 141cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 142b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic bool VersionCheck(NativeBridgeCallbacks* cb) { 143b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return cb != nullptr && cb->version == kNativeBridgeCallbackVersion; 144b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu} 145b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 1461402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlestatic void CloseNativeBridge(bool with_error) { 1471402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle state = NativeBridgeState::kClosed; 1481402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle had_error |= with_error; 1491402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle delete[] app_code_cache_dir; 1501402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle app_code_cache_dir = nullptr; 1511402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle} 1521402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 15341df668c7be461f461b3d70951dee7634ded868fAndreas Gampebool LoadNativeBridge(const char* nb_library_filename, 15441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe const NativeBridgeRuntimeCallbacks* runtime_cbs) { 15541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not 15641df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // multi-threaded, so we do not need locking here. 1574914fcd91bcd75400c0e023974158912f077464cCalin Juravle 15841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (state != NativeBridgeState::kNotSetup) { 159cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // Setup has been called before. Ignore this call. 160b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm. 161b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.", 162b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu GetNativeBridgeStateString(state)); 163b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 164cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe // Note: counts as an error, even though the bridge may be functional. 165cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe had_error = true; 16641df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return false; 167cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 168cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 16941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (nb_library_filename == nullptr || *nb_library_filename == 0) { 1701402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(false); 1711402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return false; 172cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } else { 17341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (!NativeBridgeNameAcceptable(nb_library_filename)) { 1741402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 17541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe } else { 17625bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe // Try to open the library. 17725bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe void* handle = dlopen(nb_library_filename, RTLD_LAZY); 17825bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe if (handle != nullptr) { 17925bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, 18025bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe kNativeBridgeInterfaceSymbol)); 18125bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe if (callbacks != nullptr) { 182b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (VersionCheck(callbacks)) { 183b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Store the handle for later. 184b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu native_bridge_handle = handle; 185b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } else { 186b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu callbacks = nullptr; 187b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu dlclose(handle); 188b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Unsupported native bridge interface."); 189b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 19025bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe } else { 19125bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe dlclose(handle); 19225bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe } 19325bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe } 19425bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe 19525bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe // Two failure conditions: could not find library (dlopen failed), or could not find native 19625bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe // bridge interface (dlsym failed). Both are an error and close the native bridge. 19725bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe if (callbacks == nullptr) { 1981402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 19925bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe } else { 20025bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe runtime_callbacks = runtime_cbs; 20125bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe state = NativeBridgeState::kOpened; 20225bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe } 203cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 20441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return state == NativeBridgeState::kOpened; 2054914fcd91bcd75400c0e023974158912f077464cCalin Juravle } 2064914fcd91bcd75400c0e023974158912f077464cCalin Juravle} 2074914fcd91bcd75400c0e023974158912f077464cCalin Juravle 208b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#if defined(__arm__) 209b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "arm"; 210b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#elif defined(__aarch64__) 211b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "arm64"; 212b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#elif defined(__mips__) 213b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "mips"; 214b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#elif defined(__i386__) 215b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "x86"; 216b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#elif defined(__x86_64__) 217b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "x86_64"; 218b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#else 219b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic const char* kRuntimeISA = "unknown"; 220b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#endif 221b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 222b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 223b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgubool NeedsNativeBridge(const char* instruction_set) { 224b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (instruction_set == nullptr) { 225b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGE("Null instruction set in NeedsNativeBridge."); 226b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return false; 227b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 228b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return strncmp(instruction_set, kRuntimeISA, strlen(kRuntimeISA) + 1) != 0; 229b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu} 230b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 231b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#ifdef __APPLE__ 232b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgutemplate<typename T> void UNUSED(const T&) {} 233b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#endif 234b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 2351402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravlebool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) { 2361402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (state != NativeBridgeState::kOpened) { 2371402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle ALOGE("Invalid state: native bridge is expected to be opened."); 2381402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 2391402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return false; 2401402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } 2411402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 242b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (app_data_dir_in == nullptr) { 2431402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle ALOGE("Application private directory cannot be null."); 2441402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 2451402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return false; 246b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 247b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 2481402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // Create the path to the application code cache directory. 2491402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // The memory will be release after Initialization or when the native bridge is closed. 2501402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/' 2511402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle app_code_cache_dir = new char[len]; 2521402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir); 2531402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 2541402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo. 2551402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // Failure is not fatal and will keep the native bridge in kPreInitialized. 2561402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle state = NativeBridgeState::kPreInitialized; 257b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 258b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#ifndef __APPLE__ 259b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (instruction_set == nullptr) { 2601402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return true; 261b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 262b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu size_t isa_len = strlen(instruction_set); 263b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (isa_len > 10) { 264b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for 265b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // x86_64 [including the trailing \0]). This is so we don't have to change here if there will 266b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // be another instruction set in the future. 267b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.", 268b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu instruction_set); 2691402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return true; 270b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 271b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 2721402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // If the file does not exist, the mount command will fail, 2731402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // so we save the extra file existence check. 274b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu char cpuinfo_path[1024]; 275b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 276b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#ifdef HAVE_ANDROID_OS 277b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib" 278b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#ifdef __LP64__ 279b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu "64" 280b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#endif // __LP64__ 281b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu "/%s/cpuinfo", instruction_set); 282b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#else // !HAVE_ANDROID_OS 283b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // To be able to test on the host, we hardwire a relative path. 284b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo"); 285b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#endif 286b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 287b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Bind-mount. 288b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source. 289b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu "/proc/cpuinfo", // Target. 290b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu nullptr, // FS type. 291b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu MS_BIND, // Mount flags: bind mount. 292b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu nullptr)) == -1) { // "Data." 293b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno)); 294b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 2951402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle#else // __APPLE__ 296b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu UNUSED(instruction_set); 297b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible."); 298b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu#endif 2991402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 3001402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return true; 301b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu} 302b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 303b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) { 304b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (value != nullptr) { 305b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;"); 306b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (field_id == nullptr) { 307b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 308b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Could not find %s field.", field); 309b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return; 310b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 311b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 312b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu jstring str = env->NewStringUTF(value); 313b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (str == nullptr) { 314b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 315b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Could not create string %s.", value); 316b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return; 317b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 318b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 319b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->SetStaticObjectField(build_class, field_id, str); 320b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 321b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu} 322b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 323b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu// Set up the environment for the bridged app. 324b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgustatic void SetupEnvironment(NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) { 325b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Need a JNIEnv* to do anything. 326b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (env == nullptr) { 327b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("No JNIEnv* to set up app environment."); 328b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return; 329b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 330b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 331b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Query the bridge for environment values. 332b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa); 333b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (env_values == nullptr) { 334b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return; 335b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 336b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 337b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Keep the JNIEnv clean. 338b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu jint success = env->PushLocalFrame(16); // That should be small and large enough. 339b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (success < 0) { 340b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Out of memory, really borked. 341b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Out of memory while setting up app environment."); 342b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 343b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu return; 344b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 345b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 346b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge. 347b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr || 348b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env_values->abi_count >= 0) { 349b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu jclass bclass_id = env->FindClass("android/os/Build"); 350b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (bclass_id != nullptr) { 351b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi); 352b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2); 353b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } else { 354b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // For example in a host test environment. 355b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 356b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Could not find Build class."); 357b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 358b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 359b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 360b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (env_values->os_arch != nullptr) { 361b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu jclass sclass_id = env->FindClass("java/lang/System"); 362b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (sclass_id != nullptr) { 36300851a53bebe16dd2a0460245505461f40a7a307Calin Juravle jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "initUnchangeableSystemProperty", 36400851a53bebe16dd2a0460245505461f40a7a307Calin Juravle "(Ljava/lang/String;Ljava/lang/String;)V"); 365b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu if (set_prop_id != nullptr) { 36600851a53bebe16dd2a0460245505461f40a7a307Calin Juravle // Init os.arch to the value reqired by the apps running with native bridge. 36700851a53bebe16dd2a0460245505461f40a7a307Calin Juravle env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"), 368b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->NewStringUTF(env_values->os_arch)); 369b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } else { 370b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 37100851a53bebe16dd2a0460245505461f40a7a307Calin Juravle ALOGW("Could not find initUnchangeableSystemProperty method."); 372b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 373b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } else { 374b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->ExceptionClear(); 375b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu ALOGW("Could not find System class."); 376b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 377b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu } 378b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 379b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu // Make it pristine again. 380b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu env->PopLocalFrame(nullptr); 381b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu} 382b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgu 383b3facbfdecf46eb7c063b99529ab8c18a08a6b42jgubool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { 38441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that 38541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // point we are not multi-threaded, so we do not need locking here. 3864914fcd91bcd75400c0e023974158912f077464cCalin Juravle 3871402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (state == NativeBridgeState::kPreInitialized) { 3881402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // Check for code cache: if it doesn't exist try to create it. 3891402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle struct stat st; 3901402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (stat(app_code_cache_dir, &st) == -1) { 3911402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (errno == ENOENT) { 3921402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) { 3931402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle ALOGE("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 3941402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 3951402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } 3961402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } else { 3971402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle ALOGE("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 3981402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 3991402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } 4001402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } else if (!S_ISDIR(st.st_mode)) { 4011402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle ALOGE("Code cache is not a directory %s.", app_code_cache_dir); 4021402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 4031402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } 4041402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle 4051402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // If we're still PreInitialized (dind't fail the code cache checks) try to initialize. 4061402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (state == NativeBridgeState::kPreInitialized) { 4071402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) { 4081402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle SetupEnvironment(callbacks, env, instruction_set); 4091402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle state = NativeBridgeState::kInitialized; 4101402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // We no longer need the code cache path, release the memory. 4111402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle delete[] app_code_cache_dir; 4121402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle app_code_cache_dir = nullptr; 4131402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } else { 4141402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle // Unload the library. 4151402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle dlclose(native_bridge_handle); 4161402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 4171402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle } 41841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe } 41941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe } else { 4201402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 421cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe } 422cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 42341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return state == NativeBridgeState::kInitialized; 42441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe} 4254914fcd91bcd75400c0e023974158912f077464cCalin Juravle 42641df668c7be461f461b3d70951dee7634ded868fAndreas Gampevoid UnloadNativeBridge() { 42741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that 42841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // point we are not multi-threaded, so we do not need locking here. 4294914fcd91bcd75400c0e023974158912f077464cCalin Juravle 43041df668c7be461f461b3d70951dee7634ded868fAndreas Gampe switch(state) { 43125bacb3ab71ee7e8289c76d0aa0c6473e47340e3Andreas Gampe case NativeBridgeState::kOpened: 4321402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle case NativeBridgeState::kPreInitialized: 43341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kInitialized: 43441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // Unload. 43541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe dlclose(native_bridge_handle); 4361402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(false); 43741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe break; 43841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 43941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kNotSetup: 44041df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // Not even set up. Error. 4411402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle CloseNativeBridge(true); 44241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe break; 4434914fcd91bcd75400c0e023974158912f077464cCalin Juravle 44441df668c7be461f461b3d70951dee7634ded868fAndreas Gampe case NativeBridgeState::kClosed: 44541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // Ignore. 44641df668c7be461f461b3d70951dee7634ded868fAndreas Gampe break; 44741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe } 4484914fcd91bcd75400c0e023974158912f077464cCalin Juravle} 4494914fcd91bcd75400c0e023974158912f077464cCalin Juravle 450cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampebool NativeBridgeError() { 451cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe return had_error; 452cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe} 453cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 454cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampebool NativeBridgeAvailable() { 4551402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle return state == NativeBridgeState::kOpened 4561402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle || state == NativeBridgeState::kPreInitialized 4571402fbb13523fed9d96217e801df5678e3c01a6bCalin Juravle || state == NativeBridgeState::kInitialized; 45841df668c7be461f461b3d70951dee7634ded868fAndreas Gampe} 45941df668c7be461f461b3d70951dee7634ded868fAndreas Gampe 46041df668c7be461f461b3d70951dee7634ded868fAndreas Gampebool NativeBridgeInitialized() { 46141df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after 46241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe // Runtime::DidForkFromZygote. In that case we do not need a lock. 46341df668c7be461f461b3d70951dee7634ded868fAndreas Gampe return state == NativeBridgeState::kInitialized; 464cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe} 465cd2ef4c1af69727231b84ebc82864c170ff0e8adAndreas Gampe 4664914fcd91bcd75400c0e023974158912f077464cCalin Juravlevoid* NativeBridgeLoadLibrary(const char* libpath, int flag) { 46741df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (NativeBridgeInitialized()) { 4684914fcd91bcd75400c0e023974158912f077464cCalin Juravle return callbacks->loadLibrary(libpath, flag); 4694914fcd91bcd75400c0e023974158912f077464cCalin Juravle } 4704914fcd91bcd75400c0e023974158912f077464cCalin Juravle return nullptr; 4714914fcd91bcd75400c0e023974158912f077464cCalin Juravle} 4724914fcd91bcd75400c0e023974158912f077464cCalin Juravle 4734914fcd91bcd75400c0e023974158912f077464cCalin Juravlevoid* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, 4744914fcd91bcd75400c0e023974158912f077464cCalin Juravle uint32_t len) { 47541df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (NativeBridgeInitialized()) { 4764914fcd91bcd75400c0e023974158912f077464cCalin Juravle return callbacks->getTrampoline(handle, name, shorty, len); 4774914fcd91bcd75400c0e023974158912f077464cCalin Juravle } 4784914fcd91bcd75400c0e023974158912f077464cCalin Juravle return nullptr; 4794914fcd91bcd75400c0e023974158912f077464cCalin Juravle} 4804914fcd91bcd75400c0e023974158912f077464cCalin Juravle 4814914fcd91bcd75400c0e023974158912f077464cCalin Juravlebool NativeBridgeIsSupported(const char* libpath) { 48241df668c7be461f461b3d70951dee7634ded868fAndreas Gampe if (NativeBridgeInitialized()) { 4834914fcd91bcd75400c0e023974158912f077464cCalin Juravle return callbacks->isSupported(libpath); 4844914fcd91bcd75400c0e023974158912f077464cCalin Juravle } 4854914fcd91bcd75400c0e023974158912f077464cCalin Juravle return false; 4864914fcd91bcd75400c0e023974158912f077464cCalin Juravle} 4874914fcd91bcd75400c0e023974158912f077464cCalin Juravle 4884914fcd91bcd75400c0e023974158912f077464cCalin Juravle}; // namespace android 489