Merge "Remove unneeded dependencies from libsfplugin_ccodec"
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
index 53b3d84..cef8ef5 100644
--- a/camera/cameraserver/main_cameraserver.cpp
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -34,6 +34,7 @@
     sp<IServiceManager> sm = defaultServiceManager();
     ALOGI("ServiceManager: %p", sm.get());
     CameraService::instantiate();
+    ALOGI("ServiceManager: %p done instantiate", sm.get());
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
 }
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index d74bc53..0c74a6c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -797,7 +797,8 @@
 }
 
 Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
-    if (ssRelease.opaqueData.size() == 0) {
+    // minimum opaqueData contains the uint32_t count, see comment below
+    if (ssRelease.opaqueData.size() < sizeof(uint32_t)) {
         return Status::BAD_VALUE;
     }
 
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 36137e6..c7046cb 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -29,6 +29,8 @@
 
 namespace android {
 
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
+
 // codecname set and passed in as a compile flag from Android.bp
 constexpr char COMPONENT_NAME[] = CODECNAME;
 
@@ -112,7 +114,7 @@
         addParameter(
             DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
                 .withDefault(
-                    new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                    new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -192,8 +194,8 @@
         const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 63) / 64) *
-                          ((maxSize.v.height + 63) / 64) * 3072);
+        me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+                * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
         return C2R::Ok();
     }
     static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index fa98178..2662f0f 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -31,7 +31,7 @@
 namespace android {
 
 namespace {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder";
 constexpr uint32_t kDefaultOutputDelay = 8;
 constexpr uint32_t kMaxOutputDelay = 16;
@@ -114,7 +114,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -227,7 +227,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 192);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 192), kMinInputBufferSize);
         return C2R::Ok();
     }
 
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index a1f8ff3..e0365fc 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -29,7 +29,7 @@
 #include "impeg2d.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 constexpr char COMPONENT_NAME[] = "c2.android.mpeg2.decoder";
 
 class C2SoftMpeg2Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -99,7 +99,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 2))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -213,7 +213,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 1
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 384), kMinInputBufferSize);
         return C2R::Ok();
     }
 
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 7e6685e..61b286c 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -33,7 +33,7 @@
 #include "mp4dec_api.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 #ifdef MPEG4
 constexpr char COMPONENT_NAME[] = "c2.android.mpeg4.decoder";
 #else
@@ -149,11 +149,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-#ifdef MPEG4
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 1920 * 1088 * 3 / 2))
-#else
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 352 * 288 * 3 / 2))
-#endif
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -218,7 +214,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 1
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 384), kMinInputBufferSize);
         return C2R::Ok();
     }
 
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index a52ca15..62076f8 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -30,7 +30,7 @@
 #include "C2SoftVpxDec.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 #ifdef VP9
 constexpr char COMPONENT_NAME[] = "c2.android.vp9.decoder";
 #else
@@ -166,7 +166,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -244,7 +244,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072);
+        me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+                * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
         return C2R::Ok();
     }
 
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 50a3c63..4de6535 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -189,7 +189,6 @@
         "libmedia_omx_client",
         "libaudioclient",
         "libmediametrics",
-        "libmediautils",
         "libui",
         "libutils",
         "libmedia_helper",
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 591b9e9..de9d12c 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -1382,7 +1382,7 @@
     mCaptureFps = captureFps;
     if (captureFps > fps) {
         mSnapTimestamps = 1 == base::GetIntProperty(
-                "debug.stagefright.snap_timestamps", int64_t(1));
+                "debug.stagefright.snap_timestamps", int64_t(0));
     } else {
         mSnapTimestamps = false;
     }
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index 64ea1ee..527f588 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -23,7 +23,7 @@
 
     srcs: [
         "BenchmarkCommon.cpp",
-        "Timer.cpp",
+        "Stats.cpp",
     ],
 
     export_include_dirs: ["."],
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
index bbc8790..5bdb48a 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
@@ -31,7 +31,7 @@
 void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index) {
     ALOGV("OnInputAvailableCB: index(%d)", index);
     CallBackHandle *self = (CallBackHandle *)userdata;
-    self->getTimer()->addInputTime();
+    self->getStats()->addInputTime();
     self->mIOQueue.push([self, codec, index]() { self->onInputAvailable(codec, index); });
 }
 
@@ -40,7 +40,7 @@
     ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)", index, bufferInfo->offset,
           bufferInfo->size, (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
     CallBackHandle *self = (CallBackHandle *)userdata;
-    self->getTimer()->addOutputTime();
+    self->getStats()->addOutputTime();
     AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
     self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
         AMediaCodecBufferInfo bc = bufferInfoCopy;
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index 7b87c04..df16baf 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.h
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -27,7 +27,7 @@
 #include <media/NdkMediaCodec.h>
 #include <media/NdkMediaError.h>
 
-#include "Timer.h"
+#include "Stats.h"
 
 using namespace std;
 
@@ -69,11 +69,13 @@
 
 class CallBackHandle {
   public:
-    CallBackHandle() : mSawError(false), mIsDone(false), mTimer(nullptr) {}
+    CallBackHandle() : mSawError(false), mIsDone(false), mStats(nullptr) {
+        mStats = new Stats();
+    }
 
     virtual ~CallBackHandle() {
         if (mIOThread.joinable()) mIOThread.join();
-        if (mTimer) delete mTimer;
+        if (mStats) delete mStats;
     }
 
     void ioThread();
@@ -94,7 +96,7 @@
         (void)bufferInfo;
     }
 
-    virtual Timer *getTimer() { return mTimer; }
+    Stats *getStats() { return mStats; }
 
     // Keep a queue of all function callbacks.
     typedef function<void()> IOTask;
@@ -103,8 +105,8 @@
     bool mSawError;
     bool mIsDone;
 
-  private:
-    Timer *mTimer;
+  protected:
+    Stats *mStats;
 };
 
 // Async API's callback
diff --git a/media/tests/benchmark/src/native/common/Timer.cpp b/media/tests/benchmark/src/native/common/Stats.cpp
similarity index 90%
rename from media/tests/benchmark/src/native/common/Timer.cpp
rename to media/tests/benchmark/src/native/common/Stats.cpp
index 0487123..6bcd3ce 100644
--- a/media/tests/benchmark/src/native/common/Timer.cpp
+++ b/media/tests/benchmark/src/native/common/Stats.cpp
@@ -15,13 +15,13 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "Timer"
+#define LOG_TAG "Stats"
 
 #include <iostream>
 #include <stdint.h>
 #include <utils/Log.h>
 
-#include "Timer.h"
+#include "Stats.h"
 
 /**
  * Dumps the stats of the operation for a given input media.
@@ -31,7 +31,7 @@
  * \param inputReference input media
  * \param duarationUs    is a duration of the input media in microseconds.
  */
-void Timer::dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs) {
+void Stats::dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs) {
     ALOGV("In %s", __func__);
     if (!mOutputTimer.size()) {
         ALOGE("No output produced");
@@ -40,6 +40,7 @@
     nsecs_t totalTimeTakenNs = getTotalTime();
     nsecs_t timeTakenPerSec = (totalTimeTakenNs * 1000000) / duarationUs;
     nsecs_t timeToFirstFrameNs = *mOutputTimer.begin() - mStartTimeNs;
+    int32_t size = std::accumulate(mFrameSizes.begin(), mFrameSizes.end(), 0);
     // get min and max output intervals.
     nsecs_t intervalNs;
     nsecs_t minTimeTakenNs = INT64_MAX;
@@ -59,6 +60,7 @@
     std::cout << "Time to first frame in nano sec : " << timeToFirstFrameNs << endl;
     std::cout << "Time taken (in nano sec) to " << operation
               << " 1 sec of content : " << timeTakenPerSec << endl;
+    std::cout << "Total bytes " << operation << "ed : " << size << endl;
     std::cout << "Minimum Time in nano sec : " << minTimeTakenNs << endl;
     std::cout << "Maximum Time in nano sec : " << maxTimeTakenNs << endl;
     std::cout << "Destroy Time in nano sec : " << mDeInitTimeNs << endl;
diff --git a/media/tests/benchmark/src/native/common/Timer.h b/media/tests/benchmark/src/native/common/Stats.h
similarity index 86%
rename from media/tests/benchmark/src/native/common/Timer.h
rename to media/tests/benchmark/src/native/common/Stats.h
index 92af86f..024319a 100644
--- a/media/tests/benchmark/src/native/common/Timer.h
+++ b/media/tests/benchmark/src/native/common/Stats.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __TIMER_H__
-#define __TIMER_H__
+#ifndef __STATS_H__
+#define __STATS_H__
 
 #include <sys/time.h>
 #include <algorithm>
@@ -25,22 +25,22 @@
 
 using namespace std;
 
-class Timer {
+class Stats {
   public:
-    Timer() {
+    Stats() {
         mInitTimeNs = 0;
         mDeInitTimeNs = 0;
     }
 
-    ~Timer() {
-        if (!mInputTimer.empty()) mInputTimer.clear();
-        if (!mOutputTimer.empty()) mOutputTimer.clear();
+    ~Stats() {
+        reset();
     }
 
   private:
     nsecs_t mInitTimeNs;
     nsecs_t mDeInitTimeNs;
     nsecs_t mStartTimeNs;
+    std::vector<int32_t> mFrameSizes;
     std::vector<nsecs_t> mInputTimer;
     std::vector<nsecs_t> mOutputTimer;
 
@@ -53,11 +53,14 @@
 
     void setStartTime() { mStartTimeNs = systemTime(CLOCK_MONOTONIC); }
 
+    void addFrameSize(int32_t size) { mFrameSizes.push_back(size); }
+
     void addInputTime() { mInputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
 
     void addOutputTime() { mOutputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
 
-    void resetTimers() {
+    void reset() {
+        if (!mFrameSizes.empty()) mFrameSizes.clear();
         if (!mInputTimer.empty()) mInputTimer.clear();
         if (!mOutputTimer.empty()) mOutputTimer.clear();
     }
@@ -78,4 +81,4 @@
     void dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs);
 };
 
-#endif  // __TIMER_H__
+#endif  // __STATS_H__
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
index eeea60f..ef84537 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -81,6 +81,7 @@
             mDecoderDoneCondition.notify_one();
             return;
         }
+        mStats->addFrameSize(bytesRead);
         mNumInputFrame++;
     }
 }
@@ -128,7 +129,6 @@
 
 void Decoder::setupDecoder() {
     if (!mFormat) mFormat = mExtractor->getFormat();
-    if (!mTimer) mTimer = new Timer();
 }
 
 int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
@@ -143,7 +143,7 @@
     AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
     if (!mime) return AMEDIA_ERROR_INVALID_OBJECT;
 
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     mCodec = createMediaCodec(mFormat, mime, codecName, false /*isEncoder*/);
     if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
 
@@ -152,16 +152,15 @@
                                                 OnFormatChangedCB, OnErrorCB};
         AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
 
-        CallBackHandle *callbackHandle = new CallBackHandle();
-        callbackHandle->mIOThread = thread(&CallBackHandle::ioThread, this);
+        mIOThread = thread(&CallBackHandle::ioThread, this);
     }
 
     AMediaCodec_start(mCodec);
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
 
-    mTimer->setStartTime();
+    mStats->setStartTime();
     if (!asyncMode) {
         while (!mSawOutputEOS && !mSignalledError) {
             /* Queue input data */
@@ -171,7 +170,7 @@
                     ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
                     return AMEDIA_ERROR_IO;
                 } else if (inIdx >= 0) {
-                    mTimer->addInputTime();
+                    mStats->addInputTime();
                     onInputAvailable(mCodec, inIdx);
                 }
             }
@@ -184,7 +183,7 @@
                 const char *s = AMediaFormat_toString(mFormat);
                 ALOGI("Output format: %s\n", s);
             } else if (outIdx >= 0) {
-                mTimer->addOutputTime();
+                mStats->addOutputTime();
                 onOutputAvailable(mCodec, outIdx, &info);
             } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
                          outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
@@ -207,7 +206,7 @@
 }
 
 void Decoder::deInitCodec() {
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     if (mFormat) {
         AMediaFormat_delete(mFormat);
         mFormat = nullptr;
@@ -215,19 +214,19 @@
     if (!mCodec) return;
     AMediaCodec_stop(mCodec);
     AMediaCodec_delete(mCodec);
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setDeInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
 }
 
 void Decoder::dumpStatistics(string inputReference) {
     int64_t durationUs = mExtractor->getClipDuration();
     string operation = "decode";
-    mTimer->dumpStatistics(operation, inputReference, durationUs);
+    mStats->dumpStatistics(operation, inputReference, durationUs);
 }
 
 void Decoder::resetDecoder() {
-    if (mTimer) mTimer->resetTimers();
+    if (mStats) mStats->reset();
     if (mInputBuffer) mInputBuffer = nullptr;
     if (!mFrameMetaData.empty()) mFrameMetaData.clear();
 }
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
index 7f64de3..7630e7b 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -25,7 +25,7 @@
 
 #include "BenchmarkCommon.h"
 #include "Extractor.h"
-#include "Timer.h"
+#include "Stats.h"
 
 class Decoder : public CallBackHandle {
   public:
@@ -33,7 +33,6 @@
         : mCodec(nullptr),
           mFormat(nullptr),
           mExtractor(nullptr),
-          mTimer(nullptr),
           mNumInputFrame(0),
           mNumOutputFrame(0),
           mSawInputEOS(false),
@@ -45,12 +44,9 @@
     }
 
     virtual ~Decoder() {
-        if (mTimer) delete mTimer;
         if (mExtractor) delete mExtractor;
     }
 
-    Timer *getTimer() override { return mTimer; }
-
     Extractor *getExtractor() { return mExtractor; }
 
     // Decoder related utilities
@@ -80,8 +76,6 @@
 
     Extractor *mExtractor;
 
-    Timer *mTimer;
-
     int32_t mNumInputFrame;
     int32_t mNumOutputFrame;
 
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
index 73a559a..5fdf9e3 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -112,6 +112,7 @@
             return;
         }
 
+        mStats->addFrameSize(bufferInfo->size);
         AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
         mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
         mNumOutputFrame++;
@@ -134,24 +135,23 @@
 
 void Encoder::setupEncoder() {
     if (!mFormat) mFormat = AMediaFormat_new();
-    if (!mTimer) mTimer = new Timer();
 }
 
 void Encoder::deInitCodec() {
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     if (mFormat) {
         AMediaFormat_delete(mFormat);
         mFormat = nullptr;
     }
     AMediaCodec_stop(mCodec);
     AMediaCodec_delete(mCodec);
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setDeInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
 }
 
 void Encoder::resetEncoder() {
-    if (mTimer) mTimer->resetTimers();
+    if (mStats) mStats->reset();
     if (mEleStream) mEleStream = nullptr;
     if (mMime) mMime = nullptr;
     mInputBufferSize = 0;
@@ -160,7 +160,7 @@
 
 void Encoder::dumpStatistics(string inputReference, int64_t durationUs) {
     string operation = "encode";
-    mTimer->dumpStatistics(operation, inputReference, durationUs);
+    mStats->dumpStatistics(operation, inputReference, durationUs);
 }
 
 int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize,
@@ -192,11 +192,11 @@
     const char *s = AMediaFormat_toString(mFormat);
     ALOGV("Input format: %s\n", s);
 
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     mCodec = createMediaCodec(mFormat, mMime, codecName, true /*isEncoder*/);
     if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
 
     if (!strncmp(mMime, "video/", 6)) {
         mParams.frameSize = mParams.width * mParams.height * 3 / 2;
@@ -215,20 +215,19 @@
     }
     mParams.numFrames = (mInputBufferSize + mParams.frameSize - 1) / mParams.frameSize;
 
-    sTime = mTimer->getCurTime();
+    sTime = mStats->getCurTime();
     if (asyncMode) {
         AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
                                                 OnFormatChangedCB, OnErrorCB};
         AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
-        CallBackHandle *callbackHandle = new CallBackHandle();
-        callbackHandle->mIOThread = thread(&CallBackHandle::ioThread, this);
+        mIOThread = thread(&CallBackHandle::ioThread, this);
     }
     AMediaCodec_start(mCodec);
-    eTime = mTimer->getCurTime();
-    timeTaken += mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setInitTime(timeTaken);
+    eTime = mStats->getCurTime();
+    timeTaken += mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
 
-    mTimer->setStartTime();
+    mStats->setStartTime();
     if (!asyncMode) {
         while (!mSawOutputEOS && !mSignalledError) {
             // Queue input data
@@ -238,7 +237,7 @@
                     ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
                     return AMEDIA_ERROR_IO;
                 } else if (inIdx >= 0) {
-                    mTimer->addInputTime();
+                    mStats->addInputTime();
                     onInputAvailable(mCodec, inIdx);
                 }
             }
@@ -251,7 +250,7 @@
                 const char *s = AMediaFormat_toString(mFormat);
                 ALOGI("Output format: %s\n", s);
             } else if (outIdx >= 0) {
-                mTimer->addOutputTime();
+                mStats->addOutputTime();
                 onOutputAvailable(mCodec, outIdx, &info);
             } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
                          outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
index 903d52b..75d9941 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -24,7 +24,7 @@
 #include <thread>
 
 #include "BenchmarkCommon.h"
-#include "Timer.h"
+#include "Stats.h"
 
 struct encParameter {
     int32_t bitrate = -1;
@@ -45,18 +45,13 @@
     Encoder()
         : mCodec(nullptr),
           mFormat(nullptr),
-          mTimer(nullptr),
           mNumInputFrame(0),
           mNumOutputFrame(0),
           mSawInputEOS(false),
           mSawOutputEOS(false),
           mSignalledError(false) {}
 
-    virtual ~Encoder() {
-        if (mTimer) delete mTimer;
-    }
-
-    Timer *getTimer() override { return mTimer; }
+    virtual ~Encoder() {}
 
     // Encoder related utilities
     void setupEncoder();
@@ -83,8 +78,6 @@
     AMediaCodec *mCodec;
     AMediaFormat *mFormat;
 
-    Timer *mTimer;
-
     int32_t mNumInputFrame;
     int32_t mNumOutputFrame;
     bool mSawInputEOS;
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.cpp b/media/tests/benchmark/src/native/extractor/Extractor.cpp
index 0726ae3..b4cad0b 100644
--- a/media/tests/benchmark/src/native/extractor/Extractor.cpp
+++ b/media/tests/benchmark/src/native/extractor/Extractor.cpp
@@ -22,21 +22,21 @@
 #include "Extractor.h"
 
 int32_t Extractor::initExtractor(int32_t fd, size_t fileSize) {
-    mTimer = new Timer();
+    mStats = new Stats();
 
     mFrameBuf = (uint8_t *)calloc(kMaxBufferSize, sizeof(uint8_t));
     if (!mFrameBuf) return -1;
 
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
 
     mExtractor = AMediaExtractor_new();
     if (!mExtractor) return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
     media_status_t status = AMediaExtractor_setDataSourceFd(mExtractor, fd, 0, fileSize);
     if (status != AMEDIA_OK) return status;
 
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
 
     return AMediaExtractor_getTrackCount(mExtractor);
 }
@@ -52,6 +52,7 @@
     bool csdFound = AMediaFormat_getBuffer(mFormat, csdName, &csdBuffer, &size);
     if (!csdFound) return nullptr;
     frameInfo.size = (int32_t)size;
+    mStats->addFrameSize(frameInfo.size);
 
     return csdBuffer;
 }
@@ -62,6 +63,7 @@
 
     frameInfo.flags = AMediaExtractor_getSampleFlags(mExtractor);
     frameInfo.size = size;
+    mStats->addFrameSize(frameInfo.size);
     frameInfo.presentationTimeUs = AMediaExtractor_getSampleTime(mExtractor);
     AMediaExtractor_advance(mExtractor);
 
@@ -92,11 +94,11 @@
         idx++;
     }
 
-    mTimer->setStartTime();
+    mStats->setStartTime();
     while (1) {
         int32_t status = getFrameSample(frameInfo);
         if (status || !frameInfo.size) break;
-        mTimer->addOutputTime();
+        mStats->addOutputTime();
     }
 
     if (mFormat) {
@@ -111,7 +113,7 @@
 
 void Extractor::dumpStatistics(string inputReference) {
     string operation = "extract";
-    mTimer->dumpStatistics(operation, inputReference, mDurationUs);
+    mStats->dumpStatistics(operation, inputReference, mDurationUs);
 }
 
 void Extractor::deInitExtractor() {
@@ -120,14 +122,14 @@
         mFrameBuf = nullptr;
     }
 
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     if (mExtractor) {
         // TODO: (b/140128505) Multiple calls result in DoS.
         // Uncomment call to AMediaExtractor_delete() once this is resolved
         // AMediaExtractor_delete(mExtractor);
         mExtractor = nullptr;
     }
-    int64_t eTime = mTimer->getCurTime();
-    int64_t deInitTime = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setDeInitTime(deInitTime);
+    int64_t eTime = mStats->getCurTime();
+    int64_t deInitTime = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(deInitTime);
 }
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.h b/media/tests/benchmark/src/native/extractor/Extractor.h
index 361bcd7..4c39a72 100644
--- a/media/tests/benchmark/src/native/extractor/Extractor.h
+++ b/media/tests/benchmark/src/native/extractor/Extractor.h
@@ -20,19 +20,19 @@
 #include <media/NdkMediaExtractor.h>
 
 #include "BenchmarkCommon.h"
-#include "Timer.h"
+#include "Stats.h"
 
 class Extractor {
   public:
     Extractor()
         : mFormat(nullptr),
           mExtractor(nullptr),
-          mTimer(nullptr),
+          mStats(nullptr),
           mFrameBuf{nullptr},
           mDurationUs{0} {}
 
     ~Extractor() {
-        if (mTimer) delete mTimer;
+        if (mStats) delete mStats;
     }
 
     int32_t initExtractor(int32_t fd, size_t fileSize);
@@ -58,7 +58,7 @@
   private:
     AMediaFormat *mFormat;
     AMediaExtractor *mExtractor;
-    Timer *mTimer;
+    Stats *mStats;
     uint8_t *mFrameBuf;
     int64_t mDurationUs;
 };
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.cpp b/media/tests/benchmark/src/native/muxer/Muxer.cpp
index 877f7ad..b297a66 100644
--- a/media/tests/benchmark/src/native/muxer/Muxer.cpp
+++ b/media/tests/benchmark/src/native/muxer/Muxer.cpp
@@ -24,9 +24,9 @@
 
 int32_t Muxer::initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat) {
     if (!mFormat) mFormat = mExtractor->getFormat();
-    if (!mTimer) mTimer = new Timer();
+    if (!mStats) mStats = new Stats();
 
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     mMuxer = AMediaMuxer_new(fd, (OutputFormat)outputFormat);
     if (!mMuxer) {
         cout << "[   WARN   ] Test Skipped. Unable to create muxer \n";
@@ -42,14 +42,14 @@
         return index;
     }
     AMediaMuxer_start(mMuxer);
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
     return AMEDIA_OK;
 }
 
 void Muxer::deInitMuxer() {
-    int64_t sTime = mTimer->getCurTime();
+    int64_t sTime = mStats->getCurTime();
     if (mFormat) {
         AMediaFormat_delete(mFormat);
         mFormat = nullptr;
@@ -57,24 +57,24 @@
     if (!mMuxer) return;
     AMediaMuxer_stop(mMuxer);
     AMediaMuxer_delete(mMuxer);
-    int64_t eTime = mTimer->getCurTime();
-    int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
-    mTimer->setDeInitTime(timeTaken);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
 }
 
 void Muxer::resetMuxer() {
-    if (mTimer) mTimer->resetTimers();
+    if (mStats) mStats->reset();
 }
 
 void Muxer::dumpStatistics(string inputReference) {
     string operation = "mux";
-    mTimer->dumpStatistics(operation, inputReference, mExtractor->getClipDuration());
+    mStats->dumpStatistics(operation, inputReference, mExtractor->getClipDuration());
 }
 
 int32_t Muxer::mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfos) {
     // Mux frame data
     size_t frameIdx = 0;
-    mTimer->setStartTime();
+    mStats->setStartTime();
     while (frameIdx < frameInfos.size()) {
         AMediaCodecBufferInfo info = frameInfos.at(frameIdx);
         media_status_t status = AMediaMuxer_writeSampleData(mMuxer, 0, inputBuffer, &info);
@@ -82,7 +82,8 @@
             ALOGE("Error in AMediaMuxer_writeSampleData");
             return status;
         }
-        mTimer->addOutputTime();
+        mStats->addOutputTime();
+        mStats->addFrameSize(info.size);
         frameIdx++;
     }
     return AMEDIA_OK;
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.h b/media/tests/benchmark/src/native/muxer/Muxer.h
index 154fd20..eee3146 100644
--- a/media/tests/benchmark/src/native/muxer/Muxer.h
+++ b/media/tests/benchmark/src/native/muxer/Muxer.h
@@ -20,7 +20,7 @@
 #include <media/NdkMediaMuxer.h>
 
 #include "BenchmarkCommon.h"
-#include "Timer.h"
+#include "Stats.h"
 #include "Extractor.h"
 
 typedef enum {
@@ -33,14 +33,14 @@
 
 class Muxer {
   public:
-    Muxer() : mFormat(nullptr), mMuxer(nullptr), mTimer(nullptr) { mExtractor = new Extractor(); }
+    Muxer() : mFormat(nullptr), mMuxer(nullptr), mStats(nullptr) { mExtractor = new Extractor(); }
 
     virtual ~Muxer() {
-        if (mTimer) delete mTimer;
+        if (mStats) delete mStats;
         if (mExtractor) delete mExtractor;
     }
 
-    Timer *getTimer() { return mTimer; }
+    Stats *getStats() { return mStats; }
     Extractor *getExtractor() { return mExtractor; }
 
     /* Muxer related utilities */
@@ -57,7 +57,7 @@
     AMediaFormat *mFormat;
     AMediaMuxer *mMuxer;
     Extractor *mExtractor;
-    Timer *mTimer;
+    Stats *mStats;
 };
 
 #endif  // __MUXER_H__
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 605fc1c..630efc1 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -43,14 +43,6 @@
 #define MAX_MIXER_CHANNEL_COUNT FCC_8
 
 /**
- * A device mask for all audio input and output devices where matching inputs/outputs on device
- * type alone is not enough: the address must match too
- */
-#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX|AUDIO_DEVICE_OUT_BUS)
-
-#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
-
-/**
  * Alias to AUDIO_DEVICE_OUT_DEFAULT defined for clarification when this value is used by volume
  * control APIs (e.g setStreamVolumeIndex().
  */
@@ -71,6 +63,34 @@
 }
 
 /**
+ * Check whether the output device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static inline bool apm_audio_out_device_distinguishes_on_address(audio_devices_t device)
+{
+    return device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+           device == AUDIO_DEVICE_OUT_BUS;
+}
+
+/**
+ * Check whether the input device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static inline bool apm_audio_in_device_distinguishes_on_address(audio_devices_t device)
+{
+    return device == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
+           device == AUDIO_DEVICE_IN_BUS;
+}
+
+/**
  * Check whether the device type is one
  * where addresses are used to distinguish between one connected device and another
  *
@@ -80,10 +100,8 @@
  */
 static inline bool device_distinguishes_on_address(audio_devices_t device)
 {
-    return (((device & AUDIO_DEVICE_BIT_IN) != 0) &&
-            ((~AUDIO_DEVICE_BIT_IN & device & APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL) != 0)) ||
-           (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
-            ((device & APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL) != 0));
+    return apm_audio_in_device_distinguishes_on_address(device) ||
+           apm_audio_out_device_distinguishes_on_address(device);
 }
 
 /**
@@ -95,10 +113,7 @@
  */
 static inline bool device_has_encoding_capability(audio_devices_t device)
 {
-    if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
-        return true;
-    }
-    return false;
+    return audio_is_a2dp_out_device(device);
 }
 
 /**
diff --git a/services/audiopolicy/tests/systemaudio_tests.cpp b/services/audiopolicy/tests/systemaudio_tests.cpp
index abaae52..1e4d07f 100644
--- a/services/audiopolicy/tests/systemaudio_tests.cpp
+++ b/services/audiopolicy/tests/systemaudio_tests.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <unordered_set>
+
 #include <gtest/gtest.h>
 
 #define LOG_TAG "SysAudio_Test"
@@ -115,3 +117,81 @@
                     (PatchBuilder{}).addSource(src).addSink(sink_hw_av_sync).patch(),
                     (PatchBuilder{}).addSource(src).addSink(sink_hw_av_sync).patch()));
 }
+
+void runAudioDeviceTypeHelperFunction(const std::unordered_set<audio_devices_t>& allDevices,
+                                      const audio_devices_t targetDevices[],
+                                      unsigned int targetDeviceCount,
+                                      const std::string& deviceTag,
+                                      bool (*device_type_helper_function)(audio_devices_t))
+{
+    std::unordered_set<audio_devices_t> devices(targetDevices, targetDevices + targetDeviceCount);
+    for (auto device : allDevices) {
+        if (devices.find(device) == devices.end()) {
+            ASSERT_FALSE(device_type_helper_function(device))
+                    << std::hex << device << " should not be " << deviceTag << " device";
+        } else {
+            ASSERT_TRUE(device_type_helper_function(device))
+                    << std::hex << device << " should be " << deviceTag << " device";
+        }
+    }
+}
+
+TEST(SystemAudioTest, AudioDeviceTypeHelperFunction) {
+    std::unordered_set<audio_devices_t> allDeviceTypes;
+    allDeviceTypes.insert(std::begin(AUDIO_DEVICE_OUT_ALL_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_ARRAY));
+    allDeviceTypes.insert(std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
+            std::end(AUDIO_DEVICE_IN_ALL_ARRAY));
+
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_OUT_ALL_ARRAY,
+            std::size(AUDIO_DEVICE_OUT_ALL_ARRAY), "output", audio_is_output_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_IN_ALL_ARRAY,
+            std::size(AUDIO_DEVICE_IN_ALL_ARRAY), "input", audio_is_input_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY,
+            std::size(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY), "a2dp out", audio_is_a2dp_out_device);
+    const audio_devices_t bluetoothInA2dpDevices[] = { AUDIO_DEVICE_IN_BLUETOOTH_A2DP };
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, bluetoothInA2dpDevices,
+            std::size(bluetoothInA2dpDevices), "a2dp in", audio_is_a2dp_in_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_OUT_ALL_SCO_ARRAY,
+            std::size(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY), "bluetooth out sco",
+            audio_is_bluetooth_out_sco_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_IN_ALL_SCO_ARRAY,
+            std::size(AUDIO_DEVICE_IN_ALL_SCO_ARRAY), "bluetooth in sco",
+            audio_is_bluetooth_in_sco_device);
+    const unsigned int scoDeviceCount = AUDIO_DEVICE_OUT_SCO_CNT + AUDIO_DEVICE_IN_SCO_CNT;
+    audio_devices_t scoDevices[scoDeviceCount];
+    std::copy(std::begin(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY), std::end(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY),
+              std::begin(scoDevices));
+    std::copy(std::begin(AUDIO_DEVICE_IN_ALL_SCO_ARRAY), std::end(AUDIO_DEVICE_IN_ALL_SCO_ARRAY),
+              std::begin(scoDevices) + AUDIO_DEVICE_OUT_SCO_CNT);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, scoDevices,
+            std::size(scoDevices), "bluetooth sco", audio_is_bluetooth_sco_device);
+    const audio_devices_t hearingAidOutDevices[] = { AUDIO_DEVICE_OUT_HEARING_AID };
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, hearingAidOutDevices,
+            std::size(hearingAidOutDevices), "hearing aid out", audio_is_hearing_aid_out_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_OUT_ALL_USB_ARRAY,
+            std::size(AUDIO_DEVICE_OUT_ALL_USB_ARRAY), "usb out", audio_is_usb_out_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_IN_ALL_USB_ARRAY,
+            std::size(AUDIO_DEVICE_IN_ALL_USB_ARRAY), "usb in", audio_is_usb_in_device);
+    const audio_devices_t remoteSubmixDevices[] = {
+            AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX };
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, remoteSubmixDevices,
+            std::size(remoteSubmixDevices), "remote submix", audio_is_remote_submix_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_OUT_ALL_DIGITAL_ARRAY,
+            std::size(AUDIO_DEVICE_OUT_ALL_DIGITAL_ARRAY), "digital out",
+            audio_is_digital_out_device);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, AUDIO_DEVICE_IN_ALL_DIGITAL_ARRAY,
+            std::size(AUDIO_DEVICE_IN_ALL_DIGITAL_ARRAY), "digital in",
+            audio_is_digital_in_device);
+    const unsigned int digitalDeviceCount
+            = AUDIO_DEVICE_OUT_DIGITAL_CNT + AUDIO_DEVICE_IN_DIGITAL_CNT;
+    audio_devices_t digitalDevices[digitalDeviceCount];
+    std::copy(std::begin(AUDIO_DEVICE_OUT_ALL_DIGITAL_ARRAY),
+              std::end(AUDIO_DEVICE_OUT_ALL_DIGITAL_ARRAY),
+              std::begin(digitalDevices));
+    std::copy(std::begin(AUDIO_DEVICE_IN_ALL_DIGITAL_ARRAY),
+              std::end(AUDIO_DEVICE_IN_ALL_DIGITAL_ARRAY),
+              std::begin(digitalDevices) + AUDIO_DEVICE_OUT_DIGITAL_CNT);
+    runAudioDeviceTypeHelperFunction(allDeviceTypes, digitalDevices,
+              std::size(digitalDevices), "digital", audio_device_is_digital);
+}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a503838..94642f2 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -135,6 +135,7 @@
 CameraService::CameraService() :
         mEventLog(DEFAULT_EVENT_LOG_LENGTH),
         mNumberOfCameras(0),
+        mNumberOfCamerasWithoutSystemCamera(0),
         mSoundRef(0), mInitialized(false),
         mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
     ALOGI("CameraService started (pid=%d)", getpid());
@@ -159,8 +160,6 @@
         mInitialized = true;
     }
 
-    CameraService::pingCameraServiceProxy();
-
     mUidPolicy = new UidPolicy(this);
     mUidPolicy->registerSelf();
     mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
@@ -171,6 +170,11 @@
         ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
               __FUNCTION__);
     }
+
+    // This needs to be last call in this function, so that it's as close to
+    // ServiceManager::addService() as possible.
+    CameraService::pingCameraServiceProxy();
+    ALOGI("CameraService pinged cameraservice proxy");
 }
 
 status_t CameraService::enumerateProviders() {
@@ -260,11 +264,32 @@
     enumerateProviders();
 }
 
+void CameraService::filterAPI1SystemCameraLocked(
+        const std::vector<std::string> &normalDeviceIds) {
+    mNormalDeviceIdsWithoutSystemCamera.clear();
+    for (auto &deviceId : normalDeviceIds) {
+        if (getSystemCameraKind(String8(deviceId.c_str())) ==
+                SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+            // All system camera ids will necessarily come after public camera
+            // device ids as per the HAL interface contract.
+            break;
+        }
+        mNormalDeviceIdsWithoutSystemCamera.push_back(deviceId);
+    }
+    ALOGV("%s: number of API1 compatible public cameras is %zu", __FUNCTION__,
+              mNormalDeviceIdsWithoutSystemCamera.size());
+}
+
 void CameraService::updateCameraNumAndIds() {
     Mutex::Autolock l(mServiceLock);
-    mNumberOfCameras = mCameraProviderManager->getCameraCount();
+    std::pair<int, int> systemAndNonSystemCameras = mCameraProviderManager->getCameraCount();
+    // Excludes hidden secure cameras
+    mNumberOfCameras =
+            systemAndNonSystemCameras.first + systemAndNonSystemCameras.second;
+    mNumberOfCamerasWithoutSystemCamera = systemAndNonSystemCameras.second;
     mNormalDeviceIds =
             mCameraProviderManager->getAPI1CompatibleCameraDeviceIds();
+    filterAPI1SystemCameraLocked(mNormalDeviceIds);
 }
 
 void CameraService::addStates(const String8 id) {
@@ -446,15 +471,31 @@
     broadcastTorchModeStatus(cameraId, newStatus);
 }
 
+static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+    return checkPermission(sSystemCameraPermission, callingPid, callingUid) &&
+            checkPermission(sCameraPermission, callingPid, callingUid);
+}
+
 Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
+    bool hasSystemCameraPermissions =
+            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+                    CameraThreadState::getCallingUid());
     switch (type) {
         case CAMERA_TYPE_BACKWARD_COMPATIBLE:
-            *numCameras = static_cast<int>(mNormalDeviceIds.size());
+            if (hasSystemCameraPermissions) {
+                *numCameras = static_cast<int>(mNormalDeviceIds.size());
+            } else {
+                *numCameras = static_cast<int>(mNormalDeviceIdsWithoutSystemCamera.size());
+            }
             break;
         case CAMERA_TYPE_ALL:
-            *numCameras = mNumberOfCameras;
+            if (hasSystemCameraPermissions) {
+                *numCameras = mNumberOfCameras;
+            } else {
+                *numCameras = mNumberOfCamerasWithoutSystemCamera;
+            }
             break;
         default:
             ALOGW("%s: Unknown camera type %d",
@@ -469,20 +510,31 @@
         CameraInfo* cameraInfo) {
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
+    std::string cameraIdStr = cameraIdIntToStrLocked(cameraId);
+    if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
+                "characteristics for system only device %s: ", cameraIdStr.c_str());
+    }
 
     if (!mInitialized) {
         return STATUS_ERROR(ERROR_DISCONNECTED,
                 "Camera subsystem is not available");
     }
-
-    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+    bool hasSystemCameraPermissions =
+            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+                    CameraThreadState::getCallingUid());
+    int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
+    if (hasSystemCameraPermissions) {
+        cameraIdBound = mNumberOfCameras;
+    }
+    if (cameraId < 0 || cameraId >= cameraIdBound) {
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
                 "CameraId is not valid");
     }
 
     Status ret = Status::ok();
     status_t err = mCameraProviderManager->getCameraInfo(
-            cameraIdIntToStrLocked(cameraId), cameraInfo);
+            cameraIdStr.c_str(), cameraInfo);
     if (err != OK) {
         ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                 "Error retrieving camera info from device %d: %s (%d)", cameraId,
@@ -493,13 +545,20 @@
 }
 
 std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
-    if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
+    const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
+    auto callingPid = CameraThreadState::getCallingPid();
+    auto callingUid = CameraThreadState::getCallingUid();
+    if (checkPermission(sSystemCameraPermission, callingPid, callingUid) ||
+            getpid() == callingPid) {
+        deviceIds = &mNormalDeviceIds;
+    }
+    if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(deviceIds->size())) {
         ALOGE("%s: input id %d invalid: valid range  (0, %zu)",
-                __FUNCTION__, cameraIdInt, mNormalDeviceIds.size());
+                __FUNCTION__, cameraIdInt, deviceIds->size());
         return std::string{};
     }
 
-    return mNormalDeviceIds[cameraIdInt];
+    return (*deviceIds)[cameraIdInt];
 }
 
 String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
@@ -1348,11 +1407,6 @@
     return ret;
 }
 
-static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
-    return checkPermission(sSystemCameraPermission, callingPid, callingUid) &&
-            checkPermission(sCameraPermission, callingPid, callingUid);
-}
-
 bool CameraService::shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener,
         int clientPid, int clientUid) const {
     SystemCameraKind systemCameraKind = getSystemCameraKind(cameraId);
@@ -3151,6 +3205,8 @@
     dprintf(fd, "\n== Service global info: ==\n\n");
     dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras);
     dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size());
+    dprintf(fd, "Number of public camera devices visible to API1: %zu\n",
+            mNormalDeviceIdsWithoutSystemCamera.size());
     for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
         dprintf(fd, "    Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
     }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7c77e16..058d57e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -667,6 +667,13 @@
         return mCameraProviderManager->getSystemCameraKind(cameraId.c_str());
     }
 
+    // Update the set of API1Compatible camera devices without including system
+    // cameras and secure cameras. This is used for hiding system only cameras
+    // from clients using camera1 api and not having android.permission.SYSTEM_CAMERA.
+    // This function expects @param normalDeviceIds, to have normalDeviceIds
+    // sorted in alpha-numeric order.
+    void filterAPI1SystemCameraLocked(const std::vector<std::string> &normalDeviceIds);
+
     // Single implementation shared between the various connect calls
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
@@ -821,9 +828,14 @@
      */
     void updateCameraNumAndIds();
 
+    // Number of camera devices (excluding hidden secure cameras)
     int                 mNumberOfCameras;
+    // Number of camera devices (excluding hidden secure cameras and
+    // system cameras)
+    int                 mNumberOfCamerasWithoutSystemCamera;
 
     std::vector<std::string> mNormalDeviceIds;
+    std::vector<std::string> mNormalDeviceIdsWithoutSystemCamera;
 
     // sounds
     sp<MediaPlayer>     newMediaPlayer(const char *file);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index c21bd69..974026c 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -104,13 +104,25 @@
     return OK;
 }
 
-int CameraProviderManager::getCameraCount() const {
+std::pair<int, int> CameraProviderManager::getCameraCount() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    int count = 0;
+    int systemCameraCount = 0;
+    int publicCameraCount = 0;
     for (auto& provider : mProviders) {
-        count += provider->mUniqueCameraIds.size();
+        for (auto &id : provider->mUniqueCameraIds) {
+            switch(getSystemCameraKindLocked(id)) {
+                case SystemCameraKind::PUBLIC:
+                    publicCameraCount++;
+                    break;
+                case SystemCameraKind::SYSTEM_ONLY_CAMERA:
+                    systemCameraCount++;
+                    break;
+                default:
+                    break;
+            }
+        }
     }
-    return count;
+    return std::make_pair(systemCameraCount, publicCameraCount);
 }
 
 std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
@@ -124,21 +136,38 @@
     return deviceIds;
 }
 
+void CameraProviderManager::collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+        std::vector<std::string>& publicDeviceIds,
+        std::vector<std::string>& systemDeviceIds) const {
+    for (auto &deviceId : deviceIds) {
+        if (getSystemCameraKindLocked(deviceId) == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+            systemDeviceIds.push_back(deviceId);
+        } else {
+            publicDeviceIds.push_back(deviceId);
+        }
+    }
+}
+
 std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    std::vector<std::string> publicDeviceIds;
+    std::vector<std::string> systemDeviceIds;
     std::vector<std::string> deviceIds;
     for (auto& provider : mProviders) {
         std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
-
+        // Secure cameras should not be exposed through camera 1 api
+        providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
+                [this](const std::string& s) {
+                bool rem = this->getSystemCameraKindLocked(s) ==
+                        SystemCameraKind::HIDDEN_SECURE_CAMERA;
+                return rem;}), providerDeviceIds.end());
         // API1 app doesn't handle logical and physical camera devices well. So
         // for each camera facing, only take the first id advertised by HAL in
         // all [logical, physical1, physical2, ...] id combos, and filter out the rest.
         filterLogicalCameraIdsLocked(providerDeviceIds);
-
-        deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
+        collectDeviceIdsLocked(providerDeviceIds, publicDeviceIds, systemDeviceIds);
     }
-
-    std::sort(deviceIds.begin(), deviceIds.end(),
+    auto sortFunc =
             [](const std::string& a, const std::string& b) -> bool {
                 uint32_t aUint = 0, bUint = 0;
                 bool aIsUint = base::ParseUint(a, &aUint);
@@ -154,7 +183,13 @@
                 }
                 // Simple string compare if both id are not uint
                 return a < b;
-            });
+            };
+    // We put device ids for system cameras at the end since they will be pared
+    // off for processes not having system camera permissions.
+    std::sort(publicDeviceIds.begin(), publicDeviceIds.end(), sortFunc);
+    std::sort(systemDeviceIds.begin(), systemDeviceIds.end(), sortFunc);
+    deviceIds.insert(deviceIds.end(), publicDeviceIds.begin(), publicDeviceIds.end());
+    deviceIds.insert(deviceIds.end(), systemDeviceIds.begin(), systemDeviceIds.end());
     return deviceIds;
 }
 
@@ -1054,9 +1089,12 @@
     return deviceInfo->mIsLogicalCamera;
 }
 
-SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) {
+SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    return getSystemCameraKindLocked(id);
+}
 
+SystemCameraKind CameraProviderManager::getSystemCameraKindLocked(const std::string& id) const {
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) {
         return SystemCameraKind::PUBLIC;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 801e978..f4cf667 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -152,10 +152,10 @@
             ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
 
     /**
-     * Retrieve the total number of available cameras. This value may change dynamically as cameras
-     * are added or removed.
+     * Retrieve the total number of available cameras.
+     * This value may change dynamically as cameras are added or removed.
      */
-    int getCameraCount() const;
+    std::pair<int, int> getCameraCount() const;
 
     std::vector<std::string> getCameraDeviceIds() const;
 
@@ -292,7 +292,7 @@
      */
     bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
 
-    SystemCameraKind getSystemCameraKind(const std::string& id);
+    SystemCameraKind getSystemCameraKind(const std::string& id) const;
     bool isHiddenPhysicalCamera(const std::string& cameraId);
 
     static const float kDepthARTolerance;
@@ -615,6 +615,12 @@
     status_t getCameraCharacteristicsLocked(const std::string &id,
             CameraMetadata* characteristics) const;
     void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
+
+    SystemCameraKind getSystemCameraKindLocked(const std::string& id) const;
+
+    void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+            std::vector<std::string>& normalDeviceIds,
+            std::vector<std::string>& systemCameraDeviceIds) const;
 };
 
 } // namespace android
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 69e5f50..ccbeb77 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -40,6 +40,32 @@
 #define HW_MODULE_PREFIX "primary"
 namespace android {
 
+namespace {
+
+// Given an IMemory, returns a copy of its content along with its size.
+// Returns nullptr on failure or if input is nullptr.
+std::pair<std::unique_ptr<uint8_t[]>,
+          size_t> CopyToArray(const sp<IMemory>& mem) {
+    if (mem == nullptr) {
+        return std::make_pair(nullptr, 0);
+    }
+
+    const size_t size = mem->size();
+    if (size == 0) {
+        return std::make_pair(nullptr, 0);
+    }
+
+    std::unique_ptr<uint8_t[]> ar = std::make_unique<uint8_t[]>(size);
+    if (ar == nullptr) {
+        return std::make_pair(nullptr, 0);
+    }
+
+    memcpy(ar.get(), mem->unsecurePointer(), size);
+    return std::make_pair(std::move(ar), size);
+}
+
+}
+
 SoundTriggerHwService::SoundTriggerHwService()
     : BnSoundTriggerHwService(),
       mNextUniqueId(1),
@@ -557,12 +583,13 @@
         return NO_INIT;
     }
 
-    // TODO: Using unsecurePointer() has some associated security pitfalls
-    //       (see declaration for details).
-    //       Either document why it is safe in this case or address the
-    //       issue (e.g. by copying).
-    struct sound_trigger_sound_model *sound_model =
-            (struct sound_trigger_sound_model *)modelMemory->unsecurePointer();
+    auto immutableMemory = CopyToArray(modelMemory);
+    if (immutableMemory.first == nullptr) {
+        return NO_MEMORY;
+    }
+
+    struct sound_trigger_sound_model* sound_model =
+        (struct sound_trigger_sound_model*) immutableMemory.first.get();
 
     size_t structSize;
     if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
@@ -572,9 +599,10 @@
     }
 
     if (sound_model->data_offset < structSize ||
-           sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
-           modelMemory->size() < sound_model->data_offset ||
-           sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
+        sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
+        immutableMemory.second < sound_model->data_offset ||
+            sound_model->data_size >
+            (immutableMemory.second - sound_model->data_offset)) {
         android_errorWriteLog(0x534e4554, "30148546");
         ALOGE("loadSoundModel() data_size is too big");
         return BAD_VALUE;
@@ -655,17 +683,19 @@
         return NO_INIT;
     }
 
-    // TODO: Using unsecurePointer() has some associated security pitfalls
-    //       (see declaration for details).
-    //       Either document why it is safe in this case or address the
-    //       issue (e.g. by copying).
-    struct sound_trigger_recognition_config *config =
-            (struct sound_trigger_recognition_config *)dataMemory->unsecurePointer();
+    auto immutableMemory = CopyToArray(dataMemory);
+    if (immutableMemory.first == nullptr) {
+        return NO_MEMORY;
+    }
+
+    struct sound_trigger_recognition_config* config =
+        (struct sound_trigger_recognition_config*) immutableMemory.first.get();
 
     if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
-            config->data_size > (UINT_MAX - config->data_offset) ||
-            dataMemory->size() < config->data_offset ||
-            config->data_size > (dataMemory->size() - config->data_offset)) {
+        config->data_size > (UINT_MAX - config->data_offset) ||
+        immutableMemory.second < config->data_offset ||
+            config->data_size >
+            (immutableMemory.second - config->data_offset)) {
         ALOGE("startRecognition() data_size is too big");
         return BAD_VALUE;
     }