Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c62ca218 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add AppFuseBridge class to the system service."

parents 664e8e58 3ff1c01c
Loading
Loading
Loading
Loading
+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];
        }
    };
}
+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);
}
+3 −0
Original line number Diff line number Diff line
@@ -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 \
@@ -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 \
@@ -44,6 +46,7 @@ LOCAL_C_INCLUDES += \
LOCAL_SHARED_LIBRARIES += \
    libandroid_runtime \
    libandroidfw \
    libappfuse \
    libbinder \
    libcutils \
    liblog \
+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
+2 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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;
}