Loading core/java/com/android/internal/os/AppFuseMount.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import java.io.File; public class AppFuseMount implements Parcelable { final public File mountPoint; final public ParcelFileDescriptor fd; public AppFuseMount(File mountPoint, ParcelFileDescriptor fd) { this.mountPoint = mountPoint; this.fd = fd; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.mountPoint.getPath()); dest.writeParcelable(fd, flags); } public static final Parcelable.Creator<AppFuseMount> CREATOR = new Parcelable.Creator<AppFuseMount>() { @Override public AppFuseMount createFromParcel(Parcel in) { return new AppFuseMount(new File(in.readString()), in.readParcelable(null)); } @Override public AppFuseMount[] newArray(int size) { return new AppFuseMount[size]; } }; } services/core/java/com/android/server/storage/AppFuseBridge.java 0 → 100644 +95 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.storage; import android.annotation.CallSuper; import android.annotation.WorkerThread; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.util.Log; import com.android.internal.os.AppFuseMount; import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.concurrent.CountDownLatch; public class AppFuseBridge implements Runnable { private static final String TAG = AppFuseBridge.class.getSimpleName(); private final FileDescriptor mDeviceFd; private final FileDescriptor mProxyFd; private final CountDownLatch mMountLatch = new CountDownLatch(1); /** * @param deviceFd FD of /dev/fuse. Ownership of fd is taken by AppFuseBridge. * @param proxyFd FD of socket pair. Ownership of fd is taken by AppFuseBridge. */ private AppFuseBridge(FileDescriptor deviceFd, FileDescriptor proxyFd) { mDeviceFd = deviceFd; mProxyFd = proxyFd; } public static AppFuseMount startMessageLoop( int uid, String name, FileDescriptor deviceFd, Handler handler, ParcelFileDescriptor.OnCloseListener listener) throws IOException, ErrnoException, InterruptedException { final FileDescriptor localFd = new FileDescriptor(); final FileDescriptor remoteFd = new FileDescriptor(); // Needs to specify OsConstants.SOCK_SEQPACKET to keep message boundaries. Os.socketpair(OsConstants.AF_UNIX, OsConstants.SOCK_SEQPACKET, 0, remoteFd, localFd); // Caller must invoke #start() after instantiate AppFuseBridge. // Otherwise FDs will be leaked. final AppFuseBridge bridge = new AppFuseBridge(deviceFd, localFd); final Thread thread = new Thread(bridge, TAG); thread.start(); try { bridge.mMountLatch.await(); } catch (InterruptedException error) { throw error; } return new AppFuseMount( new File("/mnt/appfuse/" + uid + "_" + name), ParcelFileDescriptor.fromFd(remoteFd, handler, listener)); } @Override public void run() { // deviceFd and proxyFd must be closed in native_start_loop. final int deviceFd = mDeviceFd.getInt$(); final int proxyFd = mProxyFd.getInt$(); mDeviceFd.setInt$(-1); mProxyFd.setInt$(-1); native_start_loop(deviceFd, proxyFd); } // Used by com_android_server_storage_AppFuse.cpp. private void onMount() { mMountLatch.countDown(); } private native boolean native_start_loop(int deviceFd, int proxyFd); } services/core/jni/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \ $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \ $(LOCAL_REL_DIR)/com_android_server_storage_AppFuseBridge.cpp \ $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \ $(LOCAL_REL_DIR)/com_android_server_tv_TvUinputBridge.cpp \ $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \ Loading @@ -37,6 +38,7 @@ LOCAL_C_INCLUDES += \ frameworks/base/libs/hwui \ frameworks/base/core/jni \ frameworks/native/services \ system/core/libappfuse/include \ system/security/keystore/include \ $(call include-path-for, libhardware)/hardware \ $(call include-path-for, libhardware_legacy)/hardware_legacy \ Loading @@ -44,6 +46,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += \ libandroid_runtime \ libandroidfw \ libappfuse \ libbinder \ libcutils \ liblog \ Loading services/core/jni/com_android_server_storage_AppFuseBridge.cpp 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specic language governing permissions and * limitations under the License. */ // Need to use LOGE_EX. #define LOG_TAG "AppFuseBridge" #include <android_runtime/Log.h> #include <android-base/logging.h> #include <core_jni_helpers.h> #include <libappfuse/FuseBridgeLoop.h> #include <nativehelper/JNIHelp.h> namespace android { namespace { constexpr const char* CLASS_NAME = "com/android/server/storage/AppFuseBridge"; static jclass appFuseClass; static jmethodID appFuseOnMount; class Callback : public FuseBridgeLoop::Callback { JNIEnv* mEnv; jobject mSelf; public: Callback(JNIEnv* env, jobject self) : mEnv(env), mSelf(self) {} void OnMount() override { mEnv->CallVoidMethod(mSelf, appFuseOnMount); if (mEnv->ExceptionCheck()) { LOGE_EX(mEnv, nullptr); mEnv->ExceptionClear(); } } }; jboolean com_android_server_storage_AppFuseBridge_start_loop( JNIEnv* env, jobject self, jint devJavaFd, jint proxyJavaFd) { FuseBridgeLoop loop; Callback callback(env, self); return loop.Start(devJavaFd, proxyJavaFd, &callback); } const JNINativeMethod methods[] = { { "native_start_loop", "(II)Z", (void *) com_android_server_storage_AppFuseBridge_start_loop } }; } // namespace void register_android_server_storage_AppFuse(JNIEnv* env) { CHECK(env != nullptr); appFuseClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME)); appFuseOnMount = GetMethodIDOrDie(env, appFuseClass, "onMount", "()V"); RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods)); } } // namespace android services/core/jni/onload.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ int register_android_server_InputWindowHandle(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); int register_android_server_PowerManagerService(JNIEnv* env); int register_android_server_storage_AppFuse(JNIEnv* env); int register_android_server_SerialService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); Loading Loading @@ -83,6 +84,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_PersistentDataBlockService(env); register_android_server_Watchdog(env); register_android_server_HardwarePropertiesManagerService(env); register_android_server_storage_AppFuse(env); return JNI_VERSION_1_4; } Loading
core/java/com/android/internal/os/AppFuseMount.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.os; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import java.io.File; public class AppFuseMount implements Parcelable { final public File mountPoint; final public ParcelFileDescriptor fd; public AppFuseMount(File mountPoint, ParcelFileDescriptor fd) { this.mountPoint = mountPoint; this.fd = fd; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.mountPoint.getPath()); dest.writeParcelable(fd, flags); } public static final Parcelable.Creator<AppFuseMount> CREATOR = new Parcelable.Creator<AppFuseMount>() { @Override public AppFuseMount createFromParcel(Parcel in) { return new AppFuseMount(new File(in.readString()), in.readParcelable(null)); } @Override public AppFuseMount[] newArray(int size) { return new AppFuseMount[size]; } }; }
services/core/java/com/android/server/storage/AppFuseBridge.java 0 → 100644 +95 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.storage; import android.annotation.CallSuper; import android.annotation.WorkerThread; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.util.Log; import com.android.internal.os.AppFuseMount; import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.concurrent.CountDownLatch; public class AppFuseBridge implements Runnable { private static final String TAG = AppFuseBridge.class.getSimpleName(); private final FileDescriptor mDeviceFd; private final FileDescriptor mProxyFd; private final CountDownLatch mMountLatch = new CountDownLatch(1); /** * @param deviceFd FD of /dev/fuse. Ownership of fd is taken by AppFuseBridge. * @param proxyFd FD of socket pair. Ownership of fd is taken by AppFuseBridge. */ private AppFuseBridge(FileDescriptor deviceFd, FileDescriptor proxyFd) { mDeviceFd = deviceFd; mProxyFd = proxyFd; } public static AppFuseMount startMessageLoop( int uid, String name, FileDescriptor deviceFd, Handler handler, ParcelFileDescriptor.OnCloseListener listener) throws IOException, ErrnoException, InterruptedException { final FileDescriptor localFd = new FileDescriptor(); final FileDescriptor remoteFd = new FileDescriptor(); // Needs to specify OsConstants.SOCK_SEQPACKET to keep message boundaries. Os.socketpair(OsConstants.AF_UNIX, OsConstants.SOCK_SEQPACKET, 0, remoteFd, localFd); // Caller must invoke #start() after instantiate AppFuseBridge. // Otherwise FDs will be leaked. final AppFuseBridge bridge = new AppFuseBridge(deviceFd, localFd); final Thread thread = new Thread(bridge, TAG); thread.start(); try { bridge.mMountLatch.await(); } catch (InterruptedException error) { throw error; } return new AppFuseMount( new File("/mnt/appfuse/" + uid + "_" + name), ParcelFileDescriptor.fromFd(remoteFd, handler, listener)); } @Override public void run() { // deviceFd and proxyFd must be closed in native_start_loop. final int deviceFd = mDeviceFd.getInt$(); final int proxyFd = mProxyFd.getInt$(); mDeviceFd.setInt$(-1); mProxyFd.setInt$(-1); native_start_loop(deviceFd, proxyFd); } // Used by com_android_server_storage_AppFuse.cpp. private void onMount() { mMountLatch.countDown(); } private native boolean native_start_loop(int deviceFd, int proxyFd); }
services/core/jni/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \ $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \ $(LOCAL_REL_DIR)/com_android_server_storage_AppFuseBridge.cpp \ $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \ $(LOCAL_REL_DIR)/com_android_server_tv_TvUinputBridge.cpp \ $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \ Loading @@ -37,6 +38,7 @@ LOCAL_C_INCLUDES += \ frameworks/base/libs/hwui \ frameworks/base/core/jni \ frameworks/native/services \ system/core/libappfuse/include \ system/security/keystore/include \ $(call include-path-for, libhardware)/hardware \ $(call include-path-for, libhardware_legacy)/hardware_legacy \ Loading @@ -44,6 +46,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += \ libandroid_runtime \ libandroidfw \ libappfuse \ libbinder \ libcutils \ liblog \ Loading
services/core/jni/com_android_server_storage_AppFuseBridge.cpp 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specic language governing permissions and * limitations under the License. */ // Need to use LOGE_EX. #define LOG_TAG "AppFuseBridge" #include <android_runtime/Log.h> #include <android-base/logging.h> #include <core_jni_helpers.h> #include <libappfuse/FuseBridgeLoop.h> #include <nativehelper/JNIHelp.h> namespace android { namespace { constexpr const char* CLASS_NAME = "com/android/server/storage/AppFuseBridge"; static jclass appFuseClass; static jmethodID appFuseOnMount; class Callback : public FuseBridgeLoop::Callback { JNIEnv* mEnv; jobject mSelf; public: Callback(JNIEnv* env, jobject self) : mEnv(env), mSelf(self) {} void OnMount() override { mEnv->CallVoidMethod(mSelf, appFuseOnMount); if (mEnv->ExceptionCheck()) { LOGE_EX(mEnv, nullptr); mEnv->ExceptionClear(); } } }; jboolean com_android_server_storage_AppFuseBridge_start_loop( JNIEnv* env, jobject self, jint devJavaFd, jint proxyJavaFd) { FuseBridgeLoop loop; Callback callback(env, self); return loop.Start(devJavaFd, proxyJavaFd, &callback); } const JNINativeMethod methods[] = { { "native_start_loop", "(II)Z", (void *) com_android_server_storage_AppFuseBridge_start_loop } }; } // namespace void register_android_server_storage_AppFuse(JNIEnv* env) { CHECK(env != nullptr); appFuseClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME)); appFuseOnMount = GetMethodIDOrDie(env, appFuseClass, "onMount", "()V"); RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods)); } } // namespace android
services/core/jni/onload.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ int register_android_server_InputWindowHandle(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); int register_android_server_PowerManagerService(JNIEnv* env); int register_android_server_storage_AppFuse(JNIEnv* env); int register_android_server_SerialService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); Loading Loading @@ -83,6 +84,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_PersistentDataBlockService(env); register_android_server_Watchdog(env); register_android_server_HardwarePropertiesManagerService(env); register_android_server_storage_AppFuse(env); return JNI_VERSION_1_4; }