Merge "HDCP: buffer over flow check" into mnc-dev
diff --git a/include/media/IResourceManagerClient.h b/include/media/IResourceManagerClient.h
index 3587aea..aa0cd88 100644
--- a/include/media/IResourceManagerClient.h
+++ b/include/media/IResourceManagerClient.h
@@ -18,6 +18,7 @@
 #define ANDROID_IRESOURCEMANAGERCLIENT_H
 
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 
@@ -29,6 +30,7 @@
     DECLARE_META_INTERFACE(ResourceManagerClient);
 
     virtual bool reclaimResource() = 0;
+    virtual String8 getName() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaResource.h b/include/media/MediaResource.h
index 0b57c84..20f2cad 100644
--- a/include/media/MediaResource.h
+++ b/include/media/MediaResource.h
@@ -25,6 +25,8 @@
 
 extern const char kResourceSecureCodec[];
 extern const char kResourceNonSecureCodec[];
+extern const char kResourceAudioCodec[];
+extern const char kResourceVideoCodec[];
 extern const char kResourceGraphicMemory[];
 
 class MediaResource {
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index a8d0fcb..c14e6c0 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -192,6 +192,7 @@
     List<sp<AMessage> > mDeferredQueue;
 
     bool mSentFormat;
+    bool mIsVideo;
     bool mIsEncoder;
     bool mUseMetadataOnEncoderOutput;
     bool mShutdownInProgress;
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index f2b21c9..d89e4c7 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -351,7 +351,7 @@
     bool isExecuting() const;
 
     uint64_t getGraphicBufferSize();
-    void addResource(const char *type, uint64_t value);
+    void addResource(const String8 &type, const String8 &subtype, uint64_t value);
 
     /* called to get the last codec error when the sticky flag is set.
      * if no such codec error is found, returns UNKNOWN_ERROR.
diff --git a/media/libmedia/IResourceManagerClient.cpp b/media/libmedia/IResourceManagerClient.cpp
index 6fa56fc..b3f56e8 100644
--- a/media/libmedia/IResourceManagerClient.cpp
+++ b/media/libmedia/IResourceManagerClient.cpp
@@ -25,6 +25,7 @@
 
 enum {
     RECLAIM_RESOURCE = IBinder::FIRST_CALL_TRANSACTION,
+    GET_NAME,
 };
 
 class BpResourceManagerClient: public BpInterface<IResourceManagerClient>
@@ -46,6 +47,19 @@
         }
         return ret;
     }
+
+    virtual String8 getName() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IResourceManagerClient::getInterfaceDescriptor());
+
+        String8 ret;
+        status_t status = remote()->transact(GET_NAME, data, &reply);
+        if (status == NO_ERROR) {
+            ret = reply.readString8();
+        }
+        return ret;
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(ResourceManagerClient, "android.media.IResourceManagerClient");
@@ -62,6 +76,12 @@
             reply->writeInt32(ret);
             return NO_ERROR;
         } break;
+        case GET_NAME: {
+            CHECK_INTERFACE(IResourceManagerClient, data, reply);
+            String8 ret = getName();
+            reply->writeString8(ret);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/MediaResource.cpp b/media/libmedia/MediaResource.cpp
index eea2c43..40ec0cb 100644
--- a/media/libmedia/MediaResource.cpp
+++ b/media/libmedia/MediaResource.cpp
@@ -23,6 +23,8 @@
 
 const char kResourceSecureCodec[] = "secure-codec";
 const char kResourceNonSecureCodec[] = "non-secure-codec";
+const char kResourceAudioCodec[] = "audio-codec";
+const char kResourceVideoCodec[] = "video-codec";
 const char kResourceGraphicMemory[] = "graphic-memory";
 
 MediaResource::MediaResource() : mValue(0) {}
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index 8ca8769..d55482d 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -52,6 +52,7 @@
 KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
 KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
 Mutex Drm::mMapLock;
+Mutex Drm::mLock;
 
 static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
     if (lhs.size() < rhs.size()) {
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index c4013b8..056723c 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -143,7 +143,7 @@
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
 private:
-    mutable Mutex mLock;
+    static Mutex mLock;
 
     status_t mInitCheck;
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index a028b01..b670d68 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -634,6 +634,17 @@
             if (mRenderer != NULL) {
                 mRenderer->setPlaybackRate(mPlaybackRate);
             }
+
+            if (mVideoDecoder != NULL) {
+                sp<MetaData> meta = getFileMeta();
+                int32_t rate;
+                if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
+                    sp<AMessage> params = new AMessage();
+                    params->setFloat("operating-rate", rate * mPlaybackRate);
+                    mVideoDecoder->setParameters(params);
+                }
+            }
+
             break;
         }
 
@@ -1249,6 +1260,8 @@
         return -EWOULDBLOCK;
     }
 
+    format->setInt32("priority", 0 /* realtime */);
+
     if (!audio) {
         AString mime;
         CHECK(format->findString("mime", &mime));
@@ -1265,6 +1278,12 @@
         if (mSourceFlags & Source::FLAG_PROTECTED) {
             format->setInt32("protected", true);
         }
+
+        sp<MetaData> meta = getFileMeta();
+        int32_t rate;
+        if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
+            format->setFloat("operating-rate", rate * mPlaybackRate);
+        }
     }
 
     if (audio) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index acc9ef5..3c4d695 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -252,6 +252,14 @@
     mResumePending = false;
 }
 
+void NuPlayer::Decoder::onSetParameters(const sp<AMessage> &params) {
+    if (mCodec == NULL) {
+        ALOGW("onSetParameters called before codec is created.");
+        return;
+    }
+    mCodec->setParameters(params);
+}
+
 void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
     bool hadNoRenderer = (mRenderer == NULL);
     mRenderer = renderer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 9f0ef1b5..dd84620 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -40,6 +40,7 @@
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
     virtual void onConfigure(const sp<AMessage> &format);
+    virtual void onSetParameters(const sp<AMessage> &params);
     virtual void onSetRenderer(const sp<Renderer> &renderer);
     virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
     virtual void onResume(bool notifyComplete);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
index 36b41ec..9d509bf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -70,6 +70,12 @@
     mDecoderLooper->registerHandler(this);
 }
 
+void NuPlayer::DecoderBase::setParameters(const sp<AMessage> &params) {
+    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
+    msg->setMessage("params", params);
+    msg->post();
+}
+
 void NuPlayer::DecoderBase::setRenderer(const sp<Renderer> &renderer) {
     sp<AMessage> msg = new AMessage(kWhatSetRenderer, this);
     msg->setObject("renderer", renderer);
@@ -123,6 +129,14 @@
             break;
         }
 
+        case kWhatSetParameters:
+        {
+            sp<AMessage> params;
+            CHECK(msg->findMessage("params", &params));
+            onSetParameters(params);
+            break;
+        }
+
         case kWhatSetRenderer:
         {
             sp<RefBase> obj;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
index 262f5d5..b52e7f7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -33,6 +33,7 @@
 
     void configure(const sp<AMessage> &format);
     void init();
+    void setParameters(const sp<AMessage> &params);
 
     void setRenderer(const sp<Renderer> &renderer);
 
@@ -62,6 +63,7 @@
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
     virtual void onConfigure(const sp<AMessage> &format) = 0;
+    virtual void onSetParameters(const sp<AMessage> &params) = 0;
     virtual void onSetRenderer(const sp<Renderer> &renderer) = 0;
     virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers) = 0;
     virtual void onResume(bool notifyComplete) = 0;
@@ -78,6 +80,7 @@
 private:
     enum {
         kWhatConfigure           = 'conf',
+        kWhatSetParameters       = 'setP',
         kWhatSetRenderer         = 'setR',
         kWhatGetInputBuffers     = 'gInB',
         kWhatRequestInputBuffers = 'reqB',
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index fdb9039..d7b070e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -88,6 +88,10 @@
     }
 }
 
+void NuPlayer::DecoderPassThrough::onSetParameters(const sp<AMessage> &/*params*/) {
+    ALOGW("onSetParameters() called unexpectedly");
+}
+
 void NuPlayer::DecoderPassThrough::onSetRenderer(
         const sp<Renderer> &renderer) {
     // renderer can't be changed during offloading
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index b7dcb8d..2f6df2c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -40,6 +40,7 @@
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
     virtual void onConfigure(const sp<AMessage> &format);
+    virtual void onSetParameters(const sp<AMessage> &params);
     virtual void onSetRenderer(const sp<Renderer> &renderer);
     virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
     virtual void onResume(bool notifyComplete);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index da22f11..c7df5a0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -405,6 +405,7 @@
     : mQuirks(0),
       mNode(0),
       mSentFormat(false),
+      mIsVideo(false),
       mIsEncoder(false),
       mUseMetadataOnEncoderOutput(false),
       mShutdownInProgress(false),
@@ -1186,6 +1187,7 @@
 
     mIsEncoder = encoder;
 
+
     status_t err = setComponentRole(encoder /* isEncoder */, mime);
 
     if (err != OK) {
@@ -1244,6 +1246,7 @@
     // sps/pps to idr frames, since in metadata mode the bitstream is in an
     // opaque handle, to which we don't have access.
     int32_t video = !strncasecmp(mime, "video/", 6);
+    mIsVideo = video;
     if (encoder && video) {
         OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
             && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
@@ -5684,6 +5687,15 @@
         }
     }
 
+    float rate;
+    if (params->findFloat("operating-rate", &rate) && rate > 0) {
+        status_t err = setOperatingRate(rate, mIsVideo);
+        if (err != OK) {
+            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
+            return err;
+        }
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 96b22c0..aa0d2e6 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -79,6 +79,21 @@
         return (err == OK);
     }
 
+    virtual String8 getName() {
+        String8 ret;
+        sp<MediaCodec> codec = mMediaCodec.promote();
+        if (codec == NULL) {
+            // codec is already gone.
+            return ret;
+        }
+
+        AString name;
+        if (codec->getName(&name) == OK) {
+            ret.setTo(name.c_str());
+        }
+        return ret;
+    }
+
 protected:
     virtual ~ResourceManagerClient() {}
 
@@ -419,7 +434,8 @@
     status_t err;
     Vector<MediaResource> resources;
     const char *type = secureCodec ? kResourceSecureCodec : kResourceNonSecureCodec;
-    resources.push_back(MediaResource(String8(type), 1));
+    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
+    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
     for (int i = 0; i <= kMaxRetry; ++i) {
         if (i > 0) {
             // Don't try to reclaim resource for the first time.
@@ -477,7 +493,8 @@
     Vector<MediaResource> resources;
     const char *type = (mFlags & kFlagIsSecure) ?
             kResourceSecureCodec : kResourceNonSecureCodec;
-    resources.push_back(MediaResource(String8(type), 1));
+    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
+    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
     // Don't know the buffer size at this point, but it's fine to use 1 because
     // the reclaimResource call doesn't consider the requester's buffer size for now.
     resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
@@ -542,9 +559,9 @@
     return size;
 }
 
-void MediaCodec::addResource(const char *type, uint64_t value) {
+void MediaCodec::addResource(const String8 &type, const String8 &subtype, uint64_t value) {
     Vector<MediaResource> resources;
-    resources.push_back(MediaResource(String8(type), value));
+    resources.push_back(MediaResource(type, subtype, value));
     mResourceManagerService->addResource(
             getCallingPid(), getId(mResourceManagerClient), mResourceManagerClient, resources);
 }
@@ -556,7 +573,8 @@
     Vector<MediaResource> resources;
     const char *type = (mFlags & kFlagIsSecure) ?
             kResourceSecureCodec : kResourceNonSecureCodec;
-    resources.push_back(MediaResource(String8(type), 1));
+    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
+    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
     // Don't know the buffer size at this point, but it's fine to use 1 because
     // the reclaimResource call doesn't consider the requester's buffer size for now.
     resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
@@ -1168,7 +1186,9 @@
                         mFlags &= ~kFlagIsSecure;
                         resourceType = String8(kResourceNonSecureCodec);
                     }
-                    addResource(resourceType, 1);
+
+                    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
+                    addResource(resourceType, String8(subtype), 1);
 
                     (new AMessage)->postReply(mReplyID);
                     break;
@@ -1282,7 +1302,11 @@
                             // allocating input buffers, so this is a good
                             // indication that now all buffers are allocated.
                             if (mIsVideo) {
-                                addResource(kResourceGraphicMemory, getGraphicBufferSize());
+                                String8 subtype;
+                                addResource(
+                                        String8(kResourceGraphicMemory),
+                                        subtype,
+                                        getGraphicBufferSize());
                             }
                             setState(STARTED);
                             (new AMessage)->postReply(mReplyID);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 0712bf0..ddca437 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -941,7 +941,10 @@
                 const mkvparser::VideoTrack *vtrack =
                     static_cast<const mkvparser::VideoTrack *>(track);
 
-                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
+                if (codecID == NULL) {
+                    ALOGW("unknown codecID is not supported.");
+                    continue;
+                } else if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
                     meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
                 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 01f2b61..ba3fcaf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1420,6 +1420,13 @@
     }
 
     if (inputDesc->mRefCount == 0) {
+        // if input maps to a dynamic policy with an activity listener, notify of state change
+        if ((inputDesc->mPolicyMix != NULL)
+                && ((inputDesc->mPolicyMix->mFlags & MIX_FLAG_NOTIFY_ACTIVITY) != 0)) {
+            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+                    MIX_STATE_MIXING);
+        }
+
         if (mInputs.activeInputsCount() == 0) {
             SoundTrigger::setCaptureState(true);
         }
@@ -1473,6 +1480,12 @@
 
     inputDesc->mRefCount--;
     if (inputDesc->mRefCount == 0) {
+        // if input maps to a dynamic policy with an activity listener, notify of state change
+        if ((inputDesc->mPolicyMix != NULL)
+                && ((inputDesc->mPolicyMix->mFlags & MIX_FLAG_NOTIFY_ACTIVITY) != 0)) {
+            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+                    MIX_STATE_IDLE);
+        }
 
         // automatically disable the remote submix output when input is stopped if not
         // used by a policy mix of type MIX_TYPE_RECORDERS
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 75a69ed..17aac4e 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -88,6 +88,51 @@
     return infos.editItemAt(infos.size() - 1);
 }
 
+status_t ResourceManagerService::dump(int fd, const Vector<String16>& args) {
+    Mutex::Autolock lock(mLock);
+
+    String8 result;
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
+    result.append(buffer);
+    result.append("  Policies:\n");
+    snprintf(buffer, SIZE, "    SupportsMultipleSecureCodecs: %d\n", mSupportsMultipleSecureCodecs);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "    SupportsSecureWithNonSecureCodec: %d\n", mSupportsSecureWithNonSecureCodec);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "  Processes:\n");
+    result.append(buffer);
+    for (size_t i = 0; i < mMap.size(); ++i) {
+        snprintf(buffer, SIZE, "    Pid: %d\n", mMap.keyAt(i));
+        result.append(buffer);
+
+        const ResourceInfos &infos = mMap.valueAt(i);
+        for (size_t j = 0; j < infos.size(); ++j) {
+            snprintf(buffer, SIZE, "      Client:\n");
+            result.append(buffer);
+            snprintf(buffer, SIZE, "        Id: %lld\n", (long long)infos[j].clientId);
+            result.append(buffer);
+
+            snprintf(buffer, SIZE, "        Name: %s\n", infos[j].client->getName().string());
+            result.append(buffer);
+
+            Vector<MediaResource> resources = infos[j].resources;
+            snprintf(buffer, SIZE, "        Resources:\n");
+            result.append(buffer);
+            for (size_t k = 0; k < resources.size(); ++k) {
+                snprintf(buffer, SIZE, "          %s\n", resources[k].toString().string());
+                result.append(buffer);
+            }
+        }
+    }
+
+    write(fd, result.string(), result.size());
+    return OK;
+}
+
 ResourceManagerService::ResourceManagerService()
     : mProcessInfo(new ProcessInfo()),
       mSupportsMultipleSecureCodecs(true),
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index 2ed9bf8..0c3d694 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -48,6 +48,8 @@
 public:
     static char const *getServiceName() { return "media.resource_manager"; }
 
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
     ResourceManagerService();
     ResourceManagerService(sp<ProcessInfoInterface> processInfo);
 
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 48d1395..bccc7fa 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -55,6 +55,10 @@
         return true;
     }
 
+    virtual String8 getName() {
+        return String8("test_client");
+    }
+
     bool reclaimed() const {
         return mReclaimed;
     }