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

Commit 23ee42f9 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

MTP: Fix some thread safety issues in MTP server start/stop sequence.



Change-Id: Ied1cddc6220fa7394e8de99df9bc37a1208b04ff
Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent d4b50201
Loading
Loading
Loading
Loading
+56 −38
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ using namespace android;
// ----------------------------------------------------------------------------

static jfieldID field_context;
static Mutex    sMutex;

// in android_media_MtpDatabase.cpp
extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
@@ -55,61 +56,78 @@ private:
    MtpServer*      mServer;
    String8         mStoragePath;
    bool            mDone;
    Mutex           mMutex;
    jobject         mJavaServer;

public:
    MtpThread(MtpDatabase* database, const char* storagePath)
        : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false)
    MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer)
        : mDatabase(database),
            mServer(NULL),
            mStoragePath(storagePath),
            mDone(false),
            mJavaServer(javaServer)
    {
    }

    virtual bool threadLoop() {
        while (1) {
            int fd = open("/dev/mtp_usb", O_RDWR);
            printf("open returned %d\n", fd);
            if (fd < 0) {
                LOGE("could not open MTP driver\n");
            return false;
                break;
            }

        mMutex.lock();
            sMutex.lock();
            mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775);
            mServer->addStorage(mStoragePath);
        mMutex.unlock();
            sMutex.unlock();

            LOGD("MtpThread mServer->run");
            mServer->run();
            close(fd);

        mMutex.lock();
            sMutex.lock();
            delete mServer;
            mServer = NULL;
        mMutex.unlock();
            if (mDone)
                goto done;
            sMutex.unlock();
            // wait a bit before retrying
            sleep(1);
        }

        bool done = mDone;
        if (done)
            delete this;
        LOGD("threadLoop returning %s", (done ? "false" : "true"));
        return !done;
        sMutex.lock();
done:
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        env->SetIntField(mJavaServer, field_context, 0);
        env->DeleteGlobalRef(mJavaServer);
        sMutex.unlock();

        LOGD("threadLoop returning");
        return false;
    }

    void setDone() { mDone = true; }
    void setDone() {
        LOGD("setDone");
        mDone = true; 
    }

    void sendObjectAdded(MtpObjectHandle handle) {
        mMutex.lock();
        sMutex.lock();
        if (mServer)
            mServer->sendObjectAdded(handle);
        else
            LOGE("sendObjectAdded called while disconnected\n");
        mMutex.unlock();
        sMutex.unlock();
    }

    void sendObjectRemoved(MtpObjectHandle handle) {
        mMutex.lock();
        sMutex.lock();
        if (mServer)
            mServer->sendObjectRemoved(handle);
        else
            LOGE("sendObjectRemoved called while disconnected\n");
        mMutex.unlock();
        sMutex.unlock();
    }
};

@@ -124,7 +142,7 @@ android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, j
    MtpDatabase* database = getMtpDatabase(env, javaDatabase);
    const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);

    MtpThread* thread = new MtpThread(database, storagePathStr);
    MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz));
    env->SetIntField(thiz, field_context, (int)thread);

    env->ReleaseStringUTFChars(storagePath, storagePathStr);
@@ -153,11 +171,11 @@ android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
{
#ifdef HAVE_ANDROID_OS
    LOGD("stop\n");
    sMutex.lock();
    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
    if (thread) {
    if (thread)
        thread->setDone();
        env->SetIntField(thiz, field_context, 0);
    }
    sMutex.unlock();
#endif
}