Loading core/java/com/android/internal/os/FuseAppLoop.java +123 −83 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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<>(); Loading @@ -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. Loading @@ -83,7 +86,6 @@ public class FuseAppLoop { } }); mThread.start(); mDefaultHandler = null; } public int registerCallback(@NonNull ProxyFileDescriptorCallback callback, Loading @@ -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; } } Loading @@ -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; } Loading @@ -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: Loading @@ -179,6 +188,7 @@ public class FuseAppLoop { if (mInstance != 0) { native_replyWrite(mInstance, unique, writeSize); } recycleLocked(args); } break; case FUSE_FSYNC: Loading @@ -187,6 +197,7 @@ public class FuseAppLoop { if (mInstance != 0) { native_replySimple(mInstance, unique, FUSE_OK); } recycleLocked(args); } break; case FUSE_RELEASE: Loading @@ -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)); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } } } /** Loading Loading @@ -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; } } Loading
core/java/com/android/internal/os/FuseAppLoop.java +123 −83 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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<>(); Loading @@ -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. Loading @@ -83,7 +86,6 @@ public class FuseAppLoop { } }); mThread.start(); mDefaultHandler = null; } public int registerCallback(@NonNull ProxyFileDescriptorCallback callback, Loading @@ -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; } } Loading @@ -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; } Loading @@ -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: Loading @@ -179,6 +188,7 @@ public class FuseAppLoop { if (mInstance != 0) { native_replyWrite(mInstance, unique, writeSize); } recycleLocked(args); } break; case FUSE_FSYNC: Loading @@ -187,6 +197,7 @@ public class FuseAppLoop { if (mInstance != 0) { native_replySimple(mInstance, unique, FUSE_OK); } recycleLocked(args); } break; case FUSE_RELEASE: Loading @@ -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)); } } Loading Loading @@ -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); } } Loading Loading @@ -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); } } } /** Loading Loading @@ -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; } }