Set metadata retriever thread group to the caller's group.

This patch modifies the native binder interface to the metadata
retriever to pass the caller's thread group across the binder
interface. On the server side, the thread scheduler group is
set to the caller's scheduler group temporarily and restored
after the request has completed. This patch also reverts a
previous patch where the priority of the thread was forced to
a low priority foreground thread.

This should give apps more control over the priority of their
metadata retrieval, particularly allow background process to
run without hogging the CPU.
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 397a55b..68dd880 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -21,6 +21,51 @@
 #include <SkBitmap.h>
 #include <media/IMediaMetadataRetriever.h>
 
+// The binder is supposed to propagate the scheduler group across
+// the binder interface so that remote calls are executed with
+// the same priority as local calls. This is currently not working
+// so this change puts in a temporary hack to fix the issue with
+// metadata retrieval which can be a huge CPU hit if done on a
+// foreground thread.
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+
+/* desktop Linux needs a little help with gettid() */
+#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
+#define __KERNEL__
+# include <linux/unistd.h>
+#ifdef _syscall0
+_syscall0(pid_t,gettid)
+#else
+pid_t gettid() { return syscall(__NR_gettid);}
+#endif
+#undef __KERNEL__
+#endif
+
+#define LOG_TAG "IMediaMetadataRetriever"
+#include <utils/Log.h>
+#include <cutils/sched_policy.h>
+
+namespace android {
+
+static void sendSchedPolicy(Parcel& data)
+{
+    SchedPolicy policy;
+    get_sched_policy(gettid(), &policy);
+    data.writeInt32(policy);
+}
+
+static void setSchedPolicy(const Parcel& data)
+{
+    SchedPolicy policy = (SchedPolicy) data.readInt32();
+    set_sched_policy(gettid(), policy);
+}
+static void restoreSchedPolicy()
+{
+    set_sched_policy(gettid(), SP_FOREGROUND);
+}
+}; // end namespace android
+#endif
+
 namespace android {
 
 enum {
@@ -30,7 +75,7 @@
     SET_MODE,
     GET_MODE,
     CAPTURE_FRAME,
-    EXTARCT_ALBUM_ART,
+    EXTRACT_ALBUM_ART,
     EXTRACT_METADATA,
 };
 
@@ -92,6 +137,9 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+        sendSchedPolicy(data);
+#endif
         remote()->transact(CAPTURE_FRAME, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -104,7 +152,10 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-        remote()->transact(EXTARCT_ALBUM_ART, data, &reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+        sendSchedPolicy(data);
+#endif
+        remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
             return NULL;
@@ -116,6 +167,9 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+        sendSchedPolicy(data);
+#endif
         data.writeInt32(keyCode);
         remote()->transact(EXTRACT_METADATA, data, &reply);
         status_t ret = reply.readInt32();
@@ -169,6 +223,9 @@
         } break;
         case CAPTURE_FRAME: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            setSchedPolicy(data);
+#endif
             sp<IMemory> bitmap = captureFrame();
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -176,10 +233,16 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            restoreSchedPolicy();
+#endif
             return NO_ERROR;
         } break;
-        case EXTARCT_ALBUM_ART: {
+        case EXTRACT_ALBUM_ART: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            setSchedPolicy(data);
+#endif
             sp<IMemory> albumArt = extractAlbumArt();
             if (albumArt != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -187,10 +250,16 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            restoreSchedPolicy();
+#endif
             return NO_ERROR;
         } break;
         case EXTRACT_METADATA: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            setSchedPolicy(data);
+#endif
             int keyCode = data.readInt32();
             const char* value = extractMetadata(keyCode);
             if (value != NULL) {  // Don't send NULL across the binder interface
@@ -199,6 +268,9 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+            restoreSchedPolicy();
+#endif
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 2cdc351..d51ce66 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -237,7 +237,6 @@
 {
     LOGV("captureFrame");
     Mutex::Autolock lock(mLock);
-    Priority priority(ANDROID_PRIORITY_BACKGROUND);
     mThumbnail.clear();
     mThumbnailDealer.clear();
     if (mRetriever == NULL) {
@@ -279,7 +278,6 @@
 {
     LOGV("extractAlbumArt");
     Mutex::Autolock lock(mLock);
-    Priority priority(ANDROID_PRIORITY_BACKGROUND);
     mAlbumArt.clear();
     mAlbumArtDealer.clear();
     if (mRetriever == NULL) {
@@ -321,19 +319,7 @@
         LOGE("retriever is not initialized");
         return NULL;
     }
-    Priority priority(ANDROID_PRIORITY_BACKGROUND);
     return mRetriever->extractMetadata(keyCode);
 }
 
-MetadataRetrieverClient::Priority::Priority(int newPriority)
-{
-    mOldPriority = getpriority(PRIO_PROCESS, 0);
-    setpriority(PRIO_PROCESS, 0, newPriority);
-}
-
-MetadataRetrieverClient::Priority::~Priority()
-{
-    setpriority(PRIO_PROCESS, 0, mOldPriority);
-}
-
 }; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 852d734..8cb8ad1 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -54,16 +54,6 @@
 private:
     friend class MediaPlayerService;
 
-    class Priority
-    {
-    public:
-        Priority(int newPriority);
-        ~Priority();
-    private:
-        Priority();
-        int         mOldPriority;
-    };
-
     explicit MetadataRetrieverClient(pid_t pid);
     virtual ~MetadataRetrieverClient();