Merge "Restore audio tee sink" into nyc-dev
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
index 2539ed3..168ceed 100644
--- a/include/media/ExtendedAudioBufferProvider.h
+++ b/include/media/ExtendedAudioBufferProvider.h
@@ -27,11 +27,11 @@
     virtual size_t  framesReady() const = 0;  // see description at AudioFlinger.h
 
     // Return the total number of frames that have been obtained and released
-    virtual size_t  framesReleased() const { return 0; }
+    virtual int64_t  framesReleased() const { return 0; }
 
     // Invoked by buffer consumer when a new timestamp is available.
     // Default implementation ignores the timestamp.
-    virtual void    onTimestamp(const AudioTimestamp& timestamp) { }
+    virtual void    onTimestamp(const ExtendedTimestamp& timestamp) { }
 };
 
 }   // namespace android
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index d6db67a..3f211bf 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -59,6 +59,7 @@
 
     virtual status_t allocateNode(
             const char *name, const sp<IOMXObserver> &observer,
+            sp<IBinder> *nodeBinder,
             node_id *node) = 0;
 
     virtual status_t freeNode(node_id node) = 0;
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
index eaea63c..a6e7992 100644
--- a/include/media/nbaio/AudioStreamInSource.h
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -38,8 +38,8 @@
     // NBAIO_Sink interface
 
     //virtual size_t framesRead() const;
-    virtual size_t framesOverrun();
-    virtual size_t overruns() { (void) framesOverrun(); return mOverruns; }
+    virtual int64_t framesOverrun();
+    virtual int64_t overruns() { (void) framesOverrun(); return mOverruns; }
 
     // This is an over-estimate, and could dupe the caller into making a blocking read()
     // FIXME Use an audio HAL API to query the buffer filling status when it's available.
@@ -56,8 +56,8 @@
 private:
     audio_stream_in * const mStream;
     size_t              mStreamBufferSizeBytes; // as reported by get_buffer_size()
-    size_t              mFramesOverrun;
-    size_t              mOverruns;
+    int64_t             mFramesOverrun;
+    int64_t             mOverruns;
 };
 
 }   // namespace android
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index 0998d45..e86b018 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -47,7 +47,7 @@
 
     virtual ssize_t write(const void *buffer, size_t count);
 
-    virtual status_t getTimestamp(AudioTimestamp& timestamp);
+    virtual status_t getTimestamp(ExtendedTimestamp &timestamp);
 
     // NBAIO_Sink end
 
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
index df9cafe..d2cd218 100644
--- a/include/media/nbaio/MonoPipe.h
+++ b/include/media/nbaio/MonoPipe.h
@@ -23,7 +23,7 @@
 
 namespace android {
 
-typedef SingleStateQueue<AudioTimestamp> AudioTimestampSingleStateQueue;
+typedef SingleStateQueue<ExtendedTimestamp> ExtendedTimestampSingleStateQueue;
 
 // MonoPipe is similar to Pipe except:
 //  - supports only a single reader, called MonoPipeReader
@@ -51,9 +51,9 @@
 
     // NBAIO_Sink interface
 
-    //virtual size_t framesWritten() const;
-    //virtual size_t framesUnderrun() const;
-    //virtual size_t underruns() const;
+    //virtual int64_t framesWritten() const;
+    //virtual int64_t framesUnderrun() const;
+    //virtual int64_t underruns() const;
 
     virtual ssize_t availableToWrite() const;
     virtual ssize_t write(const void *buffer, size_t count);
@@ -77,7 +77,7 @@
             bool    isShutdown();
 
             // Return NO_ERROR if there is a timestamp available
-            status_t getTimestamp(AudioTimestamp& timestamp);
+            status_t getTimestamp(ExtendedTimestamp &timestamp);
 
 private:
     const size_t    mReqFrames;     // as requested in constructor, unrounded
@@ -97,9 +97,9 @@
 
     bool            mIsShutdown;    // whether shutdown(true) was called, no barriers are needed
 
-    AudioTimestampSingleStateQueue::Shared      mTimestampShared;
-    AudioTimestampSingleStateQueue::Mutator     mTimestampMutator;
-    AudioTimestampSingleStateQueue::Observer    mTimestampObserver;
+    ExtendedTimestampSingleStateQueue::Shared      mTimestampShared;
+    ExtendedTimestampSingleStateQueue::Mutator     mTimestampMutator;
+    ExtendedTimestampSingleStateQueue::Observer    mTimestampObserver;
 };
 
 }   // namespace android
diff --git a/include/media/nbaio/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
index 4a7c3c5..b3c891d 100644
--- a/include/media/nbaio/MonoPipeReader.h
+++ b/include/media/nbaio/MonoPipeReader.h
@@ -49,7 +49,7 @@
 
     virtual ssize_t read(void *buffer, size_t count);
 
-    virtual void    onTimestamp(const AudioTimestamp& timestamp);
+    virtual void    onTimestamp(const ExtendedTimestamp &timestamp);
 
     // NBAIO_Source end
 
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index 2f7e291..120de4f 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -145,13 +145,13 @@
     // 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically.
 
     // Return the number of frames written successfully since construction.
-    virtual size_t framesWritten() const { return mFramesWritten; }
+    virtual int64_t framesWritten() const { return mFramesWritten; }
 
     // Number of frames lost due to underrun since construction.
-    virtual size_t framesUnderrun() const { return 0; }
+    virtual int64_t framesUnderrun() const { return 0; }
 
     // Number of underruns since construction, where a set of contiguous lost frames is one event.
-    virtual size_t underruns() const { return 0; }
+    virtual int64_t underruns() const { return 0; }
 
     // Estimate of number of frames that could be written successfully now without blocking.
     // When a write() is actually attempted, the implementation is permitted to return a smaller or
@@ -212,7 +212,7 @@
     // Returns NO_ERROR if a timestamp is available.  The timestamp includes the total number
     // of frames presented to an external observer, together with the value of CLOCK_MONOTONIC
     // as of this presentation count.  The timestamp parameter is undefined if error is returned.
-    virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; }
+    virtual status_t getTimestamp(ExtendedTimestamp &timestamp) { return INVALID_OPERATION; }
 
 protected:
     NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0)
@@ -220,7 +220,7 @@
     virtual ~NBAIO_Sink() { }
 
     // Implementations are free to ignore these if they don't need them
-    size_t  mFramesWritten;
+    int64_t  mFramesWritten;
 };
 
 // Abstract class (interface) representing a non-blocking data source, for use by a data consumer.
@@ -232,15 +232,15 @@
     // 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically.
 
     // Number of frames read successfully since construction.
-    virtual size_t framesRead() const { return mFramesRead; }
+    virtual int64_t framesRead() const { return mFramesRead; }
 
     // Number of frames lost due to overrun since construction.
     // Not const because implementations may need to do I/O.
-    virtual size_t framesOverrun() /*const*/ { return 0; }
+    virtual int64_t framesOverrun() /*const*/ { return 0; }
 
     // Number of overruns since construction, where a set of contiguous lost frames is one event.
     // Not const because implementations may need to do I/O.
-    virtual size_t overruns() /*const*/ { return 0; }
+    virtual int64_t overruns() /*const*/ { return 0; }
 
     // Estimate of number of frames that could be read successfully now.
     // When a read() is actually attempted, the implementation is permitted to return a smaller or
@@ -299,7 +299,7 @@
 
     // Invoked asynchronously by corresponding sink when a new timestamp is available.
     // Default implementation ignores the timestamp.
-    virtual void    onTimestamp(const AudioTimestamp& timestamp) { }
+    virtual void    onTimestamp(const ExtendedTimestamp& timestamp) { }
 
 protected:
     NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0)
@@ -307,7 +307,7 @@
     virtual ~NBAIO_Source() { }
 
     // Implementations are free to ignore these if they don't need them
-    size_t  mFramesRead;
+    int64_t  mFramesRead;
 };
 
 }   // namespace android
diff --git a/include/media/nbaio/Pipe.h b/include/media/nbaio/Pipe.h
index eba37bc..cc95ff7 100644
--- a/include/media/nbaio/Pipe.h
+++ b/include/media/nbaio/Pipe.h
@@ -45,9 +45,9 @@
 
     // NBAIO_Sink interface
 
-    //virtual size_t framesWritten() const;
-    //virtual size_t framesUnderrun() const;
-    //virtual size_t underruns() const;
+    //virtual int64_t framesWritten() const;
+    //virtual int64_t framesUnderrun() const;
+    //virtual int64_t underruns() const;
 
     // The write side of a pipe permits overruns; flow control is the caller's responsibility.
     // It doesn't return +infinity because that would guarantee an overrun.
diff --git a/include/media/nbaio/PipeReader.h b/include/media/nbaio/PipeReader.h
index 398353b..7c733ad 100644
--- a/include/media/nbaio/PipeReader.h
+++ b/include/media/nbaio/PipeReader.h
@@ -40,8 +40,8 @@
     // NBAIO_Source interface
 
     //virtual size_t framesRead() const;
-    virtual size_t framesOverrun() { return mFramesOverrun; }
-    virtual size_t overruns()  { return mOverruns; }
+    virtual int64_t framesOverrun() { return mFramesOverrun; }
+    virtual int64_t overruns()  { return mOverruns; }
 
     virtual ssize_t availableToRead();
 
@@ -56,8 +56,8 @@
 private:
     Pipe&       mPipe;
     int32_t     mFront;         // follows behind mPipe.mRear
-    size_t      mFramesOverrun;
-    size_t      mOverruns;
+    int64_t     mFramesOverrun;
+    int64_t     mOverruns;
 };
 
 }   // namespace android
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
index 29172e1..ae49903 100644
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -36,8 +36,8 @@
 
     // ExtendedAudioBufferProvider interface
     virtual size_t   framesReady() const;
-    virtual size_t   framesReleased() const;
-    virtual void     onTimestamp(const AudioTimestamp& timestamp);
+    virtual int64_t  framesReleased() const;
+    virtual void     onTimestamp(const ExtendedTimestamp &timestamp);
 
 private:
     const sp<NBAIO_Source> mSource;     // the wrapped source
@@ -47,7 +47,7 @@
     size_t              mOffset;    // frame offset within mAllocated of valid data
     size_t              mRemaining; // frame count within mAllocated of valid data
     size_t              mGetCount;  // buffer.frameCount of the most recent getNextBuffer
-    uint32_t            mFramesReleased;    // counter of the total number of frames released
+    int64_t             mFramesReleased;    // counter of the total number of frames released
 };
 
 }   // namespace android
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index cc5b486..4489d37 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -238,6 +238,7 @@
     uint32_t mFlags;
     uint32_t mQuirks;
     sp<IOMX> mOMX;
+    sp<IBinder> mNodeBinder;
     IOMX::node_id mNode;
     sp<MemoryDealer> mDealer[2];
 
diff --git a/include/media/stagefright/ProcessInfo.h b/include/media/stagefright/ProcessInfo.h
index ec0cdff..0be1a52 100644
--- a/include/media/stagefright/ProcessInfo.h
+++ b/include/media/stagefright/ProcessInfo.h
@@ -27,6 +27,7 @@
     ProcessInfo();
 
     virtual bool getPriority(int pid, int* priority);
+    virtual bool isValidPid(int pid);
 
 protected:
     virtual ~ProcessInfo();
diff --git a/include/media/stagefright/ProcessInfoInterface.h b/include/media/stagefright/ProcessInfoInterface.h
index 222f92d..b39112a 100644
--- a/include/media/stagefright/ProcessInfoInterface.h
+++ b/include/media/stagefright/ProcessInfoInterface.h
@@ -23,6 +23,7 @@
 
 struct ProcessInfoInterface : public RefBase {
     virtual bool getPriority(int pid, int* priority) = 0;
+    virtual bool isValidPid(int pid) = 0;
 
 protected:
     virtual ~ProcessInfoInterface() {}
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index aa9e98c..ea8a78e 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -176,6 +176,7 @@
 
                 // server write-only, client read
                 ExtendedTimestampQueue::Shared mExtendedTimestampQueue;
+
 public:
 
     volatile    int32_t     mFlags;         // combinations of CBLK_*
@@ -532,7 +533,7 @@
             size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
         : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer),
           mPlaybackRateObserver(&cblk->mPlaybackRateQueue),
-          mUnderrunCount(0), mUnderrunning(false) {
+          mUnderrunCount(0), mUnderrunning(false), mDrained(true) {
         mCblk->mSampleRate = sampleRate;
         mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
     }
@@ -569,6 +570,18 @@
     // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
     AudioPlaybackRate getPlaybackRate();
 
+    // Set the internal drain state of the track buffer from the timestamp received.
+    virtual void        setDrained(bool drained) {
+        mDrained.store(drained);
+    }
+
+    // Check if the internal drain state of the track buffer.
+    // This is not a guarantee, but advisory for determining whether the track is
+    // fully played out.
+    virtual bool        isDrained() const {
+        return mDrained.load();
+    }
+
 private:
     AudioPlaybackRate             mPlaybackRate;  // last observed playback rate
     PlaybackRateQueue::Observer   mPlaybackRateObserver;
@@ -576,6 +589,8 @@
     // The server keeps a copy here where it is safe from the client.
     uint32_t                      mUnderrunCount; // echoed to mCblk
     bool                          mUnderrunning;  // used to detect edge of underrun
+
+    std::atomic<bool>             mDrained; // is the track buffer drained
 };
 
 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 33dcc57..f0074b6 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2202,7 +2202,7 @@
     // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
 
     status_t status;
-    if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
+    if (isOffloadedOrDirect_l()) {
         // use Binder to get timestamp
         status = mAudioTrack->getTimestamp(timestamp);
     } else {
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 5a4591c..7f131f4 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -645,7 +645,7 @@
 
             Vector<uint8_t> request;
             String8 defaultUrl;
-            DrmPlugin::KeyRequestType keyRequestType;
+            DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
 
             status_t result = getKeyRequest(sessionId, initData, mimeType,
                     keyType, optionalParameters, request, defaultUrl,
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index bd398aa..0ef6e3e 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -98,7 +98,9 @@
     }
 
     virtual status_t allocateNode(
-            const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+            const char *name, const sp<IOMXObserver> &observer,
+            sp<IBinder> *nodeBinder,
+            node_id *node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeCString(name);
@@ -108,6 +110,9 @@
         status_t err = reply.readInt32();
         if (err == OK) {
             *node = (node_id)reply.readInt32();
+            if (nodeBinder != NULL) {
+                *nodeBinder = remote();
+            }
         } else {
             *node = 0;
         }
@@ -656,7 +661,8 @@
 
             node_id node;
 
-            status_t err = allocateNode(name, observer, &node);
+            status_t err = allocateNode(name, observer,
+                    NULL /* nodeBinder */, &node);
             reply->writeInt32(err);
             if (err == OK) {
                 reply->writeInt32((int32_t)node);
@@ -704,34 +710,39 @@
 
             size_t size = data.readInt64();
 
-            void *params = malloc(size);
-            data.read(params, size);
+            status_t err = NO_MEMORY;
+            void *params = calloc(size, 1);
+            if (params) {
+                err = data.read(params, size);
+                if (err != OK) {
+                    android_errorWriteLog(0x534e4554, "26914474");
+                } else {
+                    switch (code) {
+                        case GET_PARAMETER:
+                            err = getParameter(node, index, params, size);
+                            break;
+                        case SET_PARAMETER:
+                            err = setParameter(node, index, params, size);
+                            break;
+                        case GET_CONFIG:
+                            err = getConfig(node, index, params, size);
+                            break;
+                        case SET_CONFIG:
+                            err = setConfig(node, index, params, size);
+                            break;
+                        case SET_INTERNAL_OPTION:
+                        {
+                            InternalOptionType type =
+                                (InternalOptionType)data.readInt32();
 
-            status_t err;
-            switch (code) {
-                case GET_PARAMETER:
-                    err = getParameter(node, index, params, size);
-                    break;
-                case SET_PARAMETER:
-                    err = setParameter(node, index, params, size);
-                    break;
-                case GET_CONFIG:
-                    err = getConfig(node, index, params, size);
-                    break;
-                case SET_CONFIG:
-                    err = setConfig(node, index, params, size);
-                    break;
-                case SET_INTERNAL_OPTION:
-                {
-                    InternalOptionType type =
-                        (InternalOptionType)data.readInt32();
+                            err = setInternalOption(node, index, type, params, size);
+                            break;
+                        }
 
-                    err = setInternalOption(node, index, type, params, size);
-                    break;
+                        default:
+                            TRESPASS();
+                    }
                 }
-
-                default:
-                    TRESPASS();
             }
 
             reply->writeInt32(err);
@@ -950,10 +961,6 @@
             MetadataBufferType type = kMetadataBufferTypeInvalid;
             status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
 
-            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
-                android_errorWriteLog(0x534e4554, "26324358");
-            }
-
             reply->writeInt32(type);
             reply->writeInt32(err);
 
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index de350a1..ef4c833 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -39,6 +39,10 @@
         return true;
     }
 
+    virtual bool isValidPid(int /* pid */) {
+        return true;
+    }
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
 };
diff --git a/media/libnbaio/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
index 286e0eb..2dc3050 100644
--- a/media/libnbaio/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -53,7 +53,7 @@
     return NBAIO_Source::negotiate(offers, numOffers, counterOffers, numCounterOffers);
 }
 
-size_t AudioStreamInSource::framesOverrun()
+int64_t AudioStreamInSource::framesOverrun()
 {
     uint32_t framesOverrun = mStream->get_input_frames_lost(mStream);
     if (framesOverrun > 0) {
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index 3f4e0bb..ee44678 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -66,18 +66,20 @@
     return ret;
 }
 
-status_t AudioStreamOutSink::getTimestamp(AudioTimestamp& timestamp)
+status_t AudioStreamOutSink::getTimestamp(ExtendedTimestamp &timestamp)
 {
     if (mStream->get_presentation_position == NULL) {
         return INVALID_OPERATION;
     }
-    // FIXME position64 won't be needed after AudioTimestamp.mPosition is changed to uint64_t
+
     uint64_t position64;
-    int ok = mStream->get_presentation_position(mStream, &position64, &timestamp.mTime);
-    if (ok != 0) {
+    struct timespec time;
+    if (mStream->get_presentation_position(mStream, &position64, &time) != OK) {
         return INVALID_OPERATION;
     }
-    timestamp.mPosition = position64;
+    timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position64;
+    timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+            time.tv_sec * 1000000000LL + time.tv_nsec;
     return OK;
 }
 
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index aef9834..8d1cb0f 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -183,9 +183,14 @@
     return mIsShutdown;
 }
 
-status_t MonoPipe::getTimestamp(AudioTimestamp& timestamp)
+status_t MonoPipe::getTimestamp(ExtendedTimestamp &timestamp)
 {
-    if (mTimestampObserver.poll(timestamp)) {
+    ExtendedTimestamp ets;
+    if (mTimestampObserver.poll(ets)) {
+        timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+                ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+        timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+                ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
         return OK;
     }
     return INVALID_OPERATION;
diff --git a/media/libnbaio/MonoPipeReader.cpp b/media/libnbaio/MonoPipeReader.cpp
index 7e09544..01dc524 100644
--- a/media/libnbaio/MonoPipeReader.cpp
+++ b/media/libnbaio/MonoPipeReader.cpp
@@ -72,7 +72,7 @@
     return red;
 }
 
-void MonoPipeReader::onTimestamp(const AudioTimestamp& timestamp)
+void MonoPipeReader::onTimestamp(const ExtendedTimestamp &timestamp)
 {
     mPipe->mTimestampMutator.push(timestamp);
 }
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index dc01c0e..d58619f 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -112,12 +112,12 @@
     return avail < 0 ? 0 : (size_t) avail;
 }
 
-size_t SourceAudioBufferProvider::framesReleased() const
+int64_t SourceAudioBufferProvider::framesReleased() const
 {
     return mFramesReleased;
 }
 
-void SourceAudioBufferProvider::onTimestamp(const AudioTimestamp& timestamp)
+void SourceAudioBufferProvider::onTimestamp(const ExtendedTimestamp &timestamp)
 {
     mSource->onTimestamp(timestamp);
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 0dc5d4c..ee573f0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5541,7 +5541,7 @@
     ALOGV("Now uninitialized");
 
     if (mDeathNotifier != NULL) {
-        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
+        mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
         mDeathNotifier.clear();
     }
 
@@ -5638,13 +5638,6 @@
 
     sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
 
-    mDeathNotifier = new DeathNotifier(notify);
-    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
-        // This was a local binder, if it dies so do we, we won't care
-        // about any notifications in the afterlife.
-        mDeathNotifier.clear();
-    }
-
     Vector<AString> matchingCodecs;
 
     AString mime;
@@ -5683,7 +5676,7 @@
         pid_t tid = gettid();
         int prevPriority = androidGetThreadPriority(tid);
         androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
-        err = omx->allocateNode(componentName.c_str(), observer, &node);
+        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
         androidSetThreadPriority(tid, prevPriority);
 
         if (err == OK) {
@@ -5707,6 +5700,14 @@
         return false;
     }
 
+    mDeathNotifier = new DeathNotifier(notify);
+    if (mCodec->mNodeBinder == NULL ||
+            mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
+        // This was a local binder, if it dies so do we, we won't care
+        // about any notifications in the afterlife.
+        mDeathNotifier.clear();
+    }
+
     notify = new AMessage(kWhatOMXMessageList, mCodec);
     observer->setNotificationMessage(notify);
 
@@ -7078,7 +7079,7 @@
     sp<CodecObserver> observer = new CodecObserver;
     IOMX::node_id node = 0;
 
-    err = omx->allocateNode(name.c_str(), observer, &node);
+    err = omx->allocateNode(name.c_str(), observer, NULL, &node);
     if (err != OK) {
         client.disconnect();
         return err;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 3a3a538..bdfddc7 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -48,6 +48,7 @@
 struct MediaCodecSource::Puller : public AHandler {
     Puller(const sp<MediaSource> &source);
 
+    void interruptSource();
     status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
     void stop();
     void stopSource();
@@ -84,9 +85,9 @@
 
         void flush();
         // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
-        // buffer from front of the queue, place it into *|buffer| and return true. 
+        // buffer from front of the queue, place it into *|buffer| and return true.
         bool readBuffer(MediaBuffer **buffer);
-        // add a buffer to the back of the queue 
+        // add a buffer to the back of the queue
         void pushBuffer(MediaBuffer *mbuf);
     };
     Mutexed<Queue> mQueue;
@@ -186,14 +187,19 @@
     }
 
     if (interrupt) {
-        // call source->stop if read has been pending for over a second
-        // TODO: we should really call this if kWhatStop has not returned for more than a second.
-        mSource->stop();
+        interruptSource();
     }
 }
 
+void MediaCodecSource::Puller::interruptSource() {
+    // call source->stop if read has been pending for over a second
+    // We have to call this outside the looper as looper is pending on the read.
+    mSource->stop();
+}
+
 void MediaCodecSource::Puller::stopSource() {
-    (new AMessage(kWhatStop, this))->post();
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
+    (void)postSynchronouslyAndReturnError(msg);
 }
 
 void MediaCodecSource::Puller::pause() {
@@ -247,6 +253,13 @@
         case kWhatStop:
         {
             mSource->stop();
+
+            sp<AMessage> response = new AMessage;
+            response->setInt32("err", OK);
+
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+            response->postReply(replyID);
             break;
         }
 
@@ -915,7 +928,7 @@
 
         if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
             ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
-            mPuller->stopSource();
+            mPuller->interruptSource();
             ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
         }
         signalEOS();
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 50f235e..8e72405 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,19 +25,29 @@
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/OMXClient.h>
+#include <cutils/properties.h>
 #include <utils/KeyedVector.h>
 
 #include "include/OMX.h"
 
 namespace android {
 
+static bool sCodecProcessEnabled = true;
+
 struct MuxOMX : public IOMX {
-    MuxOMX(const sp<IOMX> &remoteOMX);
+    MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
     virtual ~MuxOMX();
 
-    virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
+    // Nobody should be calling this. In case someone does anyway, just
+    // return the media server IOMX.
+    // TODO: return NULL
+    virtual IBinder *onAsBinder() {
+        ALOGE("MuxOMX::onAsBinder should not be called");
+        return IInterface::asBinder(mMediaServerOMX).get();
+    }
 
     virtual bool livesLocally(node_id node, pid_t pid);
 
@@ -45,6 +55,7 @@
 
     virtual status_t allocateNode(
             const char *name, const sp<IOMXObserver> &observer,
+            sp<IBinder> *nodeBinder,
             node_id *node);
 
     virtual status_t freeNode(node_id node);
@@ -148,23 +159,32 @@
 private:
     mutable Mutex mLock;
 
-    sp<IOMX> mRemoteOMX;
+    sp<IOMX> mMediaServerOMX;
+    sp<IOMX> mMediaCodecOMX;
     sp<IOMX> mLocalOMX;
 
-    KeyedVector<node_id, bool> mIsLocalNode;
+    typedef enum {
+        LOCAL,
+        MEDIAPROCESS,
+        CODECPROCESS
+    } node_location;
+
+    KeyedVector<node_id, node_location> mNodeLocation;
 
     bool isLocalNode(node_id node) const;
     bool isLocalNode_l(node_id node) const;
     const sp<IOMX> &getOMX(node_id node) const;
     const sp<IOMX> &getOMX_l(node_id node) const;
 
-    static bool CanLiveLocally(const char *name);
+    static node_location getPreferredCodecLocation(const char *name);
 
     DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
 };
 
-MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
-    : mRemoteOMX(remoteOMX) {
+MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
+    : mMediaServerOMX(mediaServerOMX),
+      mMediaCodecOMX(mediaCodecOMX) {
+    ALOGI("MuxOMX ctor");
 }
 
 MuxOMX::~MuxOMX() {
@@ -177,27 +197,49 @@
 }
 
 bool MuxOMX::isLocalNode_l(node_id node) const {
-    return mIsLocalNode.indexOfKey(node) >= 0;
+    return mNodeLocation.valueFor(node) == LOCAL;
 }
 
 // static
-bool MuxOMX::CanLiveLocally(const char *name) {
+MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
+    if (sCodecProcessEnabled) {
+        // all non-secure decoders plus OMX.google.* encoders can go in the codec process
+        if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
+                !strncasecmp(name, "OMX.google.", 11)) {
+            return CODECPROCESS;
+        }
+        // everything else runs in the media server
+        return MEDIAPROCESS;
+    } else {
 #ifdef __LP64__
-    (void)name; // disable unused parameter warning
-    // 64 bit processes always run OMX remote on MediaServer
-    return false;
+        // 64 bit processes always run OMX remote on MediaServer
+        return MEDIAPROCESS;
 #else
-    // 32 bit processes run only OMX.google.* components locally
-    return !strncasecmp(name, "OMX.google.", 11);
+        // 32 bit processes run only OMX.google.* components locally
+        if (!strncasecmp(name, "OMX.google.", 11)) {
+            return LOCAL;
+        }
+        return MEDIAPROCESS;
 #endif
+    }
 }
 
 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
-    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
+    Mutex::Autolock autoLock(mLock);
+    return getOMX_l(node);
 }
 
 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
-    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
+    node_location loc = mNodeLocation.valueFor(node);
+    if (loc == LOCAL) {
+        return mLocalOMX;
+    } else if (loc == MEDIAPROCESS) {
+        return mMediaServerOMX;
+    } else if (loc == CODECPROCESS) {
+        return mMediaCodecOMX;
+    }
+    ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
+    return mLocalOMX;
 }
 
 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
@@ -216,29 +258,34 @@
 
 status_t MuxOMX::allocateNode(
         const char *name, const sp<IOMXObserver> &observer,
+        sp<IBinder> *nodeBinder,
         node_id *node) {
     Mutex::Autolock autoLock(mLock);
 
     sp<IOMX> omx;
 
-    if (CanLiveLocally(name)) {
+    node_location loc = getPreferredCodecLocation(name);
+    if (loc == CODECPROCESS) {
+        omx = mMediaCodecOMX;
+    } else if (loc == MEDIAPROCESS) {
+        omx = mMediaServerOMX;
+    } else {
         if (mLocalOMX == NULL) {
             mLocalOMX = new OMX;
         }
         omx = mLocalOMX;
-    } else {
-        omx = mRemoteOMX;
     }
 
-    status_t err = omx->allocateNode(name, observer, node);
+    status_t err = omx->allocateNode(name, observer, nodeBinder, node);
+    ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
+            omx == mMediaServerOMX ? "mediaserver" : "local");
+
 
     if (err != OK) {
         return err;
     }
 
-    if (omx == mLocalOMX) {
-        mIsLocalNode.add(*node, true);
-    }
+    mNodeLocation.add(*node, loc);
 
     return OK;
 }
@@ -252,7 +299,7 @@
         return err;
     }
 
-    mIsLocalNode.removeItem(node);
+    mNodeLocation.removeItem(node);
 
     return OK;
 }
@@ -352,7 +399,7 @@
         sp<IGraphicBufferProducer> *bufferProducer,
         sp<IGraphicBufferConsumer> *bufferConsumer) {
     // TODO: local or remote? Always use remote for now
-    return mRemoteOMX->createPersistentInputSurface(
+    return mMediaServerOMX->createPersistentInputSurface(
             bufferProducer, bufferConsumer);
 }
 
@@ -415,29 +462,53 @@
 }
 
 OMXClient::OMXClient() {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.codecremote", value, NULL)
+            && (!strcmp("0", value) || !strcasecmp("false", value))) {
+        sCodecProcessEnabled = false;
+    }
 }
 
 status_t OMXClient::connect() {
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.player"));
-    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    sp<IBinder> playerbinder = sm->getService(String16("media.player"));
+    sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
 
-    if (service.get() == NULL) {
+    if (mediaservice.get() == NULL) {
         ALOGE("Cannot obtain IMediaPlayerService");
         return NO_INIT;
     }
 
-    mOMX = service->getOMX();
-    if (mOMX.get() == NULL) {
-        ALOGE("Cannot obtain IOMX");
+    sp<IOMX> mediaServerOMX = mediaservice->getOMX();
+    if (mediaServerOMX.get() == NULL) {
+        ALOGE("Cannot obtain mediaserver IOMX");
         return NO_INIT;
     }
 
-    if (!mOMX->livesLocally(0 /* node */, getpid())) {
-        ALOGI("Using client-side OMX mux.");
-        mOMX = new MuxOMX(mOMX);
+    // If we don't want to use the codec process, and the media server OMX
+    // is local, use it directly instead of going through MuxOMX
+    if (!sCodecProcessEnabled &&
+            mediaServerOMX->livesLocally(0 /* node */, getpid())) {
+        mOMX = mediaServerOMX;
+        return OK;
     }
 
+    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
+    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
+
+    if (codecservice.get() == NULL) {
+        ALOGE("Cannot obtain IMediaCodecService");
+        return NO_INIT;
+    }
+
+    sp<IOMX> mediaCodecOMX = codecservice->getOMX();
+    if (mediaCodecOMX.get() == NULL) {
+        ALOGE("Cannot obtain mediacodec IOMX");
+        return NO_INIT;
+    }
+
+    mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
+
     return OK;
 }
 
diff --git a/media/libstagefright/ProcessInfo.cpp b/media/libstagefright/ProcessInfo.cpp
index 353f108..27f1a79 100644
--- a/media/libstagefright/ProcessInfo.cpp
+++ b/media/libstagefright/ProcessInfo.cpp
@@ -20,6 +20,7 @@
 
 #include <media/stagefright/ProcessInfo.h>
 
+#include <binder/IPCThreadState.h>
 #include <binder/IProcessInfoService.h>
 #include <binder/IServiceManager.h>
 
@@ -52,6 +53,12 @@
     return true;
 }
 
+bool ProcessInfo::isValidPid(int pid) {
+    int callingPid = IPCThreadState::self()->getCallingPid();
+    // Trust it if this is called from the same process otherwise pid has to match the calling pid.
+    return (callingPid == getpid()) || (callingPid == pid);
+}
+
 ProcessInfo::~ProcessInfo() {}
 
 }  // namespace android
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 4c27360..c715939 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -36,7 +36,9 @@
     virtual status_t listNodes(List<ComponentInfo> *list);
 
     virtual status_t allocateNode(
-            const char *name, const sp<IOMXObserver> &observer, node_id *node);
+            const char *name, const sp<IOMXObserver> &observer,
+            sp<IBinder> *nodeBinder,
+            node_id *node);
 
     virtual status_t freeNode(node_id node);
 
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index a20028b..6be289b 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -235,10 +235,14 @@
 }
 
 status_t OMX::allocateNode(
-        const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+        const char *name, const sp<IOMXObserver> &observer,
+        sp<IBinder> *nodeBinder, node_id *node) {
     Mutex::Autolock autoLock(mLock);
 
     *node = 0;
+    if (nodeBinder != NULL) {
+        *nodeBinder = NULL;
+    }
 
     if (mNodeIDToInstance.size() == kMaxNodeInstances) {
         // all possible node IDs are in use
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index a8c55fa..7380ab2 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -543,6 +543,7 @@
 status_t OMXNodeInstance::storeMetaDataInBuffers_l(
         OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
     if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+        android_errorWriteLog(0x534e4554, "26324358");
         return BAD_VALUE;
     }
 
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index c0ccb35..50bb0de 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -267,7 +267,7 @@
     IOMX::node_id node;
 
     status_t err =
-        mOMX->allocateNode(componentName, this, &node);
+        mOMX->allocateNode(componentName, this, NULL, &node);
     EXPECT_SUCCESS(err, "allocateNode");
 
     NodeReaper reaper(this, node);
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 1446d19..d31b8d3 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -141,6 +141,10 @@
     FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
     const size_t frameCount = current->mFrameCount;
 
+    // update boottime offset, in case it has changed
+    mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
+            mBoottimeOffset.load();
+
     // handle state change here, but since we want to diff the state,
     // we're prepared for previous == &sInitial the first time through
     unsigned previousTrackMask;
@@ -341,21 +345,23 @@
             currentTrackMask &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
 
-            // Refresh the per-track timestamp
-            if (mTimestampStatus == NO_ERROR) {
-                uint32_t trackFramesWrittenButNotPresented =
-                    mNativeFramesWrittenButNotPresented;
-                uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
-                // Can't provide an AudioTimestamp before first frame presented,
-                // or during the brief 32-bit wraparound window
-                if (trackFramesWritten >= trackFramesWrittenButNotPresented) {
-                    AudioTimestamp perTrackTimestamp;
-                    perTrackTimestamp.mPosition =
-                            trackFramesWritten - trackFramesWrittenButNotPresented;
-                    perTrackTimestamp.mTime = mTimestamp.mTime;
-                    fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
-                }
+            const int64_t trackFramesWrittenButNotPresented =
+                mNativeFramesWrittenButNotPresented;
+            const int64_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
+            ExtendedTimestamp perTrackTimestamp(mTimestamp);
+
+            // Can't provide an ExtendedTimestamp before first frame presented.
+            // Also, timestamp may not go to very last frame on stop().
+            if (trackFramesWritten >= trackFramesWrittenButNotPresented &&
+                    perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) {
+                perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+                        trackFramesWritten - trackFramesWrittenButNotPresented;
+            } else {
+                perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
+                perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
             }
+            perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = trackFramesWritten;
+            fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
 
             int name = mFastTrackNames[i];
             ALOG_ASSERT(name >= 0);
@@ -449,17 +455,34 @@
         mAttemptedWrite = true;
         // FIXME count # of writes blocked excessively, CPU usage, etc. for dump
 
-        mTimestampStatus = mOutputSink->getTimestamp(mTimestamp);
-        if (mTimestampStatus == NO_ERROR) {
-            uint32_t totalNativeFramesPresented = mTimestamp.mPosition;
+        ExtendedTimestamp timestamp; // local
+        status_t status = mOutputSink->getTimestamp(timestamp);
+        if (status == NO_ERROR) {
+            const int64_t totalNativeFramesPresented =
+                    timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
             if (totalNativeFramesPresented <= mTotalNativeFramesWritten) {
                 mNativeFramesWrittenButNotPresented =
                     mTotalNativeFramesWritten - totalNativeFramesPresented;
+                mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+                        timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+                mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+                        timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
             } else {
                 // HAL reported that more frames were presented than were written
-                mTimestampStatus = INVALID_OPERATION;
+                mNativeFramesWrittenButNotPresented = 0;
+                mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
+                mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
+                status = INVALID_OPERATION;
             }
         }
+        if (status == NO_ERROR) {
+            mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
+                    mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+        } else {
+            // fetch server time if we can't get timestamp
+            mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
+                    systemTime(SYSTEM_TIME_MONOTONIC);
+        }
     }
 }
 
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index e38878e..3cc7c9f 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -38,7 +38,9 @@
             FastMixerStateQueue* sq();
 
     virtual void setMasterMono(bool mono) { mMasterMono.store(mono); /* memory_order_seq_cst */ }
-
+    virtual void setBoottimeOffset(int64_t boottimeOffset) {
+        mBoottimeOffset.store(boottimeOffset); /* memory_order_seq_cst */
+    }
 private:
             FastMixerStateQueue mSQ;
 
@@ -79,14 +81,15 @@
     unsigned        mSampleRate;
     int             mFastTracksGen;
     FastMixerDumpState mDummyFastMixerDumpState;
-    uint32_t        mTotalNativeFramesWritten;  // copied to dumpState->mFramesWritten
+    int64_t         mTotalNativeFramesWritten;  // copied to dumpState->mFramesWritten
 
     // next 2 fields are valid only when timestampStatus == NO_ERROR
-    AudioTimestamp  mTimestamp;
-    uint32_t        mNativeFramesWrittenButNotPresented;
+    ExtendedTimestamp mTimestamp;
+    int64_t         mNativeFramesWrittenButNotPresented;
 
     // accessed without lock between multiple threads.
     std::atomic_bool mMasterMono;
+    std::atomic_int_fast64_t mBoottimeOffset;
 };  // class FastMixer
 
 }   // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index fe3cc53..fa61af2 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -88,8 +88,8 @@
 
     // ExtendedAudioBufferProvider interface
     virtual size_t framesReady() const;
-    virtual size_t framesReleased() const;
-    virtual void onTimestamp(const AudioTimestamp &timestamp);
+    virtual int64_t framesReleased() const;
+    virtual void onTimestamp(const ExtendedTimestamp &timestamp);
 
     bool isPausing() const { return mState == PAUSING; }
     bool isPaused() const { return mState == PAUSED; }
@@ -101,15 +101,15 @@
     void flushAck();
     bool isResumePending();
     void resumeAck();
-    void updateTrackFrameInfo(uint32_t trackFramesReleased, uint32_t sinkFramesWritten,
-            AudioTimestamp *timeStamp = NULL);
+    void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten,
+            const ExtendedTimestamp &timeStamp);
 
     sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
 
     // framesWritten is cumulative, never reset, and is shared all tracks
     // audioHalFrames is derived from output latency
     // FIXME parameters not needed, could get them from the thread
-    bool presentationComplete(size_t framesWritten, size_t audioHalFrames);
+    bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
 
 public:
     void triggerEvents(AudioSystem::sync_event_t type);
@@ -142,9 +142,9 @@
                                     // zero means not monitoring
 
     // access these three variables only when holding thread lock.
-    LinearMap<uint32_t> mFrameMap;           // track frame to server frame mapping
-    bool                mSinkTimestampValid; // valid cached timestamp
-    AudioTimestamp      mSinkTimestamp;
+    LinearMap<int64_t> mFrameMap;           // track frame to server frame mapping
+
+    ExtendedTimestamp  mSinkTimestamp;
 
 private:
     // The following fields are only for fast tracks, and should be in a subclass
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 4807400..e056ef2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1034,6 +1034,8 @@
         mNotifiedBatteryStart = true;
     }
     gBoottime.acquire(mWakeLockToken);
+    mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
+            gBoottime.getBoottimeOffset();
 }
 
 void AudioFlinger::ThreadBase::releaseWakeLock()
@@ -1563,6 +1565,7 @@
         mEffectBufferFormat(AUDIO_FORMAT_INVALID),
         mEffectBufferValid(false),
         mSuspended(0), mBytesWritten(0),
+        mFramesWritten(0),
         mActiveTracksGeneration(0),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
@@ -2370,13 +2373,14 @@
     if (initCheck() != NO_ERROR) {
         return INVALID_OPERATION;
     }
-    size_t framesWritten = mBytesWritten / mFrameSize;
+    int64_t framesWritten = mBytesWritten / mFrameSize;
     *halFrames = framesWritten;
 
     if (isSuspended()) {
         // return an estimation of rendered frames when the output is suspended
         size_t latencyFrames = (latency_l() * mSampleRate) / 1000;
-        *dspFrames = framesWritten >= latencyFrames ? framesWritten - latencyFrames : 0;
+        *dspFrames = (uint32_t)
+                (framesWritten >= (int64_t)latencyFrames ? framesWritten - latencyFrames : 0);
         return NO_ERROR;
     } else {
         status_t status;
@@ -2860,43 +2864,30 @@
             // and associate with the sink frames written out.  We need
             // this to convert the sink timestamp to the track timestamp.
             if (mNormalSink != 0) {
-                bool updateTracks = true;
-                bool cacheTimestamp = false;
-                AudioTimestamp timeStamp;
-                // FIXME: Use a 64 bit mNormalSink->framesWritten() counter.
-                // At this time, we must always use cached timestamps even when
-                // going through mPipeSink (which is non-blocking). The reason is that
-                // the track may be removed from the active list for many hours and
-                // the mNormalSink->framesWritten() will wrap making the linear
-                // mapping fail.
-                //
-                // (Also mAudioTrackServerProxy->framesReleased() needs to be
-                // updated to 64 bits for 64 bit frame position.)
-                //
-                if (true /* see comment above, should be: mNormalSink == mOutputSink */) {
-                    // If we use a hardware device, we must cache the sink timestamp now.
-                    // hardware devices can block timestamp access during data writes.
-                    if (mNormalSink->getTimestamp(timeStamp) == NO_ERROR) {
-                        cacheTimestamp = true;
-                    } else {
-                        updateTracks = false;
-                    }
-                }
-                if (updateTracks) {
-                    // sinkFramesWritten for non-offloaded tracks are contiguous
-                    // even after standby() is called. This is useful for the track frame
-                    // to sink frame mapping.
-                    const uint32_t sinkFramesWritten = mNormalSink->framesWritten();
-                    const size_t size = mActiveTracks.size();
-                    for (size_t i = 0; i < size; ++i) {
-                        sp<Track> t = mActiveTracks[i].promote();
-                        if (t != 0 && !t->isFastTrack()) {
-                            t->updateTrackFrameInfo(
-                                    t->mAudioTrackServerProxy->framesReleased(),
-                                    sinkFramesWritten,
-                                    cacheTimestamp ? &timeStamp : NULL);
-                        }
-                    }
+                // Note: The DuplicatingThread may not have a mNormalSink.
+                // We always fetch the timestamp here because often the downstream
+                // sink will block whie writing.
+                ExtendedTimestamp timestamp; // use private copy to fetch
+                (void) mNormalSink->getTimestamp(timestamp);
+                // copy over kernel info
+                mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+                        timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+                mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+                        timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+            }
+            // mFramesWritten for non-offloaded tracks are contiguous
+            // even after standby() is called. This is useful for the track frame
+            // to sink frame mapping.
+            mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
+            mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
+            const size_t size = mActiveTracks.size();
+            for (size_t i = 0; i < size; ++i) {
+                sp<Track> t = mActiveTracks[i].promote();
+                if (t != 0 && !t->isFastTrack()) {
+                    t->updateTrackFrameInfo(
+                            t->mAudioTrackServerProxy->framesReleased(),
+                            mFramesWritten,
+                            mTimestamp);
                 }
             }
 
@@ -3034,6 +3025,7 @@
                 mSleepTimeUs = suspendSleepTimeUs();
                 // simulate write to HAL when suspended
                 mBytesWritten += mSinkBufferSize;
+                mFramesWritten += mSinkBufferSize / mFrameSize;
                 mBytesRemaining = 0;
             }
 
@@ -3084,6 +3076,7 @@
                     } else {
                         mBytesWritten += ret;
                         mBytesRemaining -= ret;
+                        mFramesWritten += ret / mFrameSize;
                     }
                 } else if ((mMixerStatus == MIXER_DRAIN_TRACK) ||
                         (mMixerStatus == MIXER_DRAIN_ALL)) {
@@ -3209,7 +3202,12 @@
 status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
 {
     if (mNormalSink != 0) {
-        return mNormalSink->getTimestamp(timestamp);
+        ExtendedTimestamp ets;
+        status_t status = mNormalSink->getTimestamp(ets);
+        if (status == NO_ERROR) {
+            status = ets.getBestTimestamp(&timestamp);
+        }
+        return status;
     }
     if ((mType == OFFLOAD || mType == DIRECT)
             && mOutput != NULL && mOutput->stream->get_presentation_position) {
@@ -3925,7 +3923,7 @@
                 {
                     size_t audioHALFrames =
                             (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
-                    size_t framesWritten = mBytesWritten / mFrameSize;
+                    int64_t framesWritten = mBytesWritten / mFrameSize;
                     if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) {
                         // track stays in active list until presentation is complete
                         break;
@@ -4255,7 +4253,7 @@
                 // TODO: use actual buffer filling status instead of latency when available from
                 // audio HAL
                 size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
-                size_t framesWritten = mBytesWritten / mFrameSize;
+                int64_t framesWritten = mBytesWritten / mFrameSize;
                 if (mStandby || track->presentationComplete(framesWritten, audioHALFrames)) {
                     if (track->isStopped()) {
                         track->reset();
@@ -4796,7 +4794,7 @@
                     audioHALFrames = 0;
                 }
 
-                size_t framesWritten = mBytesWritten / mFrameSize;
+                int64_t framesWritten = mBytesWritten / mFrameSize;
                 if (mStandby || !last ||
                         track->presentationComplete(framesWritten, audioHALFrames)) {
                     if (track->isStopping_2()) {
@@ -5343,7 +5341,7 @@
                     track->mState = TrackBase::STOPPED;
                     size_t audioHALFrames =
                             (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
-                    size_t framesWritten =
+                    int64_t framesWritten =
                             mBytesWritten / mOutput->getFrameSize();
                     track->presentationComplete(framesWritten, audioHALFrames);
                     track->reset();
@@ -5789,9 +5787,6 @@
         }
     }
 
-    mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
-            gBoottime.getBoottimeOffset();
-
     // used to request a deferred sleep, to be executed later while mutex is unlocked
     uint32_t sleepUs = 0;
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 7c92c1c..42b3266 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -381,7 +381,7 @@
                 };
 
                 void        acquireWakeLock(int uid = -1);
-                void        acquireWakeLock_l(int uid = -1);
+                virtual void acquireWakeLock_l(int uid = -1);
                 void        releaseWakeLock();
                 void        releaseWakeLock_l();
                 void        updateWakeLockUids(const SortedVector<int> &uids);
@@ -460,6 +460,7 @@
                 sp<NBLog::Writer>       mNBLogWriter;
                 bool                    mSystemReady;
                 bool                    mNotifiedBatteryStart;
+                ExtendedTimestamp       mTimestamp;
 };
 
 // --- PlaybackThread ---
@@ -691,9 +692,8 @@
     // 'volatile' means accessed via atomic operations and no lock.
     volatile int32_t                mSuspended;
 
-    // FIXME overflows every 6+ hours at 44.1 kHz stereo 16-bit samples
-    // mFramesWritten would be better, or 64-bit even better
-    size_t                          mBytesWritten;
+    int64_t                         mBytesWritten;
+    int64_t                         mFramesWritten; // not reset on standby
 private:
     // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a
     // PlaybackThread needs to find out if master-muted, it checks it's local
@@ -868,6 +868,14 @@
     virtual     uint32_t    suspendSleepTimeUs() const;
     virtual     void        cacheParameters_l();
 
+    virtual void acquireWakeLock_l(int uid = -1) {
+        PlaybackThread::acquireWakeLock_l(uid);
+        if (hasFastMixer()) {
+            mFastMixer->setBoottimeOffset(
+                    mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]);
+        }
+    }
+
     // threadLoop snippets
     virtual     ssize_t     threadLoop_write();
     virtual     void        threadLoop_standby();
@@ -1311,8 +1319,6 @@
             // rolling index that is never cleared
             int32_t                             mRsmpInRear;    // last filled frame + 1
 
-            ExtendedTimestamp                   mTimestamp;
-
             // For dumpsys
             const sp<NBAIO_Sink>                mTeeSink;
 
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 536581c..e684fc2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -362,7 +362,6 @@
     mAuxEffectId(0), mHasVolumeController(false),
     mPresentationCompleteFrames(0),
     mFrameMap(16 /* sink-frame-to-track-frame map memory */),
-    mSinkTimestampValid(false),
     // mSinkTimestamp
     mFastIndex(-1),
     mCachedVolume(1.0),
@@ -591,23 +590,18 @@
     return mAudioTrackServerProxy->framesReady();
 }
 
-size_t AudioFlinger::PlaybackThread::Track::framesReleased() const
+int64_t AudioFlinger::PlaybackThread::Track::framesReleased() const
 {
     return mAudioTrackServerProxy->framesReleased();
 }
 
-void AudioFlinger::PlaybackThread::Track::onTimestamp(const AudioTimestamp &timestamp)
+void AudioFlinger::PlaybackThread::Track::onTimestamp(const ExtendedTimestamp &timestamp)
 {
     // This call comes from a FastTrack and should be kept lockless.
     // The server side frames are already translated to client frames.
+    mAudioTrackServerProxy->setTimestamp(timestamp);
 
-    ExtendedTimestamp ets;
-    ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
-            timestamp.mTime.tv_sec * 1000000000LL + timestamp.mTime.tv_nsec;
-    ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = timestamp.mPosition;
-
-    // Caution, this doesn't set the timebase for BOOTTIME properly, but is ignored right now.
-    mAudioTrackServerProxy->setTimestamp(ets);
+    // We do not set drained here, as FastTrack timestamp may not go to very last frame.
 }
 
 // Don't call for fast tracks; the framesReady() could result in priority inversion
@@ -872,9 +866,8 @@
 
 status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
 {
-    // Client should implement this using SSQ; the unpresented frame count in latch is irrelevant
-    if (isFastTrack()) {
-        return INVALID_OPERATION;
+    if (!isOffloaded() && !isDirect()) {
+        return INVALID_OPERATION; // normal tracks handled through SSQ
     }
     sp<ThreadBase> thread = mThread.promote();
     if (thread == 0) {
@@ -883,33 +876,7 @@
 
     Mutex::Autolock _l(thread->mLock);
     PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-
-    if (isOffloaded() || isDirect()) {
-        return playbackThread->getTimestamp_l(timestamp);
-    }
-
-    if (!mFrameMap.hasData()) {
-        // WOULD_BLOCK is consistent with AudioTrack::getTimestamp() in the
-        // FLUSHED and STOPPED state.  We should only return INVALID_OPERATION
-        // when this method is not permitted due to configuration or device.
-        return WOULD_BLOCK;
-    }
-    status_t result = OK;
-    if (!mSinkTimestampValid) { // if no sink position, try to fetch again
-        result = playbackThread->getTimestamp_l(mSinkTimestamp);
-    }
-
-    if (result == OK) {
-        // Lookup the track frame corresponding to the sink frame position.
-        timestamp.mPosition = mFrameMap.findX(mSinkTimestamp.mPosition);
-        timestamp.mTime = mSinkTimestamp.mTime;
-        // ALOGD("track (server-side) timestamp: mPosition(%u)  mTime(%llu)",
-        //        timestamp.mPosition, TIME_TO_NANOS(timestamp.mTime));
-    }
-    // (Possible) FIXME: mSinkTimestamp is updated only when the track is on
-    // the Thread active list. If the track is no longer on the thread active
-    // list should we use current time?
-    return result;
+    return playbackThread->getTimestamp_l(timestamp);
 }
 
 status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
@@ -972,9 +939,12 @@
     mAuxBuffer = buffer;
 }
 
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
-                                                         size_t audioHalFrames)
+bool AudioFlinger::PlaybackThread::Track::presentationComplete(
+        int64_t framesWritten, size_t audioHalFrames)
 {
+    // TODO: improve this based on FrameMap if it exists, to ensure full drain.
+    // This assists in proper timestamp computation as well as wakelock management.
+
     // a track is considered presented when the total number of frames written to audio HAL
     // corresponds to the number of frames written when presentationComplete() is called for the
     // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
@@ -982,15 +952,25 @@
     // to detect when all frames have been played. In this case framesWritten isn't
     // useful because it doesn't always reflect whether there is data in the h/w
     // buffers, particularly if a track has been paused and resumed during draining
-    ALOGV("presentationComplete() mPresentationCompleteFrames %d framesWritten %d",
-                      mPresentationCompleteFrames, framesWritten);
+    ALOGV("presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
+            (long long)mPresentationCompleteFrames, (long long)framesWritten);
     if (mPresentationCompleteFrames == 0) {
         mPresentationCompleteFrames = framesWritten + audioHalFrames;
-        ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
-                  mPresentationCompleteFrames, audioHalFrames);
+        ALOGV("presentationComplete() reset: mPresentationCompleteFrames %lld audioHalFrames %zu",
+                (long long)mPresentationCompleteFrames, audioHalFrames);
     }
 
-    if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) {
+    bool complete;
+    if (isOffloaded()) {
+        complete = true;
+    } else if (isDirect() || isFastTrack()) { // these do not go through linear map
+        complete = framesWritten >= mPresentationCompleteFrames;
+    } else {  // Normal tracks, OutputTracks, and PatchTracks
+        complete = framesWritten >= mPresentationCompleteFrames
+                && mAudioTrackServerProxy->isDrained();
+    }
+
+    if (complete) {
         triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
         mAudioTrackServerProxy->setStreamEndDone();
         return true;
@@ -1101,14 +1081,34 @@
 
 //To be called with thread lock held
 void AudioFlinger::PlaybackThread::Track::updateTrackFrameInfo(
-        uint32_t trackFramesReleased, uint32_t sinkFramesWritten, AudioTimestamp *timeStamp) {
+        int64_t trackFramesReleased, int64_t sinkFramesWritten,
+        const ExtendedTimestamp &timeStamp) {
+    //update frame map
     mFrameMap.push(trackFramesReleased, sinkFramesWritten);
-    if (timeStamp == NULL) {
-        mSinkTimestampValid = false;
-    } else {
-        mSinkTimestampValid = true;
-        mSinkTimestamp = *timeStamp;
+
+    // adjust server times and set drained state.
+    //
+    // Our timestamps are only updated when the track is on the Thread active list.
+    // We need to ensure that tracks are not removed before full drain.
+    ExtendedTimestamp local = timeStamp;
+    bool checked = false;
+    for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
+            i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
+        // Lookup the track frame corresponding to the sink frame position.
+        if (local.mTimeNs[i] > 0) {
+            local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
+            // check drain state from the latest stage in the pipeline.
+            if (!checked) {
+                mAudioTrackServerProxy->setDrained(
+                        local.mPosition[i] >= mAudioTrackServerProxy->framesReleased());
+                checked = true;
+            }
+        }
     }
+    if (!checked) { // no server info, assume drained.
+        mAudioTrackServerProxy->setDrained(true);
+    }
+    mServerProxy->setTimestamp(local);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/audioflinger/tests/README b/services/audioflinger/tests/README
new file mode 100644
index 0000000..508e960
--- /dev/null
+++ b/services/audioflinger/tests/README
@@ -0,0 +1,13 @@
+For libsonic dependency:
+pushd external/sonic
+mm
+popd
+
+To build resampler library:
+pushd ..
+Optionally uncomment USE_NEON=false in Android.mk
+mm
+popd
+
+Then build here:
+mm
diff --git a/services/audioflinger/tests/run_all_unit_tests.sh b/services/audioflinger/tests/run_all_unit_tests.sh
index ffae6ae..113f39e 100755
--- a/services/audioflinger/tests/run_all_unit_tests.sh
+++ b/services/audioflinger/tests/run_all_unit_tests.sh
@@ -8,4 +8,5 @@
 echo "waiting for device"
 adb root && adb wait-for-device remount
 
-adb shell /system/bin/resampler_tests
+#adb shell /system/bin/resampler_tests
+adb shell /data/nativetest/resampler_tests/resampler_tests
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 4f99860..3d4e0b5 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -206,6 +206,10 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
+    if (!mProcessInfo->isValidPid(pid)) {
+        ALOGE("Rejected addResource call with invalid pid.");
+        return;
+    }
     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
     ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos);
     // TODO: do the merge instead of append.
@@ -220,6 +224,10 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
+    if (!mProcessInfo->isValidPid(pid)) {
+        ALOGE("Rejected removeResource call with invalid pid.");
+        return;
+    }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
@@ -259,6 +267,10 @@
     Vector<sp<IResourceManagerClient>> clients;
     {
         Mutex::Autolock lock(mLock);
+        if (!mProcessInfo->isValidPid(callingPid)) {
+            ALOGE("Rejected reclaimResource call with invalid callingPid.");
+            return false;
+        }
         const MediaResource *secureCodec = NULL;
         const MediaResource *nonSecureCodec = NULL;
         const MediaResource *graphicMemory = NULL;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index df49ddc..cffedc6 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -44,6 +44,10 @@
         return true;
     }
 
+    virtual bool isValidPid(int /* pid */) {
+        return true;
+    }
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
 };