Added method to get metadata out of the player.

The method passes a list of metadata ids to be retrieved and
a parcel where the metadata records should be appended.

If the list of ids is empty, all the metadata should be returned.
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9102b40..97d55aa 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -29,7 +29,10 @@
 
 namespace android {
 
+typedef int32_t MetadataType;
+
 class Parcel;
+template<typename T> class SortedVector;
 
 enum player_type {
     PV_PLAYER = 1,
@@ -112,12 +115,23 @@
                             mCookie = cookie; mNotify = notifyFunc; }
     // Invoke a generic method on the player by using opaque parcels
     // for the request and reply.
+    //
     // @param request Parcel that is positioned at the start of the
     //                data sent by the java layer.
     // @param[out] reply Parcel to hold the reply data. Cannot be null.
-    // @return OK if the invocation was made successfully. A player
-    // not supporting the direct API should return INVALID_OPERATION.
+    // @return OK if the call was successful.
     virtual status_t    invoke(const Parcel& request, Parcel *reply) = 0;
+
+    // The Client in the MetadataPlayerService calls this method on
+    // the native player to retrieve all or a subset of metadata.
+    //
+    // @param ids SortedList of metadata ID to be fetch. If empty, all
+    //            the known metadata should be returned.
+    // @param[inout] records Parcel where the player appends its metadata.
+    // @return OK if the call was successful.
+    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
+                                    Parcel *records) = 0;
+
 protected:
     virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
 
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index d8a677f..40ccc14b 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -53,6 +53,8 @@
     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<MetadataType>& ids,
+                                    Parcel *records);
 
     // make available to PlayerDriver
     void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 02327d8..5e62f9d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -99,6 +99,8 @@
 // Keep in sync with ANY in Metadata.java
 const int32_t kAny = 0;
 
+const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
+
 
 // Unmarshall a filter from a Parcel.
 // Filter format in a parcel:
@@ -870,10 +872,14 @@
 status_t MediaPlayerService::Client::getMetadata(
         bool update_only, bool apply_filter, Parcel *reply)
 {
-    status_t status;
-    reply->writeInt32(-1);  // Placeholder for the return code
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
 
-    SortedVector<MetadataType> updates;
+    status_t status;
+    // Placeholder for the return code, updated by the caller.
+    reply->writeInt32(-1);
+
+    SortedVector<MetadataType> ids;
 
     // We don't block notifications while we fetch the data. We clear
     // mMetadataUpdated first so we don't lose notifications happening
@@ -881,15 +887,34 @@
     {
         Mutex::Autolock lock(mLock);
         if (update_only) {
-            updates = mMetadataUpdated;
+            ids = mMetadataUpdated;
         }
         mMetadataUpdated.clear();
     }
 
-    // FIXME: Implement, query the native player and do the optional filtering, etc...
-    status = OK;
+    const size_t begin = reply->dataPosition();
+    reply->writeInt32(-1);  // Placeholder for the length of the metadata
+    reply->writeInt32(kMetaMarker);
 
-    return status;
+    status = p->getMetadata(ids, reply);
+
+    if (status != OK) {
+        reply->setDataPosition(begin);
+        LOGE("getMetadata failed %d", status);
+        return status;
+    }
+
+    // FIXME: Implement filtering on the result. Not critical since
+    // filtering takes place on the update notifications already. This
+    // would be when all the metadata are fetch and a filter is set.
+
+    const size_t end = reply->dataPosition();
+
+    // Everything is fine, update the metadata length.
+    reply->setDataPosition(begin);
+    reply->writeInt32(end - begin);
+    reply->setDataPosition(end);
+    return OK;
 }
 
 status_t MediaPlayerService::Client::prepareAsync()
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 83d97fe..30b6a2e 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -46,7 +46,13 @@
     virtual status_t    reset();
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return SONIVOX_PLAYER; }
-    virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
+    virtual status_t    invoke(const Parcel& request, Parcel *reply) {
+        return INVALID_OPERATION;
+    }
+    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
+                                    Parcel *records)  {
+        return INVALID_OPERATION;
+    }
 
 private:
             status_t    createOutputTrack();
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 80d53a8..339b108 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -94,6 +94,10 @@
     virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
         return mPlayer->invoke(in, out);
     }
+    virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
+                                 Parcel *records) {
+        return INVALID_OPERATION;
+    }
 
 
     // @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
index 4024654..040eb36 100644
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -54,6 +54,10 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return VORBIS_PLAYER; }
     virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
+    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
+                                    Parcel *records)  {
+        return INVALID_OPERATION;
+    }
 
 private:
             status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index f02298d..8d575a3 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -20,14 +20,17 @@
 
 #include <string.h>
 
-#include "binder/Parcel.h"
-#include "media/MediaPlayerInterface.h"
-#include "utils/Errors.h"
+#include <binder/Parcel.h>
+#include <media/MediaPlayerInterface.h>
+#include <utils/Errors.h>
 
+using android::INVALID_OPERATION;
 using android::ISurface;
 using android::MediaPlayerBase;
+using android::MetadataType;
 using android::OK;
 using android::Parcel;
+using android::SortedVector;
 using android::TEST_PLAYER;
 using android::UNKNOWN_ERROR;
 using android::player_type;
@@ -75,6 +78,9 @@
     virtual status_t    setLooping(int loop) {return OK;}
     virtual player_type playerType() {return TEST_PLAYER;}
     virtual status_t    invoke(const Parcel& request, Parcel *reply);
+    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
+                                    Parcel *records) {return INVALID_OPERATION;}
+
   private:
     // Take a request, copy it to the reply.
     void ping(const Parcel& request, Parcel *reply);