MTP: Implement GetNumObjects

Change-Id: Iccc3a445f9a1eab7bb76eddd567c6a3a8f155b2b
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index ba5c918..1b82d39 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -164,6 +164,33 @@
         return null;
     }
 
+    private int getNumObjects(int storageID, int format, int parent) {
+        // we can ignore storageID until we support multiple storages
+        Log.d(TAG, "getObjectList parent: " + parent);
+        Cursor c = null;
+        try {
+            if (format != 0) {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_FORMAT_WHERE,
+                            new String[] { Integer.toString(parent), Integer.toString(format) },
+                             null);
+            } else {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
+            }
+            if (c != null) {
+                return c.getCount();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getNumObjects", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return -1;
+    }
+
     private int getObjectProperty(int handle, int property,
                             long[] outIntValue, char[] outStringValue) {
         Log.d(TAG, "getObjectProperty: " + property);
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 9e1ede5..5ab0a55 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -39,6 +39,7 @@
 static jmethodID method_beginSendObject;
 static jmethodID method_endSendObject;
 static jmethodID method_getObjectList;
+static jmethodID method_getNumObjects;
 static jmethodID method_getObjectProperty;
 static jmethodID method_getObjectInfo;
 static jmethodID method_getObjectFilePath;
@@ -80,6 +81,10 @@
                                     MtpObjectFormat format,
                                     MtpObjectHandle parent);
 
+    virtual int                     getNumObjects(MtpStorageID storageID,
+                                            MtpObjectFormat format,
+                                            MtpObjectHandle parent);
+
     virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet);
@@ -164,15 +169,20 @@
     MtpObjectHandleList* list = new MtpObjectHandleList();
     jint* handles = env->GetIntArrayElements(array, 0);
     jsize length = env->GetArrayLength(array);
-LOGD("getObjectList length: %d", length);
-    for (int i = 0; i < length; i++) {
-LOGD("push: %d", handles[i]);
+    for (int i = 0; i < length; i++)
         list->push(handles[i]);
-    }
    env->ReleaseIntArrayElements(array, handles, 0);
    return list;
 }
 
+int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
+                                MtpObjectFormat format,
+                                MtpObjectHandle parent) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    return env->CallIntMethod(mDatabase, method_getNumObjects,
+                (jint)storageID, (jint)format, (jint)parent);
+}
+
 MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) {
@@ -407,6 +417,11 @@
         LOGE("Can't find getObjectList");
         return -1;
     }
+    method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
+    if (method_getNumObjects == NULL) {
+        LOGE("Can't find getNumObjects");
+        return -1;
+    }
     method_getObjectProperty = env->GetMethodID(clazz, "getObjectProperty", "(II[J[C)I");
     if (method_getObjectProperty == NULL) {
         LOGE("Can't find getObjectProperty");
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index a17797e..bbbbc38 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -47,6 +47,10 @@
                                             MtpObjectFormat format,
                                             MtpObjectHandle parent) = 0;
 
+    virtual int                     getNumObjects(MtpStorageID storageID,
+                                            MtpObjectFormat format,
+                                            MtpObjectHandle parent) = 0;
+
     virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) = 0;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 1e41407..50a839e 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -55,10 +55,10 @@
 //    MTP_OPERATION_SELF_TEST,
 //    MTP_OPERATION_SET_OBJECT_PROTECTION,
 //    MTP_OPERATION_POWER_DOWN,
-    MTP_OPERATION_GET_DEVICE_PROP_DESC,
-    MTP_OPERATION_GET_DEVICE_PROP_VALUE,
-    MTP_OPERATION_SET_DEVICE_PROP_VALUE,
-    MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
+//    MTP_OPERATION_GET_DEVICE_PROP_DESC,
+//    MTP_OPERATION_GET_DEVICE_PROP_VALUE,
+//    MTP_OPERATION_SET_DEVICE_PROP_VALUE,
+//    MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
 //    MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
 //    MTP_OPERATION_MOVE_OBJECT,
 //    MTP_OPERATION_COPY_OBJECT,
@@ -67,7 +67,7 @@
     MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
 //    MTP_OPERATION_GET_OBJECT_PROP_DESC,
     MTP_OPERATION_GET_OBJECT_PROP_VALUE,
-    MTP_OPERATION_SET_OBJECT_PROP_VALUE,
+//    MTP_OPERATION_SET_OBJECT_PROP_VALUE,
 //    MTP_OPERATION_GET_OBJECT_REFERENCES,
 //    MTP_OPERATION_SET_OBJECT_REFERENCES,
 //    MTP_OPERATION_SKIP,
@@ -308,6 +308,9 @@
         case MTP_OPERATION_GET_OBJECT_HANDLES:
             response = doGetObjectHandles();
             break;
+        case MTP_OPERATION_GET_NUM_OBJECTS:
+            response = doGetNumObjects();
+            break;
         case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
             response = doGetObjectPropValue();
             break;
@@ -454,6 +457,26 @@
     return MTP_RESPONSE_OK;
 }
 
+MtpResponseCode MtpServer::doGetNumObjects() {
+    if (!mSessionOpen)
+        return MTP_RESPONSE_SESSION_NOT_OPEN;
+    MtpStorageID storageID = mRequest.getParameter(1);      // 0xFFFFFFFF for all storage
+    MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats
+    MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent
+                                                            // 0x00000000 for all objects?
+    if (parent == 0xFFFFFFFF)
+        parent = 0;
+
+    int count = mDatabase->getNumObjects(storageID, format, parent);
+    if (count >= 0) {
+        mResponse.setParameter(1, count);
+        return MTP_RESPONSE_OK;
+    } else {
+        mResponse.setParameter(1, 0);
+        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    }
+}
+
 MtpResponseCode MtpServer::doGetObjectPropValue() {
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index aff973a..9ed1c84 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -94,6 +94,7 @@
     MtpResponseCode     doGetStorageInfo();
     MtpResponseCode     doGetObjectPropsSupported();
     MtpResponseCode     doGetObjectHandles();
+    MtpResponseCode     doGetNumObjects();
     MtpResponseCode     doGetObjectPropValue();
     MtpResponseCode     doGetObjectInfo();
     MtpResponseCode     doGetObject();