jboolean com_android_mtp_AppFuse_start_app_fuse_loop(
JNIEnv* env, jobject self, jint jfd) {
- ScopedFd fd(dup(static_cast<int>(jfd)));
+ ScopedFd fd(static_cast<int>(jfd));
AppFuse appfuse(env, self);
ALOGD("Start fuse loop.");
import android.os.storage.StorageManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import com.android.mtp.annotations.UsedByNative;
import java.io.File;
import java.io.FileNotFoundException;
private final String mName;
private final Callback mCallback;
- private final Thread mMessageThread;
+ private Thread mMessageThread;
private ParcelFileDescriptor mDeviceFd;
AppFuse(String name, Callback callback) {
mName = name;
mCallback = callback;
- mMessageThread = new Thread(new Runnable() {
- @Override
- public void run() {
- native_start_app_fuse_loop(mDeviceFd.getFd());
- }
- });
}
- void mount(StorageManager storageManager) {
+ void mount(StorageManager storageManager) throws IOException {
+ Preconditions.checkState(mDeviceFd == null);
mDeviceFd = storageManager.mountAppFuse(mName);
+ mMessageThread = new AppFuseMessageThread(mDeviceFd.dup().detachFd());
mMessageThread.start();
}
ParcelFileDescriptor.MODE_READ_ONLY);
}
- @VisibleForTesting
File getMountPoint() {
return new File("/mnt/appfuse/" + Process.myUid() + "_" + mName);
}
}
private native boolean native_start_app_fuse_loop(int fd);
+
+ private class AppFuseMessageThread extends Thread {
+ /**
+ * File descriptor used by native loop.
+ * It's owned by native loop and does not need to close here.
+ */
+ private final int mRawFd;
+
+ AppFuseMessageThread(int fd) {
+ super("AppFuseMessageThread");
+ mRawFd = fd;
+ }
+
+ @Override
+ public void run() {
+ native_start_app_fuse_loop(mRawFd);
+ }
+ }
}
mRootScanner = new RootScanner(mResolver, mResources, mMtpManager, mDatabase);
mAppFuse = new AppFuse(TAG, new AppFuseCallback());
// TODO: Mount AppFuse on demands.
- mAppFuse.mount(getContext().getSystemService(StorageManager.class));
+ try {
+ mAppFuse.mount(getContext().getSystemService(StorageManager.class));
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to start app fuse.", e);
+ return false;
+ }
resume();
return true;
}
@MediumTest
public class AppFuseTest extends AndroidTestCase {
- public void testMount() throws ErrnoException {
+ public void testMount() throws ErrnoException, IOException {
final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
final AppFuse appFuse = new AppFuse("test", new TestCallback());
appFuse.mount(storageManager);
appFuse.close();
}
- public void testOpenFile_error() {
+ public void testOpenFile_fileNotFound() throws IOException {
final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
final int INODE = 10;
final AppFuse appFuse = new AppFuse("test", new TestCallback());