Merge "Start 'am' with exec()" into klp-dev
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
index 2315aa9..27a5a2d 100644
--- a/drm/common/DrmInfoEvent.cpp
+++ b/drm/common/DrmInfoEvent.cpp
@@ -16,29 +16,16 @@
 
 #include <utils/String8.h>
 #include <drm/DrmInfoEvent.h>
-#include <stdlib.h>
 
 using namespace android;
 
 DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8 message)
     : mUniqueId(uniqueId),
       mInfoType(infoType),
-      mMessage(message),
-      mDrmBuffer() {
+      mMessage(message) {
 
 }
 
-DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8 message,
-        const DrmBuffer& drmBuffer)
-        : mUniqueId(uniqueId), mInfoType(infoType), mMessage(message), mDrmBuffer() {
-    setData(drmBuffer);
-}
-
-DrmInfoEvent::~DrmInfoEvent() {
-    delete [] mDrmBuffer.data;
-}
-
-
 int DrmInfoEvent::getUniqueId() const {
     return mUniqueId;
 }
@@ -51,80 +38,3 @@
     return mMessage;
 }
 
-int DrmInfoEvent::getCount() const {
-    return mAttributes.size();
-}
-
-status_t DrmInfoEvent::put(const String8& key, String8& value) {
-        mAttributes.add(key, value);
-    return DRM_NO_ERROR;
-}
-
-const String8 DrmInfoEvent::get(const String8& key) const {
-    if (mAttributes.indexOfKey(key) != NAME_NOT_FOUND) {
-        return mAttributes.valueFor(key);
-    }
-    return String8("");
-}
-
-const DrmBuffer& DrmInfoEvent::getData() const {
-    return mDrmBuffer;
-}
-
-void DrmInfoEvent::setData(const DrmBuffer& drmBuffer) {
-    delete [] mDrmBuffer.data;
-    mDrmBuffer.data = new char[drmBuffer.length];;
-    mDrmBuffer.length = drmBuffer.length;
-    memcpy(mDrmBuffer.data, drmBuffer.data, drmBuffer.length);
-}
-
-DrmInfoEvent::KeyIterator DrmInfoEvent::keyIterator() const {
-    return KeyIterator(this);
-}
-
-DrmInfoEvent::Iterator DrmInfoEvent::iterator() const {
-    return Iterator(this);
-}
-
-// KeyIterator implementation
-DrmInfoEvent::KeyIterator::KeyIterator(const DrmInfoEvent::KeyIterator& keyIterator)
-        : mDrmInfoEvent(keyIterator.mDrmInfoEvent), mIndex(keyIterator.mIndex) {
-}
-
-bool DrmInfoEvent::KeyIterator::hasNext() {
-    return (mIndex < mDrmInfoEvent->mAttributes.size());
-}
-
-const String8& DrmInfoEvent::KeyIterator::next() {
-    const String8& key = mDrmInfoEvent->mAttributes.keyAt(mIndex);
-    mIndex++;
-    return key;
-}
-
-DrmInfoEvent::KeyIterator& DrmInfoEvent::KeyIterator::operator=(
-        const DrmInfoEvent::KeyIterator& keyIterator) {
-    mDrmInfoEvent = keyIterator.mDrmInfoEvent;
-    mIndex = keyIterator.mIndex;
-    return *this;
-}
-
-// Iterator implementation
-DrmInfoEvent::Iterator::Iterator(const DrmInfoEvent::Iterator& iterator)
-        : mDrmInfoEvent(iterator.mDrmInfoEvent), mIndex(iterator.mIndex) {
-}
-
-DrmInfoEvent::Iterator& DrmInfoEvent::Iterator::operator=(const DrmInfoEvent::Iterator& iterator) {
-    mDrmInfoEvent = iterator.mDrmInfoEvent;
-    mIndex = iterator.mIndex;
-    return *this;
-}
-
-bool DrmInfoEvent::Iterator::hasNext() {
-    return mIndex < mDrmInfoEvent->mAttributes.size();
-}
-
-const String8& DrmInfoEvent::Iterator::next() {
-    const String8& value = mDrmInfoEvent->mAttributes.editValueAt(mIndex);
-    mIndex++;
-    return value;
-}
diff --git a/drm/common/IDrmServiceListener.cpp b/drm/common/IDrmServiceListener.cpp
index d825afb..6eeea40 100644
--- a/drm/common/IDrmServiceListener.cpp
+++ b/drm/common/IDrmServiceListener.cpp
@@ -32,19 +32,6 @@
     data.writeInt32(event.getType());
     data.writeString8(event.getMessage());
 
-    data.writeInt32(event.getCount());
-    DrmInfoEvent::KeyIterator keyIt = event.keyIterator();
-    while (keyIt.hasNext()) {
-        String8 key = keyIt.next();
-        data.writeString8(key);
-        data.writeString8(event.get(key));
-    }
-    const DrmBuffer& value = event.getData();
-    data.writeInt32(value.length);
-    if (value.length > 0) {
-        data.write(value.data, value.length);
-    }
-
     remote()->transact(NOTIFY, data, &reply);
     return reply.readInt32();
 }
@@ -62,24 +49,7 @@
         int type = data.readInt32();
         const String8& message = data.readString8();
 
-        DrmInfoEvent event(uniqueId, type, message);
-        int size = data.readInt32();
-        for (int index = 0; index < size; index++) {
-            String8 key(data.readString8());
-            String8 value(data.readString8());
-            event.put(key, value);
-        }
-        int valueSize = data.readInt32();
-        if (valueSize > 0) {
-            char* valueData = new char[valueSize];
-            data.read(valueData, valueSize);
-            DrmBuffer drmBuffer(valueData, valueSize);
-            event.setData(drmBuffer);
-            delete[] valueData;
-        }
-
-        status_t status = notify(event);
-
+        status_t status = notify(DrmInfoEvent(uniqueId, type, message));
         reply->writeInt32(status);
 
         return DRM_NO_ERROR;
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
index 23b2950..dfca228 100644
--- a/include/drm/DrmInfoEvent.h
+++ b/include/drm/DrmInfoEvent.h
@@ -17,8 +17,6 @@
 #ifndef __DRM_INFO_EVENT_H__
 #define __DRM_INFO_EVENT_H__
 
-#include "drm_framework_common.h"
-
 namespace android {
 
 class String8;
@@ -73,70 +71,18 @@
 
 public:
     /**
-     * Constructor for DrmInfoEvent.
-     * Data in drmBuffer are copied to newly allocated buffer.
+     * Constructor for DrmInfoEvent
      *
      * @param[in] uniqueId Unique session identifier
      * @param[in] infoType Type of information
      * @param[in] message Message description
-     * @param[in] drmBuffer Binary information
      */
     DrmInfoEvent(int uniqueId, int infoType, const String8 message);
-    DrmInfoEvent(int uniqueId, int infoType, const String8 message, const DrmBuffer& drmBuffer);
 
     /**
      * Destructor for DrmInfoEvent
      */
-    ~DrmInfoEvent();
-
-public:
-    /**
-     * Iterator for key
-     */
-    class KeyIterator {
-        friend class DrmInfoEvent;
-
-    private:
-        KeyIterator(const DrmInfoEvent* drmInfoEvent)
-                : mDrmInfoEvent(const_cast <DrmInfoEvent*> (drmInfoEvent)), mIndex(0) {}
-
-    public:
-        KeyIterator(const KeyIterator& keyIterator);
-        KeyIterator& operator=(const KeyIterator& keyIterator);
-        virtual ~KeyIterator() {}
-
-    public:
-        bool hasNext();
-        const String8& next();
-
-    private:
-        DrmInfoEvent* mDrmInfoEvent;
-        unsigned int mIndex;
-    };
-
-    /**
-     * Iterator
-     */
-    class Iterator {
-        friend class DrmInfoEvent;
-
-    private:
-        Iterator(const DrmInfoEvent* drmInfoEvent)
-                : mDrmInfoEvent(const_cast <DrmInfoEvent*> (drmInfoEvent)), mIndex(0) {}
-
-    public:
-        Iterator(const Iterator& iterator);
-        Iterator& operator=(const Iterator& iterator);
-        virtual ~Iterator() {}
-
-    public:
-        bool hasNext();
-        const String8& next();
-
-    private:
-        DrmInfoEvent* mDrmInfoEvent;
-        unsigned int mIndex;
-    };
+    virtual ~DrmInfoEvent() {}
 
 public:
     /**
@@ -160,69 +106,10 @@
      */
     const String8 getMessage() const;
 
-    /**
-     * Returns the number of attributes contained in this instance
-     *
-     * @return Number of attributes
-     */
-    int getCount() const;
-
-    /**
-     * Adds optional information as <key, value> pair to this instance
-     *
-     * @param[in] key Key to add
-     * @param[in] value Value to add
-     * @return Returns the error code
-     */
-    status_t put(const String8& key, String8& value);
-
-    /**
-     * Retrieves the value of given key
-     *
-     * @param key Key whose value to be retrieved
-     * @return The value
-     */
-    const String8 get(const String8& key) const;
-
-    /**
-     * Returns KeyIterator object to walk through the keys associated with this instance
-     *
-     * @return KeyIterator object
-     */
-    KeyIterator keyIterator() const;
-
-    /**
-     * Returns Iterator object to walk through the values associated with this instance
-     *
-     * @return Iterator object
-     */
-    Iterator iterator() const;
-
-    /**
-     * Returns the Binary information associated with this instance
-     *
-     * @return Binary information
-     */
-    const DrmBuffer& getData() const;
-
-    /**
-     * Sets the Binary information associated with this instance.
-     * Data in drmBuffer are copied to newly allocated buffer.
-     *
-     * @param[in] drmBuffer Binary information associated with this instance
-     */
-    void setData(const DrmBuffer& drmBuffer);
-
-private:
-    DrmInfoEvent(const DrmInfoEvent& ref);
-    const DrmInfoEvent& operator=(const DrmInfoEvent& ref);
-
 private:
     int mUniqueId;
     int mInfoType;
     const String8 mMessage;
-    KeyedVector<String8, String8> mAttributes;
-    DrmBuffer mDrmBuffer;
 };
 
 };
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
index 00c4444..2539ed3 100644
--- a/include/media/ExtendedAudioBufferProvider.h
+++ b/include/media/ExtendedAudioBufferProvider.h
@@ -18,12 +18,20 @@
 #define ANDROID_EXTENDED_AUDIO_BUFFER_PROVIDER_H
 
 #include <media/AudioBufferProvider.h>
+#include <media/AudioTimestamp.h>
 
 namespace android {
 
 class ExtendedAudioBufferProvider : public AudioBufferProvider {
 public:
     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; }
+
+    // Invoked by buffer consumer when a new timestamp is available.
+    // Default implementation ignores the timestamp.
+    virtual void    onTimestamp(const AudioTimestamp& timestamp) { }
 };
 
 }   // namespace android
diff --git a/include/media/IHDCP.h b/include/media/IHDCP.h
index 54fefa3..352561e 100644
--- a/include/media/IHDCP.h
+++ b/include/media/IHDCP.h
@@ -46,6 +46,17 @@
     // Request to shutdown the active HDCP session.
     virtual status_t shutdownAsync() = 0;
 
+    // Returns the capability bitmask of this HDCP session.
+    // Possible return values (please refer to HDCAPAPI.h):
+    //   HDCP_CAPS_ENCRYPT: mandatory, meaning the HDCP module can encrypt
+    //   from an input byte-array buffer to an output byte-array buffer
+    //   HDCP_CAPS_ENCRYPT_NATIVE: the HDCP module supports encryption from
+    //   a native buffer to an output byte-array buffer. The format of the
+    //   input native buffer is specific to vendor's encoder implementation.
+    //   It is the same format as that used by the encoder when
+    //   "storeMetaDataInBuffers" extension is enabled on its output port.
+    virtual uint32_t getCaps() = 0;
+
     // ENCRYPTION only:
     // Encrypt data according to the HDCP spec. "size" bytes of data are
     // available at "inData" (virtual address), "size" may not be a multiple
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index 5976b18..7948d40 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -52,6 +52,8 @@
     // implementation of GNWT (if any)
     virtual status_t getNextWriteTimestamp(int64_t *timestamp);
 
+    virtual status_t getTimestamp(AudioTimestamp& timestamp);
+
     // NBAIO_Sink end
 
 #if 0   // until necessary
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
index 5fcfe9e..d3802fe 100644
--- a/include/media/nbaio/MonoPipe.h
+++ b/include/media/nbaio/MonoPipe.h
@@ -20,9 +20,12 @@
 #include <time.h>
 #include <utils/LinearTransform.h>
 #include "NBAIO.h"
+#include <media/SingleStateQueue.h>
 
 namespace android {
 
+typedef SingleStateQueue<AudioTimestamp> AudioTimestampSingleStateQueue;
+
 // MonoPipe is similar to Pipe except:
 //  - supports only a single reader, called MonoPipeReader
 //  - write() cannot overrun; instead it will return a short actual count if insufficient space
@@ -88,6 +91,9 @@
             // Return true if the write side of a pipe is currently shutdown.
             bool    isShutdown();
 
+            // Return NO_ERROR if there is a timestamp available
+            status_t getTimestamp(AudioTimestamp& timestamp);
+
 private:
     // A pair of methods and a helper variable which allows the reader and the
     // writer to update and observe the values of mFront and mNextRdPTS in an
@@ -127,6 +133,10 @@
     LinearTransform mSamplesToLocalTime;
 
     bool            mIsShutdown;    // whether shutdown(true) was called, no barriers are needed
+
+    AudioTimestampSingleStateQueue::Shared      mTimestampShared;
+    AudioTimestampSingleStateQueue::Mutator     mTimestampMutator;
+    AudioTimestampSingleStateQueue::Observer    mTimestampObserver;
 };
 
 }   // namespace android
diff --git a/include/media/nbaio/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
index 0e1c992..78fe867 100644
--- a/include/media/nbaio/MonoPipeReader.h
+++ b/include/media/nbaio/MonoPipeReader.h
@@ -49,6 +49,8 @@
 
     virtual ssize_t read(void *buffer, size_t count, int64_t readPTS);
 
+    virtual void    onTimestamp(const AudioTimestamp& timestamp);
+
     // NBAIO_Source end
 
 #if 0   // until necessary
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index f5d6eb5..1da0c73 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
+#include <media/AudioTimestamp.h>
 
 namespace android {
 
@@ -213,6 +214,11 @@
     //  <other> Something unexpected happened internally.  Check the logs and start debugging.
     virtual status_t getNextWriteTimestamp(int64_t *ts) { return INVALID_OPERATION; }
 
+    // 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.
+    virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; }
+
 protected:
     NBAIO_Sink(NBAIO_Format format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0) { }
     virtual ~NBAIO_Sink() { }
@@ -300,6 +306,10 @@
     virtual ssize_t readVia(readVia_t via, size_t total, void *user,
                             int64_t readPTS, size_t block = 0);
 
+    // Invoked asynchronously by corresponding sink when a new timestamp is available.
+    // Default implementation ignores the timestamp.
+    virtual void    onTimestamp(const AudioTimestamp& timestamp) { }
+
 protected:
     NBAIO_Source(NBAIO_Format format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0) { }
     virtual ~NBAIO_Source() { }
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
index c08331b..cdfb6fe 100644
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -36,6 +36,8 @@
 
     // ExtendedAudioBufferProvider interface
     virtual size_t   framesReady() const;
+    virtual size_t   framesReleased() const;
+    virtual void     onTimestamp(const AudioTimestamp& timestamp);
 
 private:
     const sp<NBAIO_Source> mSource;     // the wrapped source
@@ -45,6 +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
 };
 
 }   // namespace android
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 96755bb..56e7787 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -62,6 +62,7 @@
 LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0)
 LOCAL_SRC_FILES += SingleStateQueue.cpp
 LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"'
+# Consider a separate a library for SingleStateQueueInstantiations.
 
 LOCAL_SHARED_LIBRARIES := \
 	libui liblog libcutils libutils libbinder libsonivox libicuuc libexpat \
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 176197c..744faee 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1714,7 +1714,18 @@
 status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
 {
     AutoMutex lock(mLock);
-    return mAudioTrack->getTimestamp(timestamp);
+    // FIXME not implemented for fast tracks; should use proxy and SSQ
+    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
+        return INVALID_OPERATION;
+    }
+    if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
+        return INVALID_OPERATION;
+    }
+    status_t status = mAudioTrack->getTimestamp(timestamp);
+    if (status == NO_ERROR) {
+        timestamp.mPosition += mProxy->getEpoch();
+    }
+    return status;
 }
 
 String8 AudioTrack::getParameters(const String8& keys)
diff --git a/media/libmedia/IHDCP.cpp b/media/libmedia/IHDCP.cpp
index a46ff91..1cf987a 100644
--- a/media/libmedia/IHDCP.cpp
+++ b/media/libmedia/IHDCP.cpp
@@ -30,6 +30,7 @@
     HDCP_SET_OBSERVER,
     HDCP_INIT_ASYNC,
     HDCP_SHUTDOWN_ASYNC,
+    HDCP_GET_CAPS,
     HDCP_ENCRYPT,
     HDCP_ENCRYPT_NATIVE,
     HDCP_DECRYPT,
@@ -85,6 +86,13 @@
         return reply.readInt32();
     }
 
+    virtual uint32_t getCaps() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
+        remote()->transact(HDCP_GET_CAPS, data, &reply);
+        return reply.readInt32();
+    }
+
     virtual status_t encrypt(
             const void *inData, size_t size, uint32_t streamCTR,
             uint64_t *outInputCTR, void *outData) {
@@ -222,6 +230,14 @@
             return OK;
         }
 
+        case HDCP_GET_CAPS:
+        {
+            CHECK_INTERFACE(IHDCP, data, reply);
+
+            reply->writeInt32(getCaps());
+            return OK;
+        }
+
         case HDCP_ENCRYPT:
         {
             size_t size = data.readInt32();
diff --git a/media/libmedia/SingleStateQueueInstantiations.cpp b/media/libmedia/SingleStateQueueInstantiations.cpp
index 2afebe9..0265c8c 100644
--- a/media/libmedia/SingleStateQueueInstantiations.cpp
+++ b/media/libmedia/SingleStateQueueInstantiations.cpp
@@ -16,11 +16,13 @@
 
 #include <media/SingleStateQueue.h>
 #include <private/media/StaticAudioTrackState.h>
+#include <media/AudioTimestamp.h>
 
 // FIXME hack for gcc
 
 namespace android {
 
 template class SingleStateQueue<StaticAudioTrackState>; // typedef StaticAudioTrackSingleStateQueue
+template class SingleStateQueue<AudioTimestamp>;        // typedef AudioTimestampSingleStateQueue
 
 }
diff --git a/media/libmediaplayerservice/HDCP.cpp b/media/libmediaplayerservice/HDCP.cpp
index 8a3188c..c2ac1a3 100644
--- a/media/libmediaplayerservice/HDCP.cpp
+++ b/media/libmediaplayerservice/HDCP.cpp
@@ -100,6 +100,20 @@
     return mHDCPModule->shutdownAsync();
 }
 
+uint32_t HDCP::getCaps() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mHDCPModule == NULL) {
+        return NO_INIT;
+    }
+
+    // TO-DO:
+    // Only support HDCP_CAPS_ENCRYPT (byte-array to byte-array) for now.
+    // use mHDCPModule->getCaps() when the HDCP libraries get updated.
+    //return mHDCPModule->getCaps();
+    return HDCPModule::HDCP_CAPS_ENCRYPT;
+}
+
 status_t HDCP::encrypt(
         const void *inData, size_t size, uint32_t streamCTR,
         uint64_t *outInputCTR, void *outData) {
diff --git a/media/libmediaplayerservice/HDCP.h b/media/libmediaplayerservice/HDCP.h
index c60c2e0..26ddc86 100644
--- a/media/libmediaplayerservice/HDCP.h
+++ b/media/libmediaplayerservice/HDCP.h
@@ -30,6 +30,7 @@
     virtual status_t setObserver(const sp<IHDCPObserver> &observer);
     virtual status_t initAsync(const char *host, unsigned port);
     virtual status_t shutdownAsync();
+    virtual uint32_t getCaps();
 
     virtual status_t encrypt(
             const void *inData, size_t size, uint32_t streamCTR,
diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk
index 5d00d15..69c75b8 100644
--- a/media/libnbaio/Android.mk
+++ b/media/libnbaio/Android.mk
@@ -31,6 +31,9 @@
     libcommon_time_client \
     libcutils \
     libutils \
-    liblog
+    liblog \
+    libmedia
+# This dependency on libmedia is for SingleStateQueueInstantiations.
+# Consider a separate a library for SingleStateQueueInstantiations.
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index 6f525e5..e4341d7 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -79,4 +79,19 @@
     return mStream->get_next_write_timestamp(mStream, timestamp);
 }
 
+status_t AudioStreamOutSink::getTimestamp(AudioTimestamp& 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) {
+        return INVALID_OPERATION;
+    }
+    timestamp.mPosition = position64;
+    return OK;
+}
+
 }   // namespace android
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index e8d3d9b..de0ad28 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -42,7 +42,10 @@
         // mWriteTs
         mSetpoint((reqFrames * 11) / 16),
         mWriteCanBlock(writeCanBlock),
-        mIsShutdown(false)
+        mIsShutdown(false),
+        // mTimestampShared
+        mTimestampMutator(&mTimestampShared),
+        mTimestampObserver(&mTimestampShared)
 {
     CCHelper tmpHelper;
     status_t res;
@@ -310,4 +313,12 @@
     return mIsShutdown;
 }
 
+status_t MonoPipe::getTimestamp(AudioTimestamp& timestamp)
+{
+    if (mTimestampObserver.poll(timestamp)) {
+        return OK;
+    }
+    return INVALID_OPERATION;
+}
+
 }   // namespace android
diff --git a/media/libnbaio/MonoPipeReader.cpp b/media/libnbaio/MonoPipeReader.cpp
index 394f6ac..851341a 100644
--- a/media/libnbaio/MonoPipeReader.cpp
+++ b/media/libnbaio/MonoPipeReader.cpp
@@ -86,4 +86,9 @@
     return red;
 }
 
+void MonoPipeReader::onTimestamp(const AudioTimestamp& timestamp)
+{
+    mPipe->mTimestampMutator.push(timestamp);
+}
+
 }   // namespace android
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index d11a86c..062fa0f 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -25,7 +25,7 @@
 SourceAudioBufferProvider::SourceAudioBufferProvider(const sp<NBAIO_Source>& source) :
     mSource(source),
     // mFrameBitShiftFormat below
-    mAllocated(NULL), mSize(0), mOffset(0), mRemaining(0), mGetCount(0)
+    mAllocated(NULL), mSize(0), mOffset(0), mRemaining(0), mGetCount(0), mFramesReleased(0)
 {
     ALOG_ASSERT(source != 0);
 
@@ -90,6 +90,7 @@
             (mOffset + mRemaining <= mSize));
     mOffset += buffer->frameCount;
     mRemaining -= buffer->frameCount;
+    mFramesReleased += buffer->frameCount;
     buffer->raw = NULL;
     buffer->frameCount = 0;
     mGetCount = 0;
@@ -101,4 +102,14 @@
     return avail < 0 ? 0 : (size_t) avail;
 }
 
+size_t SourceAudioBufferProvider::framesReleased() const
+{
+    return mFramesReleased;
+}
+
+void SourceAudioBufferProvider::onTimestamp(const AudioTimestamp& timestamp)
+{
+    mSource->onTimestamp(timestamp);
+}
+
 }   // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f412dc8..66a0b4e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -106,6 +106,8 @@
         needDedicatedLooper = true;
     } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
         needDedicatedLooper = true;
+    } else if (!nameIsType && !strncmp(name, "OMX.qcom.video.decoder.avc.secure", 33)) {
+        needDedicatedLooper = true;
     }
 
     if (needDedicatedLooper) {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 5749733..ff2b503 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -292,6 +292,10 @@
         return AOT_AAC_LC;
     } else if (profile == OMX_AUDIO_AACObjectHE) {
         return AOT_SBR;
+    } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
+        return AOT_PS;
+    } else if (profile == OMX_AUDIO_AACObjectLD) {
+        return AOT_ER_AAC_LD;
     } else if (profile == OMX_AUDIO_AACObjectELD) {
         return AOT_ER_AAC_ELD;
     } else {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 9f3b19c..8f9c9c8 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -504,15 +504,11 @@
 
         if (first) {
             timeUs = info->mTimestampUs;
+            first = false;
         }
 
         if (info->mLength > size) {
             info->mLength -= size;
-
-            if (first) {
-                info->mTimestampUs = -1;
-            }
-
             size = 0;
         } else {
             size -= info->mLength;
@@ -521,7 +517,6 @@
             info = NULL;
         }
 
-        first = false;
     }
 
     if (timeUs == 0ll) {
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 0aa4ee5..286ea13 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -939,7 +939,8 @@
     if (isVideo) {
         format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
         format->setInt32("store-metadata-in-buffers", true);
-        format->setInt32("store-metadata-in-buffers-output", (mHDCP != NULL));
+        format->setInt32("store-metadata-in-buffers-output", (mHDCP != NULL)
+                && (mHDCP->getCaps() & HDCPModule::HDCP_CAPS_ENCRYPT_NATIVE));
         format->setInt32(
                 "color-format", OMX_COLOR_FormatAndroidOpaque);
         format->setInt32("profile-idc", profileIdc);
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index ad9f4f2..f27ea17 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -96,6 +96,12 @@
     uint32_t warmupCycles = 0;  // counter of number of loop cycles required to warmup
     NBAIO_Sink* teeSink = NULL; // if non-NULL, then duplicate write() to this non-blocking sink
     NBLog::Writer dummyLogWriter, *logWriter = &dummyLogWriter;
+    uint32_t totalNativeFramesWritten = 0;  // copied to dumpState->mFramesWritten
+
+    // next 2 fields are valid only when timestampStatus == NO_ERROR
+    AudioTimestamp timestamp;
+    uint32_t nativeFramesWrittenButNotPresented = 0;    // the = 0 is to silence the compiler
+    status_t timestampStatus = INVALID_OPERATION;
 
     for (;;) {
 
@@ -192,6 +198,7 @@
                 full = false;
 #endif
                 oldTsValid = !clock_gettime(CLOCK_MONOTONIC, &oldTs);
+                timestampStatus = INVALID_OPERATION;
             } else {
                 sleepNs = FAST_HOT_IDLE_NS;
             }
@@ -382,6 +389,31 @@
                 i = __builtin_ctz(currentTrackMask);
                 currentTrackMask &= ~(1 << i);
                 const FastTrack* fastTrack = &current->mFastTracks[i];
+
+                // Refresh the per-track timestamp
+                if (timestampStatus == NO_ERROR) {
+                    uint32_t trackFramesWrittenButNotPresented;
+                    uint32_t trackSampleRate = fastTrack->mSampleRate;
+                    // There is currently no sample rate conversion for fast tracks currently
+                    if (trackSampleRate != 0 && trackSampleRate != sampleRate) {
+                        trackFramesWrittenButNotPresented =
+                                ((int64_t) nativeFramesWrittenButNotPresented * trackSampleRate) /
+                                sampleRate;
+                    } else {
+                        trackFramesWrittenButNotPresented = nativeFramesWrittenButNotPresented;
+                    }
+                    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 = timestamp.mTime;
+                        fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
+                    }
+                }
+
                 int name = fastTrackNames[i];
                 ALOG_ASSERT(name >= 0);
                 if (fastTrack->mVolumeProvider != NULL) {
@@ -455,7 +487,8 @@
             dumpState->mWriteSequence++;
             if (framesWritten >= 0) {
                 ALOG_ASSERT((size_t) framesWritten <= frameCount);
-                dumpState->mFramesWritten += framesWritten;
+                totalNativeFramesWritten += framesWritten;
+                dumpState->mFramesWritten = totalNativeFramesWritten;
                 //if ((size_t) framesWritten == frameCount) {
                 //    didFullWrite = true;
                 //}
@@ -464,6 +497,18 @@
             }
             attemptedWrite = true;
             // FIXME count # of writes blocked excessively, CPU usage, etc. for dump
+
+            timestampStatus = outputSink->getTimestamp(timestamp);
+            if (timestampStatus == NO_ERROR) {
+                uint32_t totalNativeFramesPresented = timestamp.mPosition;
+                if (totalNativeFramesPresented <= totalNativeFramesWritten) {
+                    nativeFramesWrittenButNotPresented =
+                        totalNativeFramesWritten - totalNativeFramesPresented;
+                } else {
+                    // HAL reported that more frames were presented than were written
+                    timestampStatus = INVALID_OPERATION;
+                }
+            }
         }
 
         // To be exactly periodic, compute the next sleep time based on current time.
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index d34833f..0308b99 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -81,7 +81,9 @@
                                    int64_t pts = kInvalidPTS);
     // releaseBuffer() not overridden
 
+    // ExtendedAudioBufferProvider interface
     virtual size_t framesReady() const;
+    virtual size_t framesReleased() const;
 
     bool isPausing() const { return mState == PAUSING; }
     bool isPaused() const { return mState == PAUSED; }
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3921b68..fda4211 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1820,7 +1820,7 @@
         } else {
             bytesWritten = framesWritten;
         }
-        status_t status = INVALID_OPERATION;    // mLatchD.mTimestamp is invalid
+        status_t status = mNormalSink->getTimestamp(mLatchD.mTimestamp);
         if (status == NO_ERROR) {
             size_t totalFramesWritten = mNormalSink->framesWritten();
             if (totalFramesWritten >= mLatchD.mTimestamp.mPosition) {
@@ -1837,6 +1837,8 @@
             ALOG_ASSERT(mCallbackThread != 0);
             mCallbackThread->setWriteBlocked(true);
         }
+        // FIXME We should have an implementation of timestamps for direct output threads.
+        // They are used e.g for multichannel PCM playback over HDMI.
         bytesWritten = mOutput->stream->write(mOutput->stream,
                                                    mMixBuffer + offset, mBytesRemaining);
         if (mUseAsyncWrite &&
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9622709..2042050 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -498,6 +498,10 @@
     return status;
 }
 
+// releaseBuffer() is not overridden
+
+// ExtendedAudioBufferProvider interface
+
 // Note that framesReady() takes a mutex on the control block using tryLock().
 // This could result in priority inversion if framesReady() is called by the normal mixer,
 // as the normal mixer thread runs at lower
@@ -510,6 +514,11 @@
     return mAudioTrackServerProxy->framesReady();
 }
 
+size_t AudioFlinger::PlaybackThread::Track::framesReleased() const
+{
+    return mAudioTrackServerProxy->framesReleased();
+}
+
 // Don't call for fast tracks; the framesReady() could result in priority inversion
 bool AudioFlinger::PlaybackThread::Track::isReady() const {
     if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
@@ -718,9 +727,13 @@
 
 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;
+    }
     sp<ThreadBase> thread = mThread.promote();
     if (thread == 0) {
-        return false;
+        return INVALID_OPERATION;
     }
     Mutex::Autolock _l(thread->mLock);
     PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index bf9bc71..fe16314 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -492,7 +492,7 @@
           case CAMERA_DEVICE_API_VERSION_1_0:
             ALOGE("Camera id %d uses HALv1, doesn't support ProCamera",
                   cameraId);
-            return -ENOTSUP;
+            return -EOPNOTSUPP;
             break;
           case CAMERA_DEVICE_API_VERSION_2_0:
           case CAMERA_DEVICE_API_VERSION_2_1:
@@ -570,7 +570,7 @@
         switch(deviceVersion) {
           case CAMERA_DEVICE_API_VERSION_1_0:
             ALOGW("Camera using old HAL version: %d", deviceVersion);
-            return -ENOTSUP;
+            return -EOPNOTSUPP;
            // TODO: don't allow 2.0  Only allow 2.1 and higher
           case CAMERA_DEVICE_API_VERSION_2_0:
           case CAMERA_DEVICE_API_VERSION_2_1:
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
index 76750aa..7ad461a 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
@@ -100,7 +100,7 @@
      * Internal to CaptureSequencer
      */
     static const nsecs_t kWaitDuration = 100000000; // 100 ms
-    static const int kMaxTimeoutsForPrecaptureStart = 2; // 200 ms
+    static const int kMaxTimeoutsForPrecaptureStart = 10; // 1 sec
     static const int kMaxTimeoutsForPrecaptureEnd = 20;  // 2 sec
     static const int kMaxTimeoutsForCaptureEnd    = 40;  // 4 sec