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