Merge "Refactor h.264 profile/level support into avc_utils."
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
deleted file mode 100644
index 4b44ccc..0000000
--- a/include/media/PVMediaRecorder.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- **
- ** Copyright 2008, 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.
- */
-
-#ifndef ANDROID_PVMEDIARECORDER_H
-#define ANDROID_PVMEDIARECORDER_H
-
-#include <media/IMediaRecorderClient.h>
-#include <media/MediaRecorderBase.h>
-
-namespace android {
-
-class Surface;
-class ICamera;
-class AuthorDriverWrapper;
-
-class PVMediaRecorder : public MediaRecorderBase {
-public:
-    PVMediaRecorder();
-    virtual ~PVMediaRecorder();
-
-    virtual status_t init();
-    virtual status_t setAudioSource(audio_source as);
-    virtual status_t setVideoSource(video_source vs);
-    virtual status_t setOutputFormat(output_format of);
-    virtual status_t setAudioEncoder(audio_encoder ae);
-    virtual status_t setVideoEncoder(video_encoder ve);
-    virtual status_t setVideoSize(int width, int height);
-    virtual status_t setVideoFrameRate(int frames_per_second);
-    virtual status_t setCamera(const sp<ICamera>& camera);
-    virtual status_t setPreviewSurface(const sp<Surface>& surface);
-    virtual status_t setOutputFile(const char *path);
-    virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
-    virtual status_t setParameters(const String8& params);
-    virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
-    virtual status_t prepare();
-    virtual status_t start();
-    virtual status_t stop();
-    virtual status_t close();
-    virtual status_t reset();
-    virtual status_t getMaxAmplitude(int *max);
-    virtual status_t dump(int fd, const Vector<String16>& args) const;
-
-private:
-    status_t doStop();
-
-    AuthorDriverWrapper*            mAuthorDriverWrapper;
-
-    PVMediaRecorder(const PVMediaRecorder &);
-    PVMediaRecorder &operator=(const PVMediaRecorder &);
-};
-
-}; // namespace android
-
-#endif // ANDROID_PVMEDIARECORDER_H
diff --git a/include/media/PVMetadataRetriever.h b/include/media/PVMetadataRetriever.h
deleted file mode 100644
index c202dfe..0000000
--- a/include/media/PVMetadataRetriever.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-**
-** Copyright (C) 2008 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.
-*/
-
-#ifndef ANDROID_PVMETADATARETRIEVER_H
-#define ANDROID_PVMETADATARETRIEVER_H
-
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-#include <private/media/VideoFrame.h>
-
-namespace android {
-
-class MetadataDriver;
-
-class PVMetadataRetriever : public MediaMetadataRetrieverInterface
-{
-public:
-                        PVMetadataRetriever();
-    virtual             ~PVMetadataRetriever();
-
-    virtual status_t    setDataSource(const char *url);
-    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setMode(int mode);
-    virtual status_t    getMode(int* mode) const;
-    virtual VideoFrame* captureFrame();
-    virtual MediaAlbumArt* extractAlbumArt();
-    virtual const char* extractMetadata(int keyCode);
-
-private:
-    mutable Mutex       mLock;
-    MetadataDriver*     mMetadataDriver;
-    char*               mDataSourcePath;
-};
-
-}; // namespace android
-
-#endif // ANDROID_PVMETADATARETRIEVER_H
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
deleted file mode 100644
index 657e7a6..0000000
--- a/include/media/PVPlayer.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#ifndef ANDROID_PVPLAYER_H
-#define ANDROID_PVPLAYER_H
-
-#include <utils/Errors.h>
-#include <media/MediaPlayerInterface.h>
-#include <media/Metadata.h>
-
-#define MAX_OPENCORE_INSTANCES 25
-
-#ifdef MAX_OPENCORE_INSTANCES
-#include <cutils/atomic.h>
-#endif
-
-class PlayerDriver;
-
-namespace android {
-
-class PVPlayer : public MediaPlayerInterface
-{
-public:
-                        PVPlayer();
-    virtual             ~PVPlayer();
-
-    virtual status_t    initCheck();
-
-    virtual status_t    setDataSource(
-            const char *url, const KeyedVector<String8, String8> *headers);
-
-    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoISurface(const sp<ISurface>& surface);
-    virtual status_t    setVideoSurface(const sp<Surface>& surface);
-    virtual status_t    prepare();
-    virtual status_t    prepareAsync();
-    virtual status_t    start();
-    virtual status_t    stop();
-    virtual status_t    pause();
-    virtual bool        isPlaying();
-    virtual status_t    seekTo(int msec);
-    virtual status_t    getCurrentPosition(int *msec);
-    virtual status_t    getDuration(int *msec);
-    virtual status_t    reset();
-    virtual status_t    setLooping(int loop);
-    virtual player_type playerType() { return PV_PLAYER; }
-    virtual status_t    invoke(const Parcel& request, Parcel *reply);
-    virtual status_t    getMetadata(
-        const SortedVector<media::Metadata::Type>& ids,
-        Parcel *records);
-
-    // make available to PlayerDriver
-    void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
-
-private:
-    static void         do_nothing(status_t s, void *cookie, bool cancelled) { }
-    static void         run_init(status_t s, void *cookie, bool cancelled);
-    static void         run_set_video_surface(status_t s, void *cookie, bool cancelled);
-    static void         run_set_audio_output(status_t s, void *cookie, bool cancelled);
-    static void         run_prepare(status_t s, void *cookie, bool cancelled);
-    static void         check_for_live_streaming(status_t s, void *cookie, bool cancelled);
-
-    PlayerDriver*               mPlayerDriver;
-    char *                      mDataSourcePath;
-    bool                        mIsDataSourceSet;
-    sp<ISurface>                mSurface;
-    int                         mSharedFd;
-    status_t                    mInit;
-    int                         mDuration;
-
-#ifdef MAX_OPENCORE_INSTANCES
-    static volatile int32_t     sNumInstances;
-#endif
-};
-
-}; // namespace android
-
-#endif // ANDROID_PVPLAYER_H
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 55846be..3341ff7 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -38,14 +38,6 @@
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_rtsp
 
-ifneq ($(BUILD_WITHOUT_PV),true)
-LOCAL_SHARED_LIBRARIES += \
-	libopencore_player    \
-	libopencore_author
-else
-LOCAL_CFLAGS += -DNO_OPENCORE
-endif
-
 ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_SHARED_LIBRARIES += libdl
 endif
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index bb86e05..e84c2dc 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -56,7 +56,6 @@
 #include "MetadataRetrieverClient.h"
 
 #include "MidiFile.h"
-#include <media/PVPlayer.h>
 #include "TestPlayerStub.h"
 #include "StagefrightPlayer.h"
 
@@ -196,11 +195,6 @@
         {".rtttl", SONIVOX_PLAYER},
         {".rtx", SONIVOX_PLAYER},
         {".ota", SONIVOX_PLAYER},
-#ifndef NO_OPENCORE
-        {".wma", PV_PLAYER},
-        {".wmv", PV_PLAYER},
-        {".asf", PV_PLAYER},
-#endif
 };
 
 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
@@ -691,14 +685,6 @@
     if (ident == 0x5367674f) // 'OggS'
         return STAGEFRIGHT_PLAYER;
 
-#ifndef NO_OPENCORE
-    if (ident == 0x75b22630) {
-        // The magic number for .asf files, i.e. wmv and wma content.
-        // These are not currently supported through stagefright.
-        return PV_PLAYER;
-    }
-#endif
-
     // Some kind of MIDI?
     EAS_DATA_HANDLE easdata;
     if (EAS_Init(&easdata) == EAS_SUCCESS) {
@@ -737,16 +723,6 @@
         }
     }
 
-    if (!strncasecmp(url, "rtsp://", 7)) {
-        char value[PROPERTY_VALUE_MAX];
-        if (property_get("media.stagefright.enable-rtsp", value, NULL)
-            && (strcmp(value, "1") && strcasecmp(value, "true"))) {
-            // For now, we're going to use PV for rtsp-based playback
-            // by default until we can clear up a few more issues.
-            return PV_PLAYER;
-        }
-    }
-
     return getDefaultPlayerType();
 }
 
@@ -755,12 +731,6 @@
 {
     sp<MediaPlayerBase> p;
     switch (playerType) {
-#ifndef NO_OPENCORE
-        case PV_PLAYER:
-            LOGV(" create PVPlayer");
-            p = new PVPlayer();
-            break;
-#endif
         case SONIVOX_PLAYER:
             LOGV(" create MidiFile");
             p = new MidiFile();
@@ -773,6 +743,9 @@
             LOGV("Create Test Player stub");
             p = new TestPlayerStub();
             break;
+        default:
+            LOGE("Unknown player type: %d", playerType);
+            return NULL;
     }
     if (p != NULL) {
         if (p->initCheck() == NO_ERROR) {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index be6a8be..1a1780c 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -31,10 +31,6 @@
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
 
-#ifndef NO_OPENCORE
-#include <media/PVMediaRecorder.h>
-#endif
-
 #include <utils/String16.h>
 
 #include <media/AudioTrack.h>
@@ -304,22 +300,7 @@
 {
     LOGV("Client constructor");
     mPid = pid;
-
-    char value[PROPERTY_VALUE_MAX];
-    if (!property_get("media.stagefright.enable-record", value, NULL)
-        || !strcmp(value, "1") || !strcasecmp(value, "true")) {
-        mRecorder = new StagefrightRecorder;
-    } else
-#ifndef NO_OPENCORE
-    {
-        mRecorder = new PVMediaRecorder();
-    }
-#else
-    {
-        mRecorder = NULL;
-    }
-#endif
-
+    mRecorder = new StagefrightRecorder;
     mMediaPlayerService = service;
 }
 
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 39fce81..b069345 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -35,7 +35,6 @@
 #include <binder/IServiceManager.h>
 #include <media/MediaMetadataRetrieverInterface.h>
 #include <media/MediaPlayerInterface.h>
-#include <media/PVMetadataRetriever.h>
 #include <private/media/VideoFrame.h>
 #include "MidiMetadataRetriever.h"
 #include "MetadataRetrieverClient.h"
@@ -107,12 +106,6 @@
             p = new StagefrightMetadataRetriever;
             break;
         }
-#ifndef NO_OPENCORE
-        case PV_PLAYER:
-            LOGV("create pv metadata retriever");
-            p = new PVMetadataRetriever();
-            break;
-#endif
         case SONIVOX_PLAYER:
             LOGV("create midi metadata retriever");
             p = new MidiMetadataRetriever();
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 7aac447..133f225 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -5,6 +5,7 @@
 #include "include/NuHTTPDataSource.h"
 
 #include <cutils/properties.h>
+#include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaErrors.h>
 
@@ -68,6 +69,9 @@
       mOffset(0),
       mContentLength(0),
       mContentLengthValid(false),
+      mNumBandwidthHistoryItems(0),
+      mTotalTransferTimeUs(0),
+      mTotalTransferBytes(0),
       mDecryptHandle(NULL),
       mDrmManagerClient(NULL) {
 }
@@ -189,6 +193,20 @@
             return ERROR_IO;
         }
 
+        {
+            string value;
+            if (mHTTP.find_header_value("Transfer-Encoding", &value)) {
+                // We don't currently support any transfer encodings.
+
+                mState = DISCONNECTED;
+                mHTTP.disconnect();
+
+                LOGE("We don't support '%s' transfer encoding.", value.c_str());
+
+                return ERROR_UNSUPPORTED;
+            }
+        }
+
         applyTimeoutResponse();
 
         if (offset == 0) {
@@ -254,6 +272,8 @@
 
     size_t numBytesRead = 0;
     while (numBytesRead < size) {
+        int64_t startTimeUs = ALooper::GetNowUs();
+
         ssize_t n =
             mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead);
 
@@ -261,6 +281,9 @@
             return n;
         }
 
+        int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+        addBandwidthMeasurement_l(n, delayUs);
+
         numBytesRead += (size_t)n;
 
         if (n == 0) {
@@ -345,6 +368,36 @@
     }
 }
 
+bool NuHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mNumBandwidthHistoryItems < 10) {
+        return false;
+    }
+
+    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+    return true;
+}
+
+void NuHTTPDataSource::addBandwidthMeasurement_l(
+        size_t numBytes, int64_t delayUs) {
+    BandwidthEntry entry;
+    entry.mDelayUs = delayUs;
+    entry.mNumBytes = numBytes;
+    mTotalTransferTimeUs += delayUs;
+    mTotalTransferBytes += numBytes;
+
+    mBandwidthHistory.push_back(entry);
+    if (++mNumBandwidthHistoryItems > 100) {
+        BandwidthEntry *entry = &*mBandwidthHistory.begin();
+        mTotalTransferTimeUs -= entry->mDelayUs;
+        mTotalTransferBytes -= entry->mNumBytes;
+        mBandwidthHistory.erase(mBandwidthHistory.begin());
+        --mNumBandwidthHistoryItems;
+    }
+}
+
 DecryptHandle* NuHTTPDataSource::DrmInitialization(DrmManagerClient* client) {
     if (client == NULL) {
         return NULL;
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 93b7a76..c707fdc 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -3,6 +3,7 @@
 #define NU_HTTP_DATA_SOURCE_H_
 
 #include <media/stagefright/DataSource.h>
+#include <utils/List.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 
@@ -26,6 +27,10 @@
     virtual status_t getSize(off_t *size);
     virtual uint32_t flags();
 
+    // Returns true if bandwidth could successfully be estimated,
+    // false otherwise.
+    bool estimateBandwidth(int32_t *bandwidth_bps);
+
     virtual DecryptHandle* DrmInitialization(DrmManagerClient *client);
     virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
 
@@ -39,6 +44,11 @@
         CONNECTED
     };
 
+    struct BandwidthEntry {
+        int64_t mDelayUs;
+        size_t mNumBytes;
+    };
+
     Mutex mLock;
 
     State mState;
@@ -54,6 +64,11 @@
     off_t mContentLength;
     bool mContentLengthValid;
 
+    List<BandwidthEntry> mBandwidthHistory;
+    size_t mNumBandwidthHistoryItems;
+    int64_t mTotalTransferTimeUs;
+    size_t mTotalTransferBytes;
+
     DecryptHandle *mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
 
@@ -66,6 +81,7 @@
             off_t offset);
 
     void applyTimeoutResponse();
+    void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
 
     static void MakeFullHeaders(
             const KeyedVector<String8, String8> *overrides,
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index c8cb016..fafd221 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -75,6 +75,12 @@
 
     virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property) = 0;
 
+    virtual MtpResponseCode         getObjectPropertyList(MtpObjectHandle handle,
+                                            MtpObjectFormat format,
+                                            MtpObjectProperty property,
+                                            int groupCode, int depth,
+                                            MtpDataPacket& packet) = 0;
+
     virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
                                             MtpDataPacket& packet) = 0;
 
diff --git a/media/mtp/MtpDebug.cpp b/media/mtp/MtpDebug.cpp
index 3416807..1668ecf 100644
--- a/media/mtp/MtpDebug.cpp
+++ b/media/mtp/MtpDebug.cpp
@@ -56,6 +56,10 @@
     { "MTP_OPERATION_GET_OBJECT_PROP_DESC",         0x9802 },
     { "MTP_OPERATION_GET_OBJECT_PROP_VALUE",        0x9803 },
     { "MTP_OPERATION_SET_OBJECT_PROP_VALUE",        0x9804 },
+    { "MTP_OPERATION_GET_OBJECT_PROP_LIST",         0x9805 },
+    { "MTP_OPERATION_SET_OBJECT_PROP_LIST",         0x9806 },
+    { "MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC", 0x9807 },
+    { "MTP_OPERATION_SEND_OBJECT_PROP_LIST",        0x9808 },
     { "MTP_OPERATION_GET_OBJECT_REFERENCES",        0x9810 },
     { "MTP_OPERATION_SET_OBJECT_REFERENCES",        0x9811 },
     { "MTP_OPERATION_SKIP",                         0x9820 },
@@ -371,15 +375,21 @@
     return getCodeName(code, sOperationCodes);
 }
 
-const char* MtpDebug::getFormatCodeName(MtpOperationCode code) {
+const char* MtpDebug::getFormatCodeName(MtpObjectFormat code) {
+    if (code == 0)
+        return "NONE";
     return getCodeName(code, sFormatCodes);
 }
 
 const char* MtpDebug::getObjectPropCodeName(MtpPropertyCode code) {
+    if (code == 0)
+        return "NONE";
     return getCodeName(code, sObjectPropCodes);
 }
 
 const char* MtpDebug::getDevicePropCodeName(MtpPropertyCode code) {
+    if (code == 0)
+        return "NONE";
     return getCodeName(code, sDevicePropCodes);
 }
 
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index f7c12d6..86889c3 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -53,7 +53,7 @@
         mDefaultArrayValues(NULL),
         mCurrentArrayLength(0),
         mCurrentArrayValues(NULL),
-        mGroupCode(0),
+        mGroupCode(-1), // disable multiple properties in GetObjectPropList for now
         mFormFlag(kFormNone),
         mEnumLength(0),
         mEnumValues(NULL)
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 5ba6be9..6cf70ec 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -72,6 +72,10 @@
     MTP_OPERATION_GET_OBJECT_PROP_DESC,
     MTP_OPERATION_GET_OBJECT_PROP_VALUE,
     MTP_OPERATION_SET_OBJECT_PROP_VALUE,
+    MTP_OPERATION_GET_OBJECT_PROP_LIST,
+//    MTP_OPERATION_SET_OBJECT_PROP_LIST,
+//    MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
+//    MTP_OPERATION_SEND_OBJECT_PROP_LIST,
     MTP_OPERATION_GET_OBJECT_REFERENCES,
     MTP_OPERATION_SET_OBJECT_REFERENCES,
 //    MTP_OPERATION_SKIP,
@@ -276,6 +280,9 @@
         case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
             response = doResetDevicePropValue();
             break;
+        case MTP_OPERATION_GET_OBJECT_PROP_LIST:
+            response = doGetObjectPropList();
+            break;
         case MTP_OPERATION_GET_OBJECT_INFO:
             response = doGetObjectInfo();
             break;
@@ -523,6 +530,20 @@
     return mDatabase->resetDeviceProperty(property);
 }
 
+MtpResponseCode MtpServer::doGetObjectPropList() {
+
+    MtpObjectHandle handle = mRequest.getParameter(1);
+    MtpObjectFormat format = mRequest.getParameter(2);
+    MtpDeviceProperty property = mRequest.getParameter(3);
+    int groupCode = mRequest.getParameter(4);
+    int depth = mRequest.getParameter(4);
+   LOGD("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n",
+            handle, MtpDebug::getFormatCodeName(format),
+            MtpDebug::getObjectPropCodeName(property), groupCode, depth);
+
+    return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
+}
+
 MtpResponseCode MtpServer::doGetObjectInfo() {
     MtpObjectHandle handle = mRequest.getParameter(1);
     return mDatabase->getObjectInfo(handle, mData);
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 68a6564..e65ddb0 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -93,6 +93,7 @@
     MtpResponseCode     doGetDevicePropValue();
     MtpResponseCode     doSetDevicePropValue();
     MtpResponseCode     doResetDevicePropValue();
+    MtpResponseCode     doGetObjectPropList();
     MtpResponseCode     doGetObjectInfo();
     MtpResponseCode     doGetObject();
     MtpResponseCode     doSendObjectInfo();
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index b7afa66..8bc2e22 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -37,7 +37,7 @@
 #define MTP_CONTAINER_PARAMETER_OFFSET          12
 #define MTP_CONTAINER_HEADER_SIZE               12
 
-// MTP Types
+// MTP Data Types
 #define MTP_TYPE_UNDEFINED      0x0000          // Undefined
 #define MTP_TYPE_INT8           0x0001          // Signed 8-bit integer
 #define MTP_TYPE_UINT8          0x0002          // Unsigned 8-bit integer
@@ -383,6 +383,10 @@
 #define MTP_OPERATION_GET_OBJECT_PROP_DESC                  0x9802
 #define MTP_OPERATION_GET_OBJECT_PROP_VALUE                 0x9803
 #define MTP_OPERATION_SET_OBJECT_PROP_VALUE                 0x9804
+#define MTP_OPERATION_GET_OBJECT_PROP_LIST                  0x9805
+#define MTP_OPERATION_SET_OBJECT_PROP_LIST                  0x9806
+#define MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC          0x9807
+#define MTP_OPERATION_SEND_OBJECT_PROP_LIST                 0x9808
 #define MTP_OPERATION_GET_OBJECT_REFERENCES                 0x9810
 #define MTP_OPERATION_SET_OBJECT_REFERENCES                 0x9811
 #define MTP_OPERATION_SKIP                                  0x9820