com_android_internal_os_FuseAppLoop.cpp revision 4f156065c860d916b649e2b464e9405cafc732e9
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 specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "FuseAppLoopJNI" 18#define LOG_NDEBUG 0 19 20#include <stdlib.h> 21#include <sys/stat.h> 22 23#include <map> 24#include <memory> 25 26#include <android_runtime/Log.h> 27#include <android-base/logging.h> 28#include <android-base/unique_fd.h> 29#include <jni.h> 30#include <libappfuse/FuseAppLoop.h> 31#include <nativehelper/ScopedLocalRef.h> 32#include <nativehelper/ScopedPrimitiveArray.h> 33 34#include "core_jni_helpers.h" 35 36namespace android { 37namespace { 38constexpr const char* CLASS_NAME = "com/android/internal/os/FuseAppLoop"; 39 40jclass gFuseAppLoopClass; 41jmethodID gOnCommandMethod; 42jmethodID gOnOpenMethod; 43 44class Callback : public fuse::FuseAppLoopCallback { 45private: 46 typedef ScopedLocalRef<jbyteArray> LocalBytes; 47 JNIEnv* const mEnv; 48 jobject const mSelf; 49 std::map<uint64_t, std::unique_ptr<LocalBytes>> mBuffers; 50 51public: 52 Callback(JNIEnv* env, jobject self) : 53 mEnv(env), mSelf(self) {} 54 55 void OnLookup(uint64_t unique, uint64_t inode) override { 56 mEnv->CallVoidMethod(mSelf, gOnCommandMethod, FUSE_LOOKUP, unique, inode, 0, 0, nullptr); 57 CHECK(!mEnv->ExceptionCheck()); 58 } 59 60 void OnGetAttr(uint64_t unique, uint64_t inode) override { 61 mEnv->CallVoidMethod(mSelf, gOnCommandMethod, FUSE_GETATTR, unique, inode, 0, 0, nullptr); 62 CHECK(!mEnv->ExceptionCheck()); 63 } 64 65 void OnOpen(uint64_t unique, uint64_t inode) override { 66 const jbyteArray buffer = static_cast<jbyteArray>(mEnv->CallObjectMethod( 67 mSelf, gOnOpenMethod, unique, inode)); 68 CHECK(!mEnv->ExceptionCheck()); 69 if (buffer == nullptr) { 70 return; 71 } 72 73 mBuffers.insert(std::make_pair(inode, std::unique_ptr<LocalBytes>( 74 new LocalBytes(mEnv, buffer)))); 75 } 76 77 void OnFsync(uint64_t unique, uint64_t inode) override { 78 mEnv->CallVoidMethod(mSelf, gOnCommandMethod, FUSE_FSYNC, unique, inode, 0, 0, nullptr); 79 CHECK(!mEnv->ExceptionCheck()); 80 } 81 82 void OnRelease(uint64_t unique, uint64_t inode) override { 83 mBuffers.erase(inode); 84 mEnv->CallVoidMethod(mSelf, gOnCommandMethod, FUSE_RELEASE, unique, inode, 0, 0, nullptr); 85 CHECK(!mEnv->ExceptionCheck()); 86 } 87 88 void OnRead(uint64_t unique, uint64_t inode, uint64_t offset, uint32_t size) override { 89 CHECK_LE(size, static_cast<uint32_t>(fuse::kFuseMaxRead)); 90 91 auto it = mBuffers.find(inode); 92 CHECK(it != mBuffers.end()); 93 94 mEnv->CallVoidMethod( 95 mSelf, gOnCommandMethod, FUSE_READ, unique, inode, offset, size, 96 it->second->get()); 97 CHECK(!mEnv->ExceptionCheck()); 98 } 99 100 void OnWrite(uint64_t unique, uint64_t inode, uint64_t offset, uint32_t size, 101 const void* buffer) override { 102 CHECK_LE(size, static_cast<uint32_t>(fuse::kFuseMaxWrite)); 103 104 auto it = mBuffers.find(inode); 105 CHECK(it != mBuffers.end()); 106 107 jbyteArray const javaBuffer = it->second->get(); 108 109 mEnv->SetByteArrayRegion(javaBuffer, 0, size, static_cast<const jbyte*>(buffer)); 110 CHECK(!mEnv->ExceptionCheck()); 111 112 mEnv->CallVoidMethod( 113 mSelf, gOnCommandMethod, FUSE_WRITE, unique, inode, offset, size, javaBuffer); 114 CHECK(!mEnv->ExceptionCheck()); 115 } 116}; 117 118jlong com_android_internal_os_FuseAppLoop_new(JNIEnv* env, jobject self, jint jfd) { 119 return reinterpret_cast<jlong>(new fuse::FuseAppLoop(base::unique_fd(jfd))); 120} 121 122void com_android_internal_os_FuseAppLoop_delete(JNIEnv* env, jobject self, jlong ptr) { 123 delete reinterpret_cast<fuse::FuseAppLoop*>(ptr); 124} 125 126void com_android_internal_os_FuseAppLoop_start(JNIEnv* env, jobject self, jlong ptr) { 127 Callback callback(env, self); 128 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Start(&callback); 129} 130 131void com_android_internal_os_FuseAppLoop_replySimple( 132 JNIEnv* env, jobject self, jlong ptr, jlong unique, jint result) { 133 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplySimple(unique, result)) { 134 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 135 } 136} 137 138void com_android_internal_os_FuseAppLoop_replyOpen( 139 JNIEnv* env, jobject self, jlong ptr, jlong unique, jlong fh) { 140 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyOpen(unique, fh)) { 141 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 142 } 143} 144 145void com_android_internal_os_FuseAppLoop_replyLookup( 146 JNIEnv* env, jobject self, jlong ptr, jlong unique, jlong inode, jint size) { 147 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyLookup(unique, inode, size)) { 148 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 149 } 150} 151 152void com_android_internal_os_FuseAppLoop_replyGetAttr( 153 JNIEnv* env, jobject self, jlong ptr, jlong unique, jlong inode, jint size) { 154 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyGetAttr( 155 unique, inode, size, S_IFREG | 0777)) { 156 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 157 } 158} 159 160void com_android_internal_os_FuseAppLoop_replyWrite( 161 JNIEnv* env, jobject self, jlong ptr, jlong unique, jint size) { 162 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyWrite(unique, size)) { 163 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 164 } 165} 166 167void com_android_internal_os_FuseAppLoop_replyRead( 168 JNIEnv* env, jobject self, jlong ptr, jlong unique, jint size, jbyteArray data) { 169 ScopedByteArrayRO array(env, data); 170 CHECK(size >= 0); 171 CHECK(static_cast<size_t>(size) < array.size()); 172 if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyRead(unique, size, array.get())) { 173 reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); 174 } 175} 176 177const JNINativeMethod methods[] = { 178 { 179 "native_new", 180 "(I)J", 181 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_new) 182 }, 183 { 184 "native_delete", 185 "(J)V", 186 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_delete) 187 }, 188 { 189 "native_start", 190 "(J)V", 191 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_start) 192 }, 193 { 194 "native_replySimple", 195 "(JJI)V", 196 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replySimple) 197 }, 198 { 199 "native_replyOpen", 200 "(JJJ)V", 201 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replyOpen) 202 }, 203 { 204 "native_replyLookup", 205 "(JJJJ)V", 206 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replyLookup) 207 }, 208 { 209 "native_replyGetAttr", 210 "(JJJJ)V", 211 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replyGetAttr) 212 }, 213 { 214 "native_replyRead", 215 "(JJI[B)V", 216 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replyRead) 217 }, 218 { 219 "native_replyWrite", 220 "(JJI)V", 221 reinterpret_cast<void*>(com_android_internal_os_FuseAppLoop_replyWrite) 222 }, 223}; 224} // namespace 225 226int register_com_android_internal_os_FuseAppLoop(JNIEnv* env) { 227 gFuseAppLoopClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME)); 228 gOnCommandMethod = GetMethodIDOrDie(env, gFuseAppLoopClass, "onCommand", "(IJJJI[B)V"); 229 gOnOpenMethod = GetMethodIDOrDie(env, gFuseAppLoopClass, "onOpen", "(JJ)[B"); 230 RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods)); 231 return 0; 232} 233} // namespace android 234