1 /* 2 * Copyright (C) 2016 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 specic language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Need to use LOGE_EX. 18 #define LOG_TAG "AppFuseBridge" 19 20 #include <android_runtime/Log.h> 21 #include <android-base/logging.h> 22 #include <android-base/unique_fd.h> 23 #include <core_jni_helpers.h> 24 #include <libappfuse/FuseBridgeLoop.h> 25 #include <libappfuse/FuseBuffer.h> 26 #include <nativehelper/JNIHelp.h> 27 28 namespace android { 29 namespace { 30 31 constexpr const char* CLASS_NAME = "com/android/server/storage/AppFuseBridge"; 32 static jclass gAppFuseClass; 33 static jmethodID gAppFuseOnMount; 34 static jmethodID gAppFuseOnClosed; 35 36 class Callback : public fuse::FuseBridgeLoopCallback { 37 JNIEnv* mEnv; 38 jobject mSelf; 39 40 public: 41 Callback(JNIEnv* env, jobject self) : mEnv(env), mSelf(self) {} 42 void OnMount(int mount_id) override { 43 mEnv->CallVoidMethod(mSelf, gAppFuseOnMount, mount_id); 44 if (mEnv->ExceptionCheck()) { 45 LOGE_EX(mEnv, nullptr); 46 mEnv->ExceptionClear(); 47 } 48 } 49 50 void OnClosed(int mount_id) override { 51 mEnv->CallVoidMethod(mSelf, gAppFuseOnClosed, mount_id); 52 if (mEnv->ExceptionCheck()) { 53 LOGE_EX(mEnv, nullptr); 54 mEnv->ExceptionClear(); 55 } 56 } 57 }; 58 59 class MonitorScope final { 60 public: 61 MonitorScope(JNIEnv* env, jobject obj) : mEnv(env), mObj(obj), mLocked(false) { 62 if (mEnv->MonitorEnter(obj) == JNI_OK) { 63 mLocked = true; 64 } else { 65 LOG(ERROR) << "Failed to enter monitor."; 66 } 67 } 68 69 ~MonitorScope() { 70 if (mLocked) { 71 if (mEnv->MonitorExit(mObj) != JNI_OK) { 72 LOG(ERROR) << "Failed to exit monitor."; 73 } 74 } 75 } 76 77 operator bool() { 78 return mLocked; 79 } 80 81 private: 82 // Lifetime of |MonitorScope| must be shorter than the reference of mObj. 83 JNIEnv* mEnv; 84 jobject mObj; 85 bool mLocked; 86 87 DISALLOW_COPY_AND_ASSIGN(MonitorScope); 88 }; 89 90 jlong com_android_server_storage_AppFuseBridge_new(JNIEnv* env, jobject self) { 91 return reinterpret_cast<jlong>(new fuse::FuseBridgeLoop()); 92 } 93 94 void com_android_server_storage_AppFuseBridge_delete(JNIEnv* env, jobject self, jlong java_loop) { 95 fuse::FuseBridgeLoop* const loop = reinterpret_cast<fuse::FuseBridgeLoop*>(java_loop); 96 CHECK(loop); 97 delete loop; 98 } 99 100 void com_android_server_storage_AppFuseBridge_start_loop( 101 JNIEnv* env, jobject self, jlong java_loop) { 102 fuse::FuseBridgeLoop* const loop = reinterpret_cast<fuse::FuseBridgeLoop*>(java_loop); 103 CHECK(loop); 104 Callback callback(env, self); 105 loop->Start(&callback); 106 } 107 108 jint com_android_server_storage_AppFuseBridge_add_bridge( 109 JNIEnv* env, jobject self, jlong java_loop, jint mountId, jint javaDevFd) { 110 base::unique_fd devFd(javaDevFd); 111 fuse::FuseBridgeLoop* const loop = reinterpret_cast<fuse::FuseBridgeLoop*>(java_loop); 112 CHECK(loop); 113 114 base::unique_fd proxyFd[2]; 115 if (!fuse::SetupMessageSockets(&proxyFd)) { 116 return -1; 117 } 118 119 if (!loop->AddBridge(mountId, std::move(devFd), std::move(proxyFd[0]))) { 120 return -1; 121 } 122 123 return proxyFd[1].release(); 124 } 125 126 const JNINativeMethod methods[] = { 127 { 128 "native_new", 129 "()J", 130 reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_new) 131 }, 132 { 133 "native_delete", 134 "(J)V", 135 reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_delete) 136 }, 137 { 138 "native_start_loop", 139 "(J)V", 140 reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_start_loop) 141 }, 142 { 143 "native_add_bridge", 144 "(JII)I", 145 reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_add_bridge) 146 } 147 }; 148 149 } // namespace 150 151 void register_android_server_storage_AppFuse(JNIEnv* env) { 152 CHECK(env != nullptr); 153 154 gAppFuseClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME)); 155 gAppFuseOnMount = GetMethodIDOrDie(env, gAppFuseClass, "onMount", "(I)V"); 156 gAppFuseOnClosed = GetMethodIDOrDie(env, gAppFuseClass, "onClosed", "(I)V"); 157 RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods)); 158 } 159 } // namespace android 160