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

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

Merge "Process FuseAppLoop messages in Handler.Callback" into oc-dev

parents 6df866a8 ea6e6e17
Loading
Loading
Loading
Loading
+123 −83
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.ProxyFileDescriptorCallback;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -28,10 +29,11 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ThreadFactory;

public class FuseAppLoop {
public class FuseAppLoop implements Handler.Callback {
    private static final String TAG = "FuseAppLoop";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    public static final int ROOT_INODE = 1;
@@ -43,13 +45,11 @@ public class FuseAppLoop {
        }
    };
    private static final int FUSE_OK = 0;
    private static final int ARGS_POOL_SIZE = 50;

    private final Object mLock = new Object();
    private final int mMountPointId;
    private final Thread mThread;
    private final Handler mDefaultHandler;

    private static final int CMD_FSYNC = 1;

    @GuardedBy("mLock")
    private final SparseArray<CallbackEntry> mCallbackMap = new SparseArray<>();
@@ -57,6 +57,9 @@ public class FuseAppLoop {
    @GuardedBy("mLock")
    private final BytesMap mBytesMap = new BytesMap();

    @GuardedBy("mLock")
    private final LinkedList<Args> mArgsPool = new LinkedList<>();

    /**
     * Sequential number can be used as file name and inode in AppFuse.
     * 0 is regarded as an error, 1 is mount point. So we start the number from 2.
@@ -83,7 +86,6 @@ public class FuseAppLoop {
            }
        });
        mThread.start();
        mDefaultHandler = null;
    }

    public int registerCallback(@NonNull ProxyFileDescriptorCallback callback,
@@ -110,7 +112,8 @@ public class FuseAppLoop {
                    break;
                }
            }
            mCallbackMap.put(id, new CallbackEntry(callback, handler));
            mCallbackMap.put(id, new CallbackEntry(
                    callback, new Handler(handler.getLooper(), this)));
            return id;
        }
    }
@@ -137,22 +140,25 @@ public class FuseAppLoop {
    // Defined in FuseBuffer.h
    private static final int FUSE_MAX_WRITE = 256 * 1024;

    // Called by JNI.
    @SuppressWarnings("unused")
    private void onCommand(int command, long unique, long inode, long offset, int size,
            byte[] data) {
        synchronized(mLock) {
            try {
                final CallbackEntry entry = getCallbackEntryOrThrowLocked(inode);
                entry.postRunnable(() -> {
    @Override
    public boolean handleMessage(Message msg) {
        final Args args = (Args) msg.obj;
        final CallbackEntry entry = args.entry;
        final long inode = args.inode;
        final long unique = args.unique;
        final int size = args.size;
        final long offset = args.offset;
        final byte[] data = args.data;

        try {
                        switch (command) {
            switch (msg.what) {
                case FUSE_LOOKUP: {
                    final long fileSize = entry.callback.onGetSize();
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyLookup(mInstance, unique, inode, fileSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                }
@@ -162,15 +168,18 @@ public class FuseAppLoop {
                        if (mInstance != 0) {
                            native_replyGetAttr(mInstance, unique, inode, fileSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                }
                case FUSE_READ:
                                final int readSize = entry.callback.onRead(offset, size, data);
                    final int readSize = entry.callback.onRead(
                            offset, size, data);
                    synchronized (mLock) {
                        if (mInstance != 0) {
                            native_replyRead(mInstance, unique, readSize, data);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_WRITE:
@@ -179,6 +188,7 @@ public class FuseAppLoop {
                        if (mInstance != 0) {
                            native_replyWrite(mInstance, unique, writeSize);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_FSYNC:
@@ -187,6 +197,7 @@ public class FuseAppLoop {
                        if (mInstance != 0) {
                            native_replySimple(mInstance, unique, FUSE_OK);
                        }
                        recycleLocked(args);
                    }
                    break;
                case FUSE_RELEASE:
@@ -196,19 +207,46 @@ public class FuseAppLoop {
                            native_replySimple(mInstance, unique, FUSE_OK);
                        }
                        mBytesMap.stopUsing(entry.getThreadId());
                        recycleLocked(args);
                    }
                    break;
                default:
                                throw new IllegalArgumentException(
                                        "Unknown FUSE command: " + command);
                    throw new IllegalArgumentException("Unknown FUSE command: " + msg.what);
            }
        } catch (Exception error) {
            synchronized (mLock) {
                Log.e(TAG, "", error);
                        replySimple(unique, getError(error));
                replySimpleLocked(unique, getError(error));
                recycleLocked(args);
            }
                });
            } catch (ErrnoException error) {
                Log.e(TAG, "", error);
        }

        return true;
    }

    // Called by JNI.
    @SuppressWarnings("unused")
    private void onCommand(int command, long unique, long inode, long offset, int size,
            byte[] data) {
        synchronized (mLock) {
            try {
                final Args args;
                if (mArgsPool.size() == 0) {
                    args = new Args();
                } else {
                    args = mArgsPool.pop();
                }
                args.unique = unique;
                args.inode = inode;
                args.offset = offset;
                args.size = size;
                args.data = data;
                args.entry = getCallbackEntryOrThrowLocked(inode);
                if (!args.entry.handler.sendMessage(
                        Message.obtain(args.entry.handler, command, 0, 0, args))) {
                    throw new ErrnoException("onCommand", OsConstants.EBADF);
                }
            } catch (Exception error) {
                replySimpleLocked(unique, getError(error));
            }
        }
@@ -253,9 +291,9 @@ public class FuseAppLoop {
        return entry;
    }

    private void replySimple(long unique, int result) {
        synchronized (mLock) {
            replySimpleLocked(unique, result);
    private void recycleLocked(Args args) {
        if (mArgsPool.size() < ARGS_POOL_SIZE) {
            mArgsPool.add(args);
        }
    }

@@ -296,13 +334,6 @@ public class FuseAppLoop {
        long getThreadId() {
            return handler.getLooper().getThread().getId();
        }

        void postRunnable(Runnable runnable) throws ErrnoException {
            final boolean result = handler.post(runnable);
            if (!result) {
                throw new ErrnoException("postRunnable", OsConstants.EBADF);
            }
        }
    }

    /**
@@ -342,4 +373,13 @@ public class FuseAppLoop {
            mEntries.clear();
        }
    }

    private static class Args {
        long unique;
        long inode;
        long offset;
        int size;
        byte[] data;
        CallbackEntry entry;
    }
}