MTP: Add MtpServer Java class to wrap MTP device support.

Change-Id: I818c2d3b3f52ad5bb515acc4d3288b2b43e11908
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 32a5f3d..c4138b6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -114,6 +114,7 @@
 	android_media_JetPlayer.cpp \
 	android_media_MtpClient.cpp \
 	android_media_MtpCursor.cpp \
+	android_media_MtpServer.cpp \
 	android_media_ToneGenerator.cpp \
 	android_hardware_Camera.cpp \
 	android_hardware_SensorManager.cpp \
@@ -193,9 +194,10 @@
 	libicudata \
 	libmedia \
 	libwpa_client \
-	libjpeg
+	libjpeg \
+	libstagefright
 
-LOCAL_STATIC_LIBRARIES := libmtphost libusbhost
+LOCAL_STATIC_LIBRARIES := libmtp libusbhost
 
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
 LOCAL_C_INCLUDES += \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f2bd168..58b3097 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -128,6 +128,7 @@
 extern int register_android_debug_JNITest(JNIEnv* env);
 extern int register_android_media_MtpClient(JNIEnv *env);
 extern int register_android_media_MtpCursor(JNIEnv *env);
+extern int register_android_media_MtpServer(JNIEnv *env);
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_pim_EventRecurrence(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
@@ -1283,6 +1284,7 @@
     REG_JNI(register_android_media_JetPlayer),
     REG_JNI(register_android_media_MtpClient),
     REG_JNI(register_android_media_MtpCursor),
+    REG_JNI(register_android_media_MtpServer),
     REG_JNI(register_android_media_ToneGenerator),
 
     REG_JNI(register_android_opengl_classes),
diff --git a/core/jni/android_media_MtpServer.cpp b/core/jni/android_media_MtpServer.cpp
new file mode 100644
index 0000000..9f961a2
--- /dev/null
+++ b/core/jni/android_media_MtpServer.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "MtpServerJNI"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include "MtpServer.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+static jfieldID field_context;
+
+
+// ----------------------------------------------------------------------------
+
+static bool ExceptionCheck(void* env)
+{
+    return ((JNIEnv *)env)->ExceptionCheck();
+}
+
+class MtpThread : public Thread {
+private:
+    String8 mStoragePath;
+    String8 mDatabasePath;
+    bool mDone;
+    bool mScannedOnce;
+
+public:
+    MtpThread(const char* storagePath, const char* databasePath)
+        : mStoragePath(storagePath), mDatabasePath(databasePath), mDone(false), mScannedOnce(false)
+    {
+    }
+
+    virtual bool threadLoop() {
+        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;
+        }
+
+        MtpServer* server = new MtpServer(fd, mDatabasePath);
+        server->addStorage(mStoragePath);
+
+        // temporary
+        LOGD("MtpThread server->scanStorage");
+        server->scanStorage();
+        LOGD("MtpThread server->run");
+        server->run();
+        close(fd);
+        delete server;
+
+        bool done = mDone;
+        if (done)
+            delete this;
+        LOGD("threadLoop returning %s", (done ? "false" : "true"));
+        return !done;
+    }
+
+    void setDone() { mDone = true; }
+};
+
+static void
+android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jstring storagePath, jstring databasePath)
+{
+    LOGD("setup\n");
+
+    const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
+    const char *databasePathStr = env->GetStringUTFChars(databasePath, NULL);
+
+    MtpThread* thread = new MtpThread(storagePathStr, databasePathStr);
+    env->SetIntField(thiz, field_context, (int)thread);
+
+    env->ReleaseStringUTFChars(storagePath, storagePathStr);
+    env->ReleaseStringUTFChars(databasePath, databasePathStr);
+}
+
+static void
+android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
+{
+    LOGD("finalize\n");
+}
+
+
+static void
+android_media_MtpServer_start(JNIEnv *env, jobject thiz)
+{
+    LOGD("start\n");
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    thread->run("MtpThread");
+}
+
+static void
+android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
+{
+    LOGD("stop\n");
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    if (thread) {
+        thread->setDone();
+        env->SetIntField(thiz, field_context, 0);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"native_setup",            "(Ljava/lang/String;Ljava/lang/String;)V",  (void *)android_media_MtpServer_setup},
+    {"native_finalize",         "()V",  (void *)android_media_MtpServer_finalize},
+    {"native_start",            "()V",  (void *)android_media_MtpServer_start},
+    {"native_stop",             "()V",  (void *)android_media_MtpServer_stop},
+};
+
+static const char* const kClassPathName = "android/media/MtpServer";
+
+int register_android_media_MtpServer(JNIEnv *env)
+{
+    jclass clazz;
+
+    LOGD("register_android_media_MtpServer\n");
+
+    clazz = env->FindClass("android/media/MtpServer");
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MtpServer");
+        return -1;
+    }
+    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (field_context == NULL) {
+        LOGE("Can't find MtpServer.mNativeContext");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/MtpServer", gMethods, NELEM(gMethods));
+}
+
+} // namespace android
diff --git a/media/java/android/media/MtpClient.java b/media/java/android/media/MtpClient.java
index 95182bd..ad6640f 100644
--- a/media/java/android/media/MtpClient.java
+++ b/media/java/android/media/MtpClient.java
@@ -110,4 +110,4 @@
     private native boolean native_delete_object(int deviceID, int objectID);
     private native int native_get_parent(int deviceID, int objectID);
     private native int native_get_storage_id(int deviceID, int objectID);
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/MtpServer.java b/media/java/android/media/MtpServer.java
new file mode 100644
index 0000000..a9a54e7
--- /dev/null
+++ b/media/java/android/media/MtpServer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 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 android.media;
+
+import android.util.Log;
+
+/**
+ * Java wrapper for MTP/PTP support as USB responder.
+ * {@hide}
+ */
+public class MtpServer {
+
+    private static final String TAG = "MtpServer";
+
+    static {
+        System.loadLibrary("media_jni");
+    }
+
+    public MtpServer(String storagePath, String databasePath) {
+        native_setup(storagePath, databasePath);
+    }
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    }
+
+    public void start() {
+        native_start();
+    }
+
+    public void stop() {
+        native_stop();
+    }
+
+    // used by the JNI code
+    private int mNativeContext;
+
+    private native final void native_setup(String storagePath, String databasePath);
+    private native final void native_finalize();
+    private native final void native_start();
+    private native final void native_stop();
+}
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index 9f684e1..f363b7c 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -20,62 +20,55 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                                       \
-                  mtptest.cpp                           \
+                  MtpClient.cpp                         \
+                  MtpCursor.cpp                         \
                   MtpDatabase.cpp                       \
                   MtpDataPacket.cpp                     \
                   MtpDebug.cpp                          \
+                  MtpDevice.cpp                         \
+                  MtpDeviceInfo.cpp                     \
                   MtpMediaScanner.cpp                   \
+                  MtpObjectInfo.cpp                     \
                   MtpPacket.cpp                         \
+                  MtpProperty.cpp                       \
                   MtpRequestPacket.cpp                  \
                   MtpResponsePacket.cpp                 \
                   MtpServer.cpp                         \
+                  MtpStorageInfo.cpp                    \
                   MtpStringBuffer.cpp                   \
                   MtpStorage.cpp                        \
                   MtpUtils.cpp                          \
                   SqliteDatabase.cpp                    \
                   SqliteStatement.cpp                   \
 
-LOCAL_MODULE:= mtptest
+LOCAL_MODULE:= libmtp
 
 LOCAL_C_INCLUDES := external/sqlite/dist
 
+LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                                       \
+                  mtptest.cpp                           \
+
+LOCAL_MODULE:= mtptest
+
 LOCAL_CFLAGS := -DMTP_DEVICE
 
 LOCAL_SHARED_LIBRARIES := libutils libsqlite libstagefright libcutils \
 	libmedia
 
+LOCAL_STATIC_LIBRARIES := libmtp
+
 include $(BUILD_EXECUTABLE)
 
 endif
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := libmtphost
-
-LOCAL_SRC_FILES:=                                       \
-                  MtpClient.cpp                         \
-                  MtpCursor.cpp                         \
-                  MtpDataPacket.cpp                     \
-                  MtpDebug.cpp                          \
-                  MtpDevice.cpp                         \
-                  MtpDeviceInfo.cpp                     \
-                  MtpObjectInfo.cpp                     \
-                  MtpPacket.cpp                         \
-                  MtpProperty.cpp                       \
-                  MtpRequestPacket.cpp                  \
-                  MtpResponsePacket.cpp                 \
-                  MtpStorageInfo.cpp                    \
-                  MtpStringBuffer.cpp                   \
-                  MtpUtils.cpp                          \
-
-
-LOCAL_CFLAGS := -g -DMTP_HOST
-LOCAL_LDFLAGS := -g
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
 LOCAL_MODULE := scantest
 LOCAL_SRC_FILES:=                                       \
                   scantest.cpp                          \
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
index 6a33a2b..b7c79b2 100644
--- a/media/mtp/MtpTypes.h
+++ b/media/mtp/MtpTypes.h
@@ -42,7 +42,7 @@
 // values 0x00000000 and 0xFFFFFFFF are reserved for special purposes.
 typedef uint32_t MtpObjectHandle;
 
-typedef union MtpPropertyValue {
+union MtpPropertyValue {
     int8_t          i8;
     uint8_t         u8;
     int16_t         i16;