1 /* 2 * Copyright (C) 2014 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 "native_bridge_art_interface.h" 18 19 #include "nativebridge/native_bridge.h" 20 21 #include "base/logging.h" 22 #include "mirror/art_method-inl.h" 23 #include "mirror/class-inl.h" 24 #include "scoped_thread_state_change.h" 25 26 namespace art { 27 28 const char* GetMethodShorty(JNIEnv* env, jmethodID mid) { 29 ScopedObjectAccess soa(env); 30 StackHandleScope<1> scope(soa.Self()); 31 mirror::ArtMethod* m = soa.DecodeMethod(mid); 32 MethodHelper mh(scope.NewHandle(m)); 33 return mh.GetShorty(); 34 } 35 36 uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) { 37 if (clazz == nullptr) 38 return 0; 39 40 ScopedObjectAccess soa(env); 41 mirror::Class* c = soa.Decode<mirror::Class*>(clazz); 42 43 uint32_t native_method_count = 0; 44 for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) { 45 mirror::ArtMethod* m = c->GetDirectMethod(i); 46 if (m->IsNative()) { 47 native_method_count++; 48 } 49 } 50 for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) { 51 mirror::ArtMethod* m = c->GetVirtualMethod(i); 52 if (m->IsNative()) { 53 native_method_count++; 54 } 55 } 56 return native_method_count; 57 } 58 59 uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods, 60 uint32_t method_count) { 61 if ((clazz == nullptr) || (methods == nullptr)) { 62 return 0; 63 } 64 ScopedObjectAccess soa(env); 65 mirror::Class* c = soa.Decode<mirror::Class*>(clazz); 66 67 uint32_t count = 0; 68 for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) { 69 mirror::ArtMethod* m = c->GetDirectMethod(i); 70 if (m->IsNative()) { 71 if (count < method_count) { 72 methods[count].name = m->GetName(); 73 methods[count].signature = m->GetShorty(); 74 methods[count].fnPtr = m->GetEntryPointFromJni(); 75 count++; 76 } else { 77 LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m); 78 } 79 } 80 } 81 for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) { 82 mirror::ArtMethod* m = c->GetVirtualMethod(i); 83 if (m->IsNative()) { 84 if (count < method_count) { 85 methods[count].name = m->GetName(); 86 methods[count].signature = m->GetShorty(); 87 methods[count].fnPtr = m->GetEntryPointFromJni(); 88 count++; 89 } else { 90 LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m); 91 } 92 } 93 } 94 return count; 95 } 96 97 // Native bridge library runtime callbacks. They represent the runtime interface to native bridge. 98 // 99 // The interface is expected to expose the following methods: 100 // getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(), 101 // native bridge calls back to VM for the shorty of the method so that it can prepare based on 102 // host calling convention. 103 // getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(), 104 // native bridge can call back to get all native methods of specified class so that all 105 // corresponding trampolines can be destroyed. 106 static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ { 107 GetMethodShorty, GetNativeMethodCount, GetNativeMethods 108 }; 109 110 bool LoadNativeBridge(std::string& native_bridge_library_filename) { 111 VLOG(startup) << "Runtime::Setup native bridge library: " 112 << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename); 113 return android::LoadNativeBridge(native_bridge_library_filename.c_str(), 114 &native_bridge_art_callbacks_); 115 } 116 117 void PreInitializeNativeBridge(std::string dir) { 118 VLOG(startup) << "Runtime::Pre-initialize native bridge"; 119 #ifndef __APPLE__ // Mac OS does not support CLONE_NEWNS. 120 if (unshare(CLONE_NEWNS) == -1) { 121 LOG(WARNING) << "Could not create mount namespace."; 122 } 123 android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA)); 124 #endif 125 } 126 127 void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { 128 android::InitializeNativeBridge(env, instruction_set); 129 } 130 131 void UnloadNativeBridge() { 132 android::UnloadNativeBridge(); 133 } 134 135 }; // namespace art 136