Merge "Replace direct pid writes with setting task profiles" into rvc-dev
diff --git a/media/bufferpool/2.0/Accessor.cpp b/media/bufferpool/2.0/Accessor.cpp
index 57b4609..e05b12a 100644
--- a/media/bufferpool/2.0/Accessor.cpp
+++ b/media/bufferpool/2.0/Accessor.cpp
@@ -117,6 +117,10 @@
     Accessor::Impl::createInvalidator();
 }
 
+void Accessor::createEvictor() {
+    Accessor::Impl::createEvictor();
+}
+
 // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow.
 Return<void> Accessor::connect(
         const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer,
diff --git a/media/bufferpool/2.0/Accessor.h b/media/bufferpool/2.0/Accessor.h
index 8d02519..8b43301 100644
--- a/media/bufferpool/2.0/Accessor.h
+++ b/media/bufferpool/2.0/Accessor.h
@@ -187,6 +187,8 @@
 
     static void createInvalidator();
 
+    static void createEvictor();
+
 private:
     class Impl;
     std::shared_ptr<Impl> mImpl;
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index cb55b07..51d9a69 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -39,6 +39,9 @@
 
     static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
     static constexpr size_t kMinBufferCountForEviction = 25;
+
+    static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
+    static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
 }
 
 // Buffer structure in bufferpool process
@@ -146,7 +149,7 @@
 
 Accessor::Impl::Impl(
         const std::shared_ptr<BufferPoolAllocator> &allocator)
-        : mAllocator(allocator) {}
+        : mAllocator(allocator), mScheduleEvictTs(0) {}
 
 Accessor::Impl::~Impl() {
 }
@@ -184,6 +187,7 @@
         }
         mBufferPool.processStatusMessages();
         mBufferPool.cleanUp();
+        scheduleEvictIfNeeded();
     }
     return status;
 }
@@ -198,6 +202,7 @@
     // Since close# will be called after all works are finished, it is OK to
     // evict unused buffers.
     mBufferPool.cleanUp(true);
+    scheduleEvictIfNeeded();
     return ResultStatus::OK;
 }
 
@@ -224,6 +229,7 @@
         mBufferPool.handleOwnBuffer(connectionId, *bufferId);
     }
     mBufferPool.cleanUp();
+    scheduleEvictIfNeeded();
     return status;
 }
 
@@ -249,6 +255,7 @@
         }
     }
     mBufferPool.cleanUp();
+    scheduleEvictIfNeeded();
     return ResultStatus::CRITICAL_ERROR;
 }
 
@@ -891,6 +898,88 @@
     }
 }
 
+void Accessor::Impl::evictorThread(
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors,
+        std::mutex &mutex,
+        std::condition_variable &cv) {
+    std::list<const std::weak_ptr<Accessor::Impl>> evictList;
+    while (true) {
+        int expired = 0;
+        int evicted = 0;
+        {
+            nsecs_t now = systemTime();
+            std::unique_lock<std::mutex> lock(mutex);
+            if (accessors.size() == 0) {
+                cv.wait(lock);
+            }
+            auto it = accessors.begin();
+            while (it != accessors.end()) {
+                if (now > (it->second + kEvictDurationNs)) {
+                    ++expired;
+                    evictList.push_back(it->first);
+                    it = accessors.erase(it);
+                } else {
+                    ++it;
+                }
+            }
+        }
+        // evict idle accessors;
+        for (auto it = evictList.begin(); it != evictList.end(); ++it) {
+            const std::shared_ptr<Accessor::Impl> accessor = it->lock();
+            if (accessor) {
+                accessor->cleanUp(true);
+                ++evicted;
+            }
+        }
+        if (expired > 0) {
+            ALOGD("evictor expired: %d, evicted: %d", expired, evicted);
+        }
+        evictList.clear();
+        ::usleep(kEvictGranularityNs / 1000);
+    }
+}
+
+Accessor::Impl::AccessorEvictor::AccessorEvictor() {
+    std::thread evictor(
+            evictorThread,
+            std::ref(mAccessors),
+            std::ref(mMutex),
+            std::ref(mCv));
+    evictor.detach();
+}
+
+void Accessor::Impl::AccessorEvictor::addAccessor(
+        const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    bool notify = mAccessors.empty();
+    auto it = mAccessors.find(impl);
+    if (it == mAccessors.end()) {
+        mAccessors.emplace(impl, ts);
+    } else {
+        it->second = ts;
+    }
+    if (notify) {
+        mCv.notify_one();
+    }
+}
+
+std::unique_ptr<Accessor::Impl::AccessorEvictor> Accessor::Impl::sEvictor;
+
+void Accessor::Impl::createEvictor() {
+    if (!sEvictor) {
+        sEvictor = std::make_unique<Accessor::Impl::AccessorEvictor>();
+    }
+}
+
+void Accessor::Impl::scheduleEvictIfNeeded() {
+    nsecs_t now = systemTime();
+
+    if (now > (mScheduleEvictTs + kEvictGranularityNs)) {
+        mScheduleEvictTs = now;
+        sEvictor->addAccessor(shared_from_this(), now);
+    }
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace bufferpool
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index 9888be5..cd1b4d0 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -20,6 +20,7 @@
 #include <map>
 #include <set>
 #include <condition_variable>
+#include <utils/Timers.h>
 #include "Accessor.h"
 
 namespace android {
@@ -71,6 +72,8 @@
 
     static void createInvalidator();
 
+    static void createEvictor();
+
 private:
     // ConnectionId = pid : (timestamp_created + seqId)
     // in order to guarantee uniqueness for each connection
@@ -78,6 +81,8 @@
 
     const std::shared_ptr<BufferPoolAllocator> mAllocator;
 
+    nsecs_t mScheduleEvictTs;
+
     /**
      * Buffer pool implementation.
      *
@@ -389,6 +394,25 @@
         std::mutex &mutex,
         std::condition_variable &cv,
         bool &ready);
+
+    struct AccessorEvictor {
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> mAccessors;
+        std::mutex mMutex;
+        std::condition_variable mCv;
+
+        AccessorEvictor();
+        void addAccessor(const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts);
+    };
+
+    static std::unique_ptr<AccessorEvictor> sEvictor;
+
+    static void evictorThread(
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors,
+        std::mutex &mutex,
+        std::condition_variable &cv);
+
+    void scheduleEvictIfNeeded();
+
 };
 
 }  // namespace implementation
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/bufferpool/2.0/ClientManager.cpp
index 87ee4e8..54a20b9 100644
--- a/media/bufferpool/2.0/ClientManager.cpp
+++ b/media/bufferpool/2.0/ClientManager.cpp
@@ -484,6 +484,7 @@
         sInstance = new ClientManager();
     }
     Accessor::createInvalidator();
+    Accessor::createEvictor();
     return sInstance;
 }
 
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 01d106f..1e4560c 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1406,6 +1406,9 @@
         // TODO: convert err into status_t
         mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
     }
+    // Assure buffers are not owned when stop() was called without flush().
+    std::list<std::unique_ptr<C2Work>> flushedWork;
+    mChannel->flush(flushedWork);
 
     {
         Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index 679b091..a11f55e 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -409,7 +409,9 @@
         if (!BitstreamRead1Bits(stream)) return PV_FAIL;
 
         /* video_object_layer_width (13 bits) */
-        video->displayWidth = video->width = (int) BitstreamReadBits16(stream, 13);
+        tmpvar = BitstreamReadBits16(stream, 13);
+        if (!tmpvar) return PV_FAIL;
+        video->displayWidth = video->width = tmpvar;
 
         /* round up to a multiple of MB_SIZE.   08/09/2000 */
         video->width = (video->width + 15) & -16;
@@ -419,7 +421,9 @@
         if (!BitstreamRead1Bits(stream)) return PV_FAIL;
 
         /* video_object_layer_height (13 bits) */
-        video->displayHeight = video->height = (int) BitstreamReadBits16(stream, 13);
+        tmpvar = BitstreamReadBits16(stream, 13);
+        if (!tmpvar) return PV_FAIL;
+        video->displayHeight = video->height = tmpvar;
 
         /* round up to a multiple of MB_SIZE.   08/09/2000 */
         video->height = (video->height + 15) & -16;
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 657144c..4bb21fa 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1153,7 +1153,7 @@
     }
 
     const RangeInfo &info = *mRangeInfos.begin();
-    if (mBuffer->size() < info.mLength) {
+    if (info.mLength == 0 || mBuffer->size() < info.mLength) {
         return NULL;
     }