Merge changes I147a476c,Ia769b124,Ibc0e3346,Icc961e82,Iaeb69e03, ... into sc-dev

* changes:
  Downmix: Clean up the generic downmix
  Downmix: Remove unneeded LVM_FLOAT
  Downmix: Remove unnecessary channel mask redefine
  Downmix: Enable host test
  Downmix: Move to cpp
  Downmix: Add benchmark
  Downmix: Clean up unnecessary API and add gtest
diff --git a/apex/Android.bp b/apex/Android.bp
index d911ad3..dc22628 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -25,9 +25,7 @@
     name: "com.android.media-defaults",
     updatable: true,
     bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"],
-    java_libs: [
-      "service-media-s",
-    ],
+    systemserverclasspath_fragments: ["com.android.media-systemserverclasspath-fragment"],
     multilib: {
         first: {
             // Extractor process runs only with the primary ABI.
@@ -101,6 +99,13 @@
     apex_available: ["com.android.media"],
 }
 
+// Encapsulate the contributions made by the com.android.media to the systemserverclasspath.
+systemserverclasspath_fragment {
+    name: "com.android.media-systemserverclasspath-fragment",
+    contents: ["service-media-s"],
+    apex_available: ["com.android.media"],
+}
+
 filegroup {
     name: "com.android.media-androidManifest",
     srcs: ["AndroidManifest-media.xml"],
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
index ae9f8ba..24306a2 100644
--- a/apex/mediatranscoding.rc
+++ b/apex/mediatranscoding.rc
@@ -8,5 +8,4 @@
     ioprio rt 4
     # Restrict to little cores only with system-background cpuset.
     writepid /dev/cpuset/system-background/tasks
-    interface aidl media.transcoding
     disabled
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 873d738..6e82968 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -92,7 +92,7 @@
             String cameraId,
             String opPackageName,
             @nullable String featureId,
-            int clientUid);
+            int clientUid, int oomScoreOffset);
 
     /**
      * Add listener for changes to camera device and flashlight state.
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 73cabbf..a03c69c 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -739,7 +739,7 @@
     // Send a zero length package name and let camera service figure it out from UID
     binder::Status serviceRet = cs->connectDevice(
             callbacks, String16(cameraId), String16(""), {},
-            hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
+            hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0, /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
         ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 0cf390f..a0773a2 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -378,7 +378,7 @@
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
-                {}, hardware::ICameraService::USE_CALLING_UID,
+                {}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
                 /*out*/&device);
         EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
@@ -421,7 +421,7 @@
         {
             SCOPED_TRACE("openNewDevice");
             binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
-                    {}, hardware::ICameraService::USE_CALLING_UID,
+                    {}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
                     /*out*/&device);
             EXPECT_TRUE(res.isOk()) << res;
         }
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 3333925..6ca5fc8 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -635,13 +635,14 @@
 AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder,
                                                 int32_t deviceId) __INTRODUCED_IN(26);
 
-// TODO b/182392769: reexamine if Identity can be used
 /**
  * Declare the name of the package creating the stream.
  *
  * This is usually {@code Context#getPackageName()}.
  *
  * The default, if you do not call this function, is a random package in the calling uid.
+ * The vast majority of apps have only one package per calling UID. If the package
+ * name does not match the calling UID, then requests will be rejected.
  *
  * Available since API level 31.
  *
@@ -656,7 +657,7 @@
  *
  * This is usually {@code Context#getAttributionTag()}.
  *
- * The default, if you do not call this function, is the default attribution tag.
+ * The default, if you do not call this function, is null.
  *
  * Available since API level 31.
  *
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index e2c8f8f..daa923e 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -127,7 +127,7 @@
 
     if ((as == AUDIO_SOURCE_FM_TUNER
             && !(captureAudioOutputAllowed(mIdentity) || captureTunerAudioInputAllowed(mIdentity)))
-            || !recordingAllowed(mIdentity)) {
+            || !recordingAllowed(mIdentity, (audio_source_t)as)) {
         return PERMISSION_DENIED;
     }
     Mutex::Autolock lock(mLock);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 57bdba0..8fa7463 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -29,6 +29,7 @@
 #include <C2Buffer.h>
 
 #include "include/SoftwareRenderer.h"
+#include "PlaybackDurationAccumulator.h"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
@@ -92,6 +93,7 @@
 // NB: these are matched with public Java API constants defined
 // in frameworks/base/media/java/android/media/MediaCodec.java
 // These must be kept synchronized with the constants there.
+static const char *kCodecLogSessionId = "android.media.mediacodec.log-session-id";
 static const char *kCodecCodec = "android.media.mediacodec.codec";  /* e.g. OMX.google.aac.decoder */
 static const char *kCodecMime = "android.media.mediacodec.mime";    /* e.g. audio/mime */
 static const char *kCodecMode = "android.media.mediacodec.mode";    /* audio, video */
@@ -107,6 +109,16 @@
 static const char *kCodecCaptureRate = "android.media.mediacodec.capture-rate";
 static const char *kCodecOperatingRate = "android.media.mediacodec.operating-rate";
 static const char *kCodecPriority = "android.media.mediacodec.priority";
+
+// Min/Max QP before shaping
+static const char *kCodecOriginalVideoQPIMin = "android.media.mediacodec.original-video-qp-i-min";
+static const char *kCodecOriginalVideoQPIMax = "android.media.mediacodec.original-video-qp-i-max";
+static const char *kCodecOriginalVideoQPPMin = "android.media.mediacodec.original-video-qp-p-min";
+static const char *kCodecOriginalVideoQPPMax = "android.media.mediacodec.original-video-qp-p-max";
+static const char *kCodecOriginalVideoQPBMin = "android.media.mediacodec.original-video-qp-b-min";
+static const char *kCodecOriginalVideoQPBMax = "android.media.mediacodec.original-video-qp-b-max";
+
+// Min/Max QP after shaping
 static const char *kCodecRequestedVideoQPIMin = "android.media.mediacodec.video-qp-i-min";
 static const char *kCodecRequestedVideoQPIMax = "android.media.mediacodec.video-qp-i-max";
 static const char *kCodecRequestedVideoQPPMin = "android.media.mediacodec.video-qp-p-min";
@@ -152,8 +164,12 @@
 static const char *kCodecRecentLatencyAvg = "android.media.mediacodec.recent.avg";      /* in us */
 static const char *kCodecRecentLatencyCount = "android.media.mediacodec.recent.n";
 static const char *kCodecRecentLatencyHist = "android.media.mediacodec.recent.hist";    /* in us */
+static const char *kCodecPlaybackDuration =
+        "android.media.mediacodec.playback-duration"; /* in sec */
 
-static const char *kCodecShapingEnhanced = "android.media.mediacodec.shaped";    /* 0/1 */
+/* -1: shaper disabled
+   >=0: number of fields changed */
+static const char *kCodecShapingEnhanced = "android.media.mediacodec.shaped";
 
 // XXX suppress until we get our representation right
 static bool kEmitHistogram = false;
@@ -740,6 +756,8 @@
       mHaveInputSurface(false),
       mHavePendingInputBuffers(false),
       mCpuBoostRequested(false),
+      mPlaybackDurationAccumulator(new PlaybackDurationAccumulator()),
+      mIsSurfaceToScreen(false),
       mLatencyUnknown(0),
       mBytesEncoded(0),
       mEarliestEncodedPtsUs(INT64_MAX),
@@ -846,6 +864,10 @@
     if (mLatencyUnknown > 0) {
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
     }
+    int64_t playbackDuration = mPlaybackDurationAccumulator->getDurationInSeconds();
+    if (playbackDuration > 0) {
+        mediametrics_setInt64(mMetricsHandle, kCodecPlaybackDuration, playbackDuration);
+    }
     if (mLifetimeStartNs > 0) {
         nsecs_t lifetime = systemTime(SYSTEM_TIME_MONOTONIC) - mLifetimeStartNs;
         lifetime = lifetime / (1000 * 1000);    // emitted in ms, truncated not rounded
@@ -985,6 +1007,28 @@
     ALOGV("Ignoring tunnel-peek=%d for %s", tunnelPeek, asString(mTunnelPeekState));
 }
 
+void MediaCodec::updatePlaybackDuration(const sp<AMessage> &msg) {
+    int what = 0;
+    msg->findInt32("what", &what);
+    if (msg->what() != kWhatCodecNotify && what != kWhatOutputFramesRendered) {
+        static bool logged = false;
+        if (!logged) {
+            logged = true;
+            ALOGE("updatePlaybackDuration: expected kWhatOuputFramesRendered (%d)", msg->what());
+        }
+        return;
+    }
+    // Playback duration only counts if the buffers are going to the screen.
+    if (!mIsSurfaceToScreen) {
+        return;
+    }
+    int64_t renderTimeNs;
+    size_t index = 0;
+    while (msg->findInt64(AStringPrintf("%zu-system-nano", index++).c_str(), &renderTimeNs)) {
+        mPlaybackDurationAccumulator->processRenderTime(renderTimeNs);
+    }
+}
+
 bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor)
 {
     if (nbuckets <= 0 || width <= 0) {
@@ -1460,6 +1504,8 @@
     }
 
     if (mIsVideo) {
+        // TODO: validity check log-session-id: it should be a 32-hex-digit.
+        format->findString("log-session-id", &mLogSessionId);
         format->findInt32("width", &mVideoWidth);
         format->findInt32("height", &mVideoHeight);
         if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
@@ -1467,6 +1513,7 @@
         }
 
         if (mMetricsHandle != 0) {
+            mediametrics_setCString(mMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str());
             mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth);
             mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight);
             mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
@@ -1498,30 +1545,6 @@
             if (format->findInt32("priority", &priority)) {
                 mediametrics_setInt32(mMetricsHandle, kCodecPriority, priority);
             }
-            int32_t qpIMin = -1;
-            if (format->findInt32("video-qp-i-min", &qpIMin)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin);
-            }
-            int32_t qpIMax = -1;
-            if (format->findInt32("video-qp-i-max", &qpIMax)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMax, qpIMax);
-            }
-            int32_t qpPMin = -1;
-            if (format->findInt32("video-qp-p-min", &qpPMin)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMin, qpPMin);
-            }
-            int32_t qpPMax = -1;
-            if (format->findInt32("video-qp-p-max", &qpPMax)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMax, qpPMax);
-            }
-             int32_t qpBMin = -1;
-            if (format->findInt32("video-qp-b-min", &qpBMin)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMin, qpBMin);
-            }
-            int32_t qpBMax = -1;
-            if (format->findInt32("video-qp-b-max", &qpBMax)) {
-                mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMax, qpBMax);
-            }
         }
 
         // Prevent possible integer overflow in downstream code.
@@ -1549,6 +1572,9 @@
                                                  enableMediaFormatShapingDefault);
         if (!enableShaping) {
             ALOGI("format shaping disabled, property '%s'", enableMediaFormatShapingProperty);
+            if (mMetricsHandle != 0) {
+                mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, -1);
+            }
         } else {
             (void) shapeMediaFormat(format, flags);
             // XXX: do we want to do this regardless of shaping enablement?
@@ -1556,6 +1582,34 @@
         }
     }
 
+    // push min/max QP to MediaMetrics after shaping
+    if (mIsVideo && mMetricsHandle != 0) {
+        int32_t qpIMin = -1;
+        if (format->findInt32("video-qp-i-min", &qpIMin)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin);
+        }
+        int32_t qpIMax = -1;
+        if (format->findInt32("video-qp-i-max", &qpIMax)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMax, qpIMax);
+        }
+        int32_t qpPMin = -1;
+        if (format->findInt32("video-qp-p-min", &qpPMin)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMin, qpPMin);
+        }
+        int32_t qpPMax = -1;
+        if (format->findInt32("video-qp-p-max", &qpPMax)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPPMax, qpPMax);
+        }
+        int32_t qpBMin = -1;
+        if (format->findInt32("video-qp-b-min", &qpBMin)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMin, qpBMin);
+        }
+        int32_t qpBMax = -1;
+        if (format->findInt32("video-qp-b-max", &qpBMax)) {
+            mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPBMax, qpBMax);
+        }
+    }
+
     updateLowLatency(format);
 
     msg->setMessage("format", format);
@@ -1875,14 +1929,40 @@
         sp<AMessage> deltas = updatedFormat->changesFrom(format, false /* deep */);
         size_t changeCount = deltas->countEntries();
         ALOGD("shapeMediaFormat: deltas(%zu): %s", changeCount, deltas->debugString(2).c_str());
+        if (mMetricsHandle != 0) {
+            mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, changeCount);
+        }
         if (changeCount > 0) {
             if (mMetricsHandle != 0) {
-                mediametrics_setInt32(mMetricsHandle, kCodecShapingEnhanced, changeCount);
                 // save some old properties before we fold in the new ones
                 int32_t bitrate;
                 if (format->findInt32(KEY_BIT_RATE, &bitrate)) {
                     mediametrics_setInt32(mMetricsHandle, kCodecOriginalBitrate, bitrate);
                 }
+                int32_t qpIMin = -1;
+                if (format->findInt32("original-video-qp-i-min", &qpIMin)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPIMin, qpIMin);
+                }
+                int32_t qpIMax = -1;
+                if (format->findInt32("original-video-qp-i-max", &qpIMax)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPIMax, qpIMax);
+                }
+                int32_t qpPMin = -1;
+                if (format->findInt32("original-video-qp-p-min", &qpPMin)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPPMin, qpPMin);
+                }
+                int32_t qpPMax = -1;
+                if (format->findInt32("original-video-qp-p-max", &qpPMax)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPPMax, qpPMax);
+                }
+                 int32_t qpBMin = -1;
+                if (format->findInt32("original-video-qp-b-min", &qpBMin)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPBMin, qpBMin);
+                }
+                int32_t qpBMax = -1;
+                if (format->findInt32("original-video-qp-b-max", &qpBMax)) {
+                    mediametrics_setInt32(mMetricsHandle, kCodecOriginalVideoQPBMax, qpBMax);
+                }
             }
             // NB: for any field in both format and deltas, the deltas copy wins
             format->extend(deltas);
@@ -3199,6 +3279,7 @@
                     ALOGV("TunnelPeekState: %s -> %s",
                           asString(previousState),
                           asString(TunnelPeekState::kBufferRendered));
+                    updatePlaybackDuration(msg);
                     // check that we have a notification set
                     if (mOnFrameRenderedNotification != NULL) {
                         sp<AMessage> notify = mOnFrameRenderedNotification->dup();
@@ -4905,6 +4986,10 @@
             return ALREADY_EXISTS;
         }
 
+        // in case we don't connect, ensure that we don't signal the surface is
+        // connected to the screen
+        mIsSurfaceToScreen = false;
+
         err = nativeWindowConnect(surface.get(), "connectToSurface");
         if (err == OK) {
             // Require a fresh set of buffers after each connect by using a unique generation
@@ -4930,6 +5015,10 @@
             if (!mAllowFrameDroppingBySurface) {
                 disableLegacyBufferDropPostQ(surface);
             }
+            // keep track whether or not the buffers of the connected surface go to the screen
+            int result = 0;
+            surface->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &result);
+            mIsSurfaceToScreen = result != 0;
         }
     }
     // do not return ALREADY_EXISTS unless surfaces are the same
@@ -4947,6 +5036,7 @@
         }
         // assume disconnected even on error
         mSurface.clear();
+        mIsSurfaceToScreen = false;
     }
     return err;
 }
diff --git a/media/libstagefright/PlaybackDurationAccumulator.h b/media/libstagefright/PlaybackDurationAccumulator.h
new file mode 100644
index 0000000..cb5f0c4
--- /dev/null
+++ b/media/libstagefright/PlaybackDurationAccumulator.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PLAYBACK_DURATION_ACCUMULATOR_H_
+
+namespace android {
+
+// Accumulates playback duration by processing render times of individual frames and by ignoring
+// frames rendered during inactive playbacks such as seeking, pausing, or re-buffering.
+class PlaybackDurationAccumulator {
+private:
+    // Controls the maximum delta between render times before considering the playback is not
+    // active and has stalled.
+    static const int64_t MAX_PRESENTATION_DURATION_NS = 500 * 1000 * 1000;
+
+public:
+    PlaybackDurationAccumulator() {
+        mPlaybackDurationNs = 0;
+        mPreviousRenderTimeNs = 0;
+    }
+
+    // Process a render time expressed in nanoseconds.
+    void processRenderTime(int64_t newRenderTimeNs) {
+        // If we detect wrap-around or out of order frames, just ignore the duration for this
+        // and the next frame.
+        if (newRenderTimeNs < mPreviousRenderTimeNs) {
+            mPreviousRenderTimeNs = 0;
+        }
+        if (mPreviousRenderTimeNs > 0) {
+            int64_t presentationDurationNs = newRenderTimeNs - mPreviousRenderTimeNs;
+            if (presentationDurationNs < MAX_PRESENTATION_DURATION_NS) {
+                mPlaybackDurationNs += presentationDurationNs;
+            }
+        }
+        mPreviousRenderTimeNs = newRenderTimeNs;
+    }
+
+    int64_t getDurationInSeconds() {
+        return mPlaybackDurationNs / 1000 / 1000 / 1000; // Nanoseconds to seconds.
+    }
+
+private:
+    // The playback duration accumulated so far.
+    int64_t mPlaybackDurationNs;
+    // The previous render time used to compute the next presentation duration.
+    int64_t mPreviousRenderTimeNs;
+};
+
+}
+
+#endif
+
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 3517bae..0e6f0b3 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -58,6 +58,7 @@
 struct PersistentSurface;
 class SoftwareRenderer;
 class Surface;
+class PlaybackDurationAccumulator;
 namespace hardware {
 namespace cas {
 namespace native {
@@ -418,6 +419,7 @@
     void updateLowLatency(const sp<AMessage> &msg);
     constexpr const char *asString(TunnelPeekState state, const char *default_string="?");
     void updateTunnelPeek(const sp<AMessage> &msg);
+    void updatePlaybackDuration(const sp<AMessage> &msg);
 
     sp<AMessage> mOutputFormat;
     sp<AMessage> mInputFormat;
@@ -429,6 +431,7 @@
     sp<ResourceManagerServiceProxy> mResourceManagerProxy;
 
     bool mIsVideo;
+    AString mLogSessionId;
     int32_t mVideoWidth;
     int32_t mVideoHeight;
     int32_t mRotationDegrees;
@@ -485,6 +488,9 @@
 
     std::shared_ptr<BufferChannelBase> mBufferChannel;
 
+    PlaybackDurationAccumulator * mPlaybackDurationAccumulator;
+    bool mIsSurfaceToScreen;
+
     MediaCodec(
             const sp<ALooper> &looper, pid_t pid, uid_t uid,
             std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase = nullptr,
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index a9617ec..3e4e4932 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -35,6 +35,7 @@
         "android.hardware.media.omx@1.0",
         "libandroidicu",
         "libfmq",
+        "libbase",
         "libbinder",
         "libhidlbase",
         "liblog",
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 58e2d2a..dc1b9b8 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "mediaserver"
 //#define LOG_NDEBUG 0
 
+#include <android-base/properties.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
@@ -42,6 +43,12 @@
     ResourceManagerService::instantiate();
     registerExtensions();
     ::android::hardware::configureRpcThreadpool(16, false);
+
+    if (!android::base::GetBoolProperty("ro.config.low_ram", false)) {
+        // Start the media.transcoding service if the device is not low ram
+        // device.
+        android::base::SetProperty("ctl.start", "media.transcoding");
+    }
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
     ::android::hardware::joinRpcThreadpool();
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index e3931b1..214a174 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -67,7 +67,7 @@
     return packages[0];
 }
 
-static int32_t getOpForSource(audio_source_t source) {
+int32_t getOpForSource(audio_source_t source) {
   switch (source) {
     case AUDIO_SOURCE_HOTWORD:
       return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
@@ -133,8 +133,8 @@
     return true;
 }
 
-bool recordingAllowed(const Identity& identity) {
-    return checkRecordingInternal(identity, String16(), /*start*/ false, AUDIO_SOURCE_DEFAULT);
+bool recordingAllowed(const Identity& identity, audio_source_t source) {
+    return checkRecordingInternal(identity, String16(), /*start*/ false, source);
 }
 
 bool startRecording(const Identity& identity, const String16& msg, audio_source_t source) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 6e75746..e7132b8 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -80,7 +80,8 @@
     }
 }
 
-bool recordingAllowed(const media::permission::Identity& identity);
+bool recordingAllowed(const media::permission::Identity& identity,
+        audio_source_t source = AUDIO_SOURCE_DEFAULT);
 bool startRecording(const media::permission::Identity& identity,
     const String16& msg, audio_source_t source);
 void finishRecording(const media::permission::Identity& identity, audio_source_t source);
@@ -98,6 +99,7 @@
 bool modifyPhoneStateAllowed(const media::permission::Identity& identity);
 bool bypassInterruptionPolicyAllowed(const media::permission::Identity& identity);
 void purgePermissionCache();
+int32_t getOpForSource(audio_source_t source);
 
 media::permission::Identity getCallingIdentity();
 
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 2436248..0af4c7b 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,14 +148,6 @@
     void                setFinalVolume(float volume);
     float               getFinalVolume() const { return mFinalVolume; }
 
-    /** @return true if the track has changed (metadata or volume) since
-     *          the last time this function was called,
-     *          true if this function was never called since the track creation,
-     *          false otherwise.
-     *  Thread safe.
-     */
-    bool            readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
-
     using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
     using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
     /** Copy the track metadata in the provided iterator. Thread safe. */
@@ -234,8 +226,6 @@
     bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
     void signalClientFlag(int32_t flag);
 
-    /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
-    void setMetadataHasChanged() { mChangeNotified.clear(); }
 public:
     void triggerEvents(AudioSystem::sync_event_t type);
     virtual void invalidate();
@@ -320,8 +310,6 @@
     bool                mFlushHwPending; // track requests for thread flush
     bool                mPauseHwPending = false; // direct/offload track request for thread pause
     audio_output_flags_t mFlags;
-    // If the last track change was notified to the client with readAndClearHasChanged
-    std::atomic_flag     mChangeNotified = ATOMIC_FLAG_INIT;
     TeePatches  mTeePatches;
 };  // end of Track
 
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 451c198..a1c2de7 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -19,17 +19,18 @@
     #error This header file should only be included from AudioFlinger.h
 #endif
 
-// Checks and monitors OP_RECORD_AUDIO
+// Checks and monitors app ops for audio record
 class OpRecordAudioMonitor : public RefBase {
 public:
     ~OpRecordAudioMonitor() override;
-    bool hasOpRecordAudio() const;
+    bool hasOp() const;
+    int32_t getOp() const { return mAppOp; }
 
     static sp<OpRecordAudioMonitor> createIfNeeded
         (const media::permission::Identity& identity, const audio_attributes_t& attr);
 
 private:
-    explicit OpRecordAudioMonitor(const media::permission::Identity& identity);
+    OpRecordAudioMonitor(const media::permission::Identity& identity, int32_t appOp);
     void onFirstRef() override;
 
     AppOpsManager mAppOpsManager;
@@ -44,12 +45,13 @@
     };
 
     sp<RecordAudioOpCallback> mOpCallback;
-    // called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
-    // and in onFirstRef()
-    void checkRecordAudio();
+    // called by RecordAudioOpCallback when the app op for this OpRecordAudioMonitor is updated
+    // in AppOp callback and in onFirstRef()
+    void checkOp();
 
-    std::atomic_bool mHasOpRecordAudio;
+    std::atomic_bool mHasOp;
     const media::permission::Identity mIdentity;
+    const int32_t mAppOp;
 };
 
 // record track
@@ -149,7 +151,7 @@
 
             bool                               mSilenced;
 
-            // used to enforce OP_RECORD_AUDIO
+            // used to enforce the audio record app op corresponding to this track's audio source
             sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
             std::string                        mSharedAudioPackageName = {};
             int32_t                            mStartFrames = -1;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d42a6ca..d878611 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1798,8 +1798,14 @@
 
 template <typename T>
 bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
-    const bool hasChanged = mHasChanged;
+    bool hasChanged = mHasChanged;
     mHasChanged = false;
+
+    for (const sp<T> &track : mActiveTracks) {
+        // Do not short-circuit as all hasChanged states must be reset
+        // as all the metadata are going to be sent
+        hasChanged |= track->readAndClearHasChanged();
+    }
     return hasChanged;
 }
 
@@ -1986,7 +1992,7 @@
 
 void AudioFlinger::PlaybackThread::onFirstRef()
 {
-    if (mOutput == nullptr || mOutput->stream == nullptr) {
+    if (!isStreamInitialized()) {
         ALOGE("The stream is not open yet"); // This should not happen.
     } else {
         // setEventCallback will need a strong pointer as a parameter. Calling it
@@ -2695,7 +2701,7 @@
 
 status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
     Mutex::Autolock _l(mLock);
-    if (mOutput == nullptr || mOutput->stream == nullptr) {
+    if (!isStreamInitialized()) {
         return NO_INIT;
     }
     return mOutput->stream->selectPresentation(presentationId, programId);
@@ -2992,16 +2998,7 @@
 
 void AudioFlinger::PlaybackThread::updateMetadata_l()
 {
-    if (mOutput == nullptr || mOutput->stream == nullptr ) {
-        return; // That should not happen
-    }
-    bool hasChanged = mActiveTracks.readAndClearHasChanged();
-    for (const sp<Track> &track : mActiveTracks) {
-        // Do not short-circuit as all hasChanged states must be reset
-        // as all the metadata are going to be sent
-        hasChanged |= track->readAndClearHasChanged();
-    }
-    if (!hasChanged) {
+    if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
         return; // nothing to do
     }
     StreamOutHalInterface::SourceMetadata metadata;
@@ -8186,7 +8183,7 @@
 {
     ALOGV("RecordThread::getActiveMicrophones");
     AutoMutex _l(mLock);
-    if (mInput == nullptr || mInput->stream == nullptr) {
+    if (!isStreamInitialized()) {
         return NO_INIT;
     }
     status_t status = mInput->stream->getActiveMicrophones(activeMicrophones);
@@ -8198,7 +8195,7 @@
 {
     ALOGV("setPreferredMicrophoneDirection(%d)", direction);
     AutoMutex _l(mLock);
-    if (mInput == nullptr || mInput->stream == nullptr) {
+    if (!isStreamInitialized()) {
         return NO_INIT;
     }
     return mInput->stream->setPreferredMicrophoneDirection(direction);
@@ -8208,7 +8205,7 @@
 {
     ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
     AutoMutex _l(mLock);
-    if (mInput == nullptr || mInput->stream == nullptr) {
+    if (!isStreamInitialized()) {
         return NO_INIT;
     }
     return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
@@ -8259,9 +8256,8 @@
 
 void AudioFlinger::RecordThread::updateMetadata_l()
 {
-    if (mInput == nullptr || mInput->stream == nullptr ||
-            !mActiveTracks.readAndClearHasChanged()) {
-        return;
+    if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+        return; // nothing to do
     }
     StreamInHalInterface::SinkMetadata metadata;
     for (const sp<RecordTrack> &track : mActiveTracks) {
@@ -9959,14 +9955,16 @@
                 }
             }
         }
+        for (const sp<MmapTrack> &track : mActiveTracks) {
+            track->setMetadataHasChanged();
+        }
     }
 }
 
 void AudioFlinger::MmapPlaybackThread::updateMetadata_l()
 {
-    if (mOutput == nullptr || mOutput->stream == nullptr ||
-            !mActiveTracks.readAndClearHasChanged()) {
-        return;
+    if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+        return; // nothing to do
     }
     StreamOutHalInterface::SourceMetadata metadata;
     for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10093,9 +10091,8 @@
 
 void AudioFlinger::MmapCaptureThread::updateMetadata_l()
 {
-    if (mInput == nullptr || mInput->stream == nullptr ||
-            !mActiveTracks.readAndClearHasChanged()) {
-        return;
+    if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
+        return; // nothing to do
     }
     StreamInHalInterface::SinkMetadata metadata;
     for (const sp<MmapTrack> &track : mActiveTracks) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 65db986..17acb16 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -527,6 +527,8 @@
                     }
                 }
 
+    virtual     bool isStreamInitialized() = 0;
+
 protected:
 
                 // entry describing an effect being suspended in mSuspendedSessions keyed vector
@@ -741,7 +743,9 @@
                     void            updatePowerState(sp<ThreadBase> thread, bool force = false);
 
                     /** @return true if one or move active tracks was added or removed since the
-                     *          last time this function was called or the vector was created. */
+                     *          last time this function was called or the vector was created.
+                     *          true if volume of one of active tracks was changed.
+                     */
                     bool            readAndClearHasChanged();
 
                 private:
@@ -993,6 +997,10 @@
                                         && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
                             }
 
+    virtual     bool        isStreamInitialized() {
+                                return !(mOutput == nullptr || mOutput->stream == nullptr);
+                            }
+
                 audio_channel_mask_t hapticChannelMask() const override {
                                          return mHapticChannelMask;
                                      }
@@ -1780,6 +1788,10 @@
                                           audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
                                           int64_t sharedAudioStartMs = -1);
 
+    virtual bool        isStreamInitialized() {
+                            return !(mInput == nullptr || mInput->stream == nullptr);
+                        }
+
 protected:
             void        dumpInternals_l(int fd, const Vector<String16>& args) override;
             void        dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1949,6 +1961,8 @@
     virtual     void        setRecordSilenced(audio_port_handle_t portId __unused,
                                               bool silenced __unused) {}
 
+    virtual     bool        isStreamInitialized() { return false; }
+
  protected:
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
                 void        dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -2011,6 +2025,10 @@
 
                 status_t    getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
 
+    virtual     bool        isStreamInitialized() {
+                                return !(mOutput == nullptr || mOutput->stream == nullptr);
+                            }
+
 protected:
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
 
@@ -2043,6 +2061,10 @@
 
                 status_t       getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
 
+    virtual     bool           isStreamInitialized() {
+                                   return !(mInput == nullptr || mInput->stream == nullptr);
+                               }
+
 protected:
 
                 AudioStreamIn*  mInput;
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 38dab5b..92f129c 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -255,6 +255,17 @@
 
     audio_channel_mask_t channelMask() const { return mChannelMask; }
 
+    /** @return true if the track has changed (metadata or volume) since
+     *          the last time this function was called,
+     *          true if this function was never called since the track creation,
+     *          false otherwise.
+     *  Thread safe.
+     */
+    bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
+
+    /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
+    void setMetadataHasChanged() { mChangeNotified.clear(); }
+
 protected:
     DISALLOW_COPY_AND_ASSIGN(TrackBase);
 
@@ -391,6 +402,9 @@
     std::atomic<FrameTime> mKernelFrameTime{};     // last frame time on kernel side.
     const pid_t         mCreatorPid;  // can be different from mclient->pid() for instance
                                       // when created by NuPlayer on behalf of a client
+
+    // If the last track change was notified to the client with readAndClearHasChanged
+    std::atomic_flag    mChangeNotified = ATOMIC_FLAG_INIT;
 };
 
 // PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3258689..8be7c86 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2215,7 +2215,7 @@
         return nullptr;
     }
 
-    // Capturing from FM TUNER output is not controlled by OP_RECORD_AUDIO
+    // Capturing from FM TUNER output is not controlled by an app op
     // because it does not affect users privacy as does capturing from an actual microphone.
     if (attr.source == AUDIO_SOURCE_FM_TUNER) {
         ALOGV("not muting FM TUNER capture for uid %d", identity.uid);
@@ -2227,12 +2227,12 @@
             || checkedIdentity.packageName.value().size() == 0) {
         return nullptr;
     }
-    return new OpRecordAudioMonitor(checkedIdentity);
+    return new OpRecordAudioMonitor(checkedIdentity, getOpForSource(attr.source));
 }
 
 AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
-        const Identity& identity)
-        : mHasOpRecordAudio(true), mIdentity(identity)
+        const Identity& identity, int32_t appOp)
+        : mHasOp(true), mIdentity(identity), mAppOp(appOp)
 {
 }
 
@@ -2246,36 +2246,36 @@
 
 void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef()
 {
-    checkRecordAudio();
+    checkOp();
     mOpCallback = new RecordAudioOpCallback(this);
-    ALOGV("start watching OP_RECORD_AUDIO for %s", mIdentity.toString().c_str());
-    mAppOpsManager.startWatchingMode(AppOpsManager::OP_RECORD_AUDIO,
+    ALOGV("start watching op %d for %s", mAppOp, mIdentity.toString().c_str());
+    mAppOpsManager.startWatchingMode(mAppOp,
         VALUE_OR_FATAL(aidl2legacy_string_view_String16(mIdentity.packageName.value_or(""))),
         mOpCallback);
 }
 
-bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOpRecordAudio() const {
-    return mHasOpRecordAudio.load();
+bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOp() const {
+    return mHasOp.load();
 }
 
-// Called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
-// and in onFirstRef()
+// Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
+// is updated in AppOp callback and in onFirstRef()
 // Note this method is never called (and never to be) for audio server / root track
 // due to the UID in createIfNeeded(). As a result for those record track, it's:
 // - not called from constructor,
 // - not called from RecordAudioOpCallback because the callback is not installed in this case
-void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkRecordAudio()
+void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkOp()
 {
 
-    const int32_t mode = mAppOpsManager.checkOp(AppOpsManager::OP_RECORD_AUDIO,
+    const int32_t mode = mAppOpsManager.checkOp(mAppOp,
             mIdentity.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
                 mIdentity.packageName.value_or(""))));
     const bool hasIt =  (mode == AppOpsManager::MODE_ALLOWED);
     // verbose logging only log when appOp changed
-    ALOGI_IF(hasIt != mHasOpRecordAudio.load(),
-            "OP_RECORD_AUDIO missing, %ssilencing record %s",
-            hasIt ? "un" : "", mIdentity.toString().c_str());
-    mHasOpRecordAudio.store(hasIt);
+    ALOGI_IF(hasIt != mHasOp.load(),
+            "App op %d missing, %ssilencing record %s",
+            mAppOp, hasIt ? "un" : "", mIdentity.toString().c_str());
+    mHasOp.store(hasIt);
 
 }
 
@@ -2286,12 +2286,12 @@
 void AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
             const String16& packageName) {
     UNUSED(packageName);
-    if (op != AppOpsManager::OP_RECORD_AUDIO) {
-        return;
-    }
     sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
     if (monitor != NULL) {
-        monitor->checkRecordAudio();
+        if (op != monitor->getOp()) {
+            return;
+        }
+        monitor->checkOp();
     }
 }
 
@@ -2661,7 +2661,7 @@
         return true;
     }
     // The monitor is only created for record tracks that can be silenced.
-    return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOpRecordAudio() : false;
+    return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOp() : false;
 }
 
 status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 27a7ac4..ca8e96c 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -187,8 +187,10 @@
                 availableOutputDevices = availPrimaryOutputDevices;
             }
 
-            // Do not use A2DP devices when in call but use them when not in call
-            // (e.g for voice mail playback)
+        }
+        // Do not use A2DP devices when in call but use them when not in call
+        // (e.g for voice mail playback)
+        if (isInCall()) {
             availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypes({
                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, }));
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 551013f..b9c715e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -580,7 +580,7 @@
     // Capturing from FM_TUNER source is controlled by captureTunerAudioInputAllowed() and
     // captureAudioOutputAllowed() (deprecated) as this does not affect users privacy
     // as does capturing from an actual microphone.
-    if (!(recordingAllowed(adjIdentity) || attr.source == AUDIO_SOURCE_FM_TUNER)) {
+    if (!(recordingAllowed(adjIdentity, attr.source) || attr.source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for %s",
                 __func__, adjIdentity.toString().c_str());
         return binderStatusFromStatusT(PERMISSION_DENIED);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a0448b4..329400d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -945,7 +945,7 @@
     if (!(ret = connectHelper<ICameraClient,Client>(
             sp<ICameraClient>{nullptr}, id, cameraId,
             internalPackageName, {}, uid, USE_CALLING_PID,
-            API_1, /*shimUpdateOnly*/ true, /*out*/ tmp)
+            API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0, /*out*/ tmp)
             ).isOk()) {
         ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
     }
@@ -1217,10 +1217,12 @@
 }
 
 void CameraService::finishConnectLocked(const sp<BasicClient>& client,
-        const CameraService::DescriptorPtr& desc) {
+        const CameraService::DescriptorPtr& desc, int oomScoreOffset) {
 
     // Make a descriptor for the incoming client
-    auto clientDescriptor = CameraService::CameraClientManager::makeClientDescriptor(client, desc);
+    auto clientDescriptor =
+            CameraService::CameraClientManager::makeClientDescriptor(client, desc,
+                    oomScoreOffset);
     auto evicted = mActiveClientManager.addAndEvict(clientDescriptor);
 
     logConnected(desc->getKey(), static_cast<int>(desc->getOwnerId()),
@@ -1250,6 +1252,7 @@
 
 status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
+        int oomScoreOffset,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
@@ -1301,7 +1304,8 @@
         for (size_t i = 0; i < ownerPids.size() - 1; i++) {
             pidToPriorityMap.emplace(ownerPids[i],
                     resource_policy::ClientPriority(priorityScores[i], states[i],
-                            /* isVendorClient won't get copied over*/ false));
+                            /* isVendorClient won't get copied over*/ false,
+                            /* oomScoreOffset won't get copied over*/ 0));
         }
         mActiveClientManager.updatePriorities(pidToPriorityMap);
 
@@ -1314,13 +1318,16 @@
             return BAD_VALUE;
         }
 
-        // Make descriptor for incoming client
+        int32_t actualScore = priorityScores[priorityScores.size() - 1];
+        int32_t actualState = states[states.size() - 1];
+
+        // Make descriptor for incoming client. We store the oomScoreOffset
+        // since we might need it later on new handleEvictionsLocked and
+        // ProcessInfoService would not take that into account.
         clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                 sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
-                state->getConflicting(),
-                priorityScores[priorityScores.size() - 1],
-                clientPid,
-                states[states.size() - 1]);
+                state->getConflicting(), actualScore, clientPid, actualState,
+                oomScoreOffset);
 
         resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
 
@@ -1463,7 +1470,7 @@
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
             clientPackageName, {}, clientUid, clientPid, API_1,
-            /*shimUpdateOnly*/ false, /*out*/client);
+            /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, /*out*/client);
 
     if(!ret.isOk()) {
         logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1539,7 +1546,7 @@
         const String16& cameraId,
         const String16& clientPackageName,
         const std::optional<String16>& clientFeatureId,
-        int clientUid,
+        int clientUid, int oomScoreOffset,
         /*out*/
         sp<hardware::camera2::ICameraDeviceUser>* device) {
 
@@ -1548,19 +1555,41 @@
     String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
     String16 clientPackageNameAdj = clientPackageName;
+    int callingPid = CameraThreadState::getCallingPid();
 
     if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         std::string vendorClient =
                 StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
         clientPackageNameAdj = String16(vendorClient.c_str());
     }
+
+    if (oomScoreOffset < 0) {
+        String8 msg =
+                String8::format("Cannot increase the priority of a client %s pid %d for "
+                        "camera id %s", String8(clientPackageNameAdj).string(), callingPid,
+                        id.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    // enforce system camera permissions
+    if (oomScoreOffset > 0 &&
+            !hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid())) {
+        String8 msg =
+                String8::format("Cannot change the priority of a client %s pid %d for "
+                        "camera id %s without SYSTEM_CAMERA permissions",
+                        String8(clientPackageNameAdj).string(), callingPid, id.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.string());
+    }
+
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
             /*api1CameraId*/-1, clientPackageNameAdj, clientFeatureId,
-            clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
+            clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
+            /*out*/client);
 
     if(!ret.isOk()) {
-        logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageNameAdj),
-                ret.toString8());
+        logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8());
         return ret;
     }
 
@@ -1572,7 +1601,7 @@
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
         int api1CameraId, const String16& clientPackageName,
         const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
-        apiLevel effectiveApiLevel, bool shimUpdateOnly,
+        apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
@@ -1623,7 +1652,7 @@
         sp<BasicClient> clientTmp = nullptr;
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
         if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
-                IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
+                IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, /*out*/&clientTmp,
                 /*out*/&partial)) != NO_ERROR) {
             switch (err) {
                 case -ENODEV:
@@ -1741,7 +1770,7 @@
             mServiceLock.lock();
         } else {
             // Otherwise, add client to active clients list
-            finishConnectLocked(client, partial);
+            finishConnectLocked(client, partial, oomScoreOffset);
         }
 
         client->setImageDumpMask(mImageDumpMask);
@@ -1788,7 +1817,8 @@
         auto offlineClientDesc = CameraClientManager::makeClientDescriptor(
                 kOfflineDevice + onlineClientDesc->getKey(), offlineClient, /*cost*/ 0,
                 /*conflictingKeys*/ std::set<String8>(), onlinePriority.getScore(),
-                onlineClientDesc->getOwnerId(), onlinePriority.getState());
+                onlineClientDesc->getOwnerId(), onlinePriority.getState(),
+                /*ommScoreOffset*/ 0);
 
         // Allow only one offline device per camera
         auto incompatibleClients = mActiveClientManager.getIncompatibleClients(offlineClientDesc);
@@ -3662,21 +3692,23 @@
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const String8& key, const sp<BasicClient>& value, int32_t cost,
         const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
-        int32_t state) {
+        int32_t state, int32_t oomScoreOffset) {
 
     bool isVendorClient = getCurrentServingCall() == BinderCallType::HWBINDER;
     int32_t score_adj = isVendorClient ? kVendorClientScore : score;
     int32_t state_adj = isVendorClient ? kVendorClientState: state;
 
     return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
-            key, value, cost, conflictingKeys, score_adj, ownerId, state_adj, isVendorClient);
+            key, value, cost, conflictingKeys, score_adj, ownerId, state_adj, isVendorClient,
+            oomScoreOffset);
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
-        const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial) {
+        const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial,
+        int32_t oomScoreOffset) {
     return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
             partial->getConflicting(), partial->getPriority().getScore(),
-            partial->getOwnerId(), partial->getPriority().getState());
+            partial->getOwnerId(), partial->getPriority().getState(), oomScoreOffset);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 10e1748..22dd0db 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -138,7 +138,7 @@
     virtual binder::Status     connectDevice(
             const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
             const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
-            int32_t clientUid,
+            int32_t clientUid, int scoreOffset,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
 
@@ -510,14 +510,14 @@
          */
         static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
                 int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
-                int32_t ownerId, int32_t state);
+                int32_t ownerId, int32_t state, int oomScoreOffset);
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
          * values intialized from a prior ClientDescriptor.
          */
         static DescriptorPtr makeClientDescriptor(const sp<BasicClient>& value,
-                const CameraService::DescriptorPtr& partial);
+                const CameraService::DescriptorPtr& partial, int oomScoreOffset);
 
     }; // class CameraClientManager
 
@@ -739,6 +739,7 @@
     // Only call with with mServiceLock held.
     status_t handleEvictionsLocked(const String8& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
+        int scoreOffset,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial);
@@ -772,7 +773,8 @@
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
             int api1CameraId, const String16& clientPackageName,
             const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
-            apiLevel effectiveApiLevel, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
+            apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset,
+            /*out*/sp<CLIENT>& device);
 
     // Lock guarding camera service state
     Mutex               mServiceLock;
@@ -831,7 +833,8 @@
      *
      * This method must be called with mServiceLock held.
      */
-    void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc);
+    void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc,
+            int oomScoreOffset);
 
     /**
      * Returns the underlying camera Id string mapped to a camera id int
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index aa1e95a..88d2f72 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -104,7 +104,7 @@
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mAidlICameraService->connectDevice(
             callbacks, String16(cameraId.c_str()), String16(""), {},
-            hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
+            hardware::ICameraService::USE_CALLING_UID, 0/*oomScoreOffset*/, /*out*/&deviceRemote);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
         ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 985b2f8..8bd4ed7 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -526,7 +526,7 @@
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         mCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
-                android::CameraService::USE_CALLING_UID, &device);
+                android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/, &device);
         if (device == nullptr) {
             continue;
         }
diff --git a/services/camera/libcameraservice/tests/ClientManagerTest.cpp b/services/camera/libcameraservice/tests/ClientManagerTest.cpp
index 037c5c2..c79ef45 100644
--- a/services/camera/libcameraservice/tests/ClientManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/ClientManagerTest.cpp
@@ -44,7 +44,7 @@
 
 TestDescriptorPtr makeDescFromTestClient(const TestClient& tc) {
     return std::make_shared<TestClientDescriptor>(/*ID*/tc.mId, tc, tc.mCost, tc.mConflictingKeys,
-            tc.mScore, tc.mOwnerId, tc.mState, tc.mIsVendorClient);
+            tc.mScore, tc.mOwnerId, tc.mState, tc.mIsVendorClient, /*oomScoreOffset*/0);
 }
 
 class TestClientManager : public ClientManager<int, TestClient> {
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 09258ef..d164885 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -64,20 +64,26 @@
      * case where the construction is offloaded to another thread which isn't a
      * hwbinder thread.
      */
-    ClientPriority(int32_t score, int32_t state, bool isVendorClient) :
-            mScore((score == INVALID_ADJ) ? UNKNOWN_ADJ : score),
-            mState(state),
-            mIsVendorClient(isVendorClient) { }
+    ClientPriority(int32_t score, int32_t state, bool isVendorClient, int32_t scoreOffset = 0) :
+            mIsVendorClient(isVendorClient), mScoreOffset(scoreOffset) {
+        setScore(score);
+        setState(state);
+    }
 
     int32_t getScore() const { return mScore; }
     int32_t getState() const { return mState; }
+    int32_t isVendorClient() const { return mIsVendorClient; }
 
     void setScore(int32_t score) {
         // For vendor clients, the score is set once and for all during
         // construction. Otherwise, it can get reset each time cameraserver
         // queries ActivityManagerService for oom_adj scores / states .
-        if (!mIsVendorClient) {
-            mScore = (score == INVALID_ADJ) ? UNKNOWN_ADJ : score;
+        // For clients where the score offset is set by the app, add it to the
+        // score provided by ActivityManagerService.
+        if (score == INVALID_ADJ) {
+            mScore = UNKNOWN_ADJ;
+        } else {
+            mScore = mScoreOffset + score;
         }
     }
 
@@ -87,9 +93,7 @@
       // queries ActivityManagerService for oom_adj scores / states
       // (ActivityManagerService returns a vendor process' state as
       // PROCESS_STATE_NONEXISTENT.
-      if (!mIsVendorClient) {
-          mState = state;
-      }
+      mState = state;
     }
 
     bool operator==(const ClientPriority& rhs) const {
@@ -120,6 +124,7 @@
         int32_t mScore;
         int32_t mState;
         bool mIsVendorClient = false;
+        int32_t mScoreOffset = 0;
 };
 
 // --------------------------------------------------------------------------------
@@ -137,9 +142,10 @@
 public:
     ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
             const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-            bool isVendorClient);
+            bool isVendorClient, int32_t oomScoreOffset);
     ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
-            int32_t score, int32_t ownerId, int32_t state, bool isVendorClient);
+            int32_t score, int32_t ownerId, int32_t state, bool isVendorClient,
+            int32_t oomScoreOffset);
 
     ~ClientDescriptor();
 
@@ -204,18 +210,18 @@
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
         const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-        bool isVendorClient) :
+        bool isVendorClient, int32_t scoreOffset) :
         mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
-        mPriority(score, state, isVendorClient),
+        mPriority(score, state, isVendorClient, scoreOffset),
         mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
         std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-        bool isVendorClient) :
+        bool isVendorClient, int32_t scoreOffset) :
         mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
         mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
-        mPriority(score, state, isVendorClient), mOwnerId{ownerId} {}
+        mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -266,6 +272,9 @@
     // off in the incoming priority argument since an AIDL thread might have
     // called getCurrentServingCall() == BinderCallType::HWBINDER after refreshing
     // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
+    if (mPriority.isVendorClient()) {
+        return;
+    }
     mPriority.setScore(priority.getScore());
     mPriority.setState(priority.getState());
 }
diff --git a/services/mediametrics/statsd_audiopolicy.cpp b/services/mediametrics/statsd_audiopolicy.cpp
index f44b7c4..3d9376e 100644
--- a/services/mediametrics/statsd_audiopolicy.cpp
+++ b/services/mediametrics/statsd_audiopolicy.cpp
@@ -32,7 +32,7 @@
 #include <statslog.h>
 
 #include "MediaMetricsService.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -50,7 +50,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::AudioPolicyData metrics_proto;
+    ::android::stats::mediametrics_message::AudioPolicyData metrics_proto;
 
     // flesh out the protobuf we'll hand off with our data
     //
diff --git a/services/mediametrics/statsd_audiorecord.cpp b/services/mediametrics/statsd_audiorecord.cpp
index 70a67ae..41efcaa 100644
--- a/services/mediametrics/statsd_audiorecord.cpp
+++ b/services/mediametrics/statsd_audiorecord.cpp
@@ -33,7 +33,7 @@
 
 #include "MediaMetricsService.h"
 #include "StringUtils.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -50,7 +50,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::AudioRecordData metrics_proto;
+    ::android::stats::mediametrics_message::AudioRecordData metrics_proto;
 
     // flesh out the protobuf we'll hand off with our data
     //
diff --git a/services/mediametrics/statsd_audiothread.cpp b/services/mediametrics/statsd_audiothread.cpp
index 34cc923..e9b6dd6 100644
--- a/services/mediametrics/statsd_audiothread.cpp
+++ b/services/mediametrics/statsd_audiothread.cpp
@@ -32,7 +32,7 @@
 #include <statslog.h>
 
 #include "MediaMetricsService.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -50,7 +50,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::AudioThreadData metrics_proto;
+    ::android::stats::mediametrics_message::AudioThreadData metrics_proto;
 
 #define	MM_PREFIX "android.media.audiothread."
 
diff --git a/services/mediametrics/statsd_audiotrack.cpp b/services/mediametrics/statsd_audiotrack.cpp
index fe269a1..59627ae 100644
--- a/services/mediametrics/statsd_audiotrack.cpp
+++ b/services/mediametrics/statsd_audiotrack.cpp
@@ -33,7 +33,7 @@
 
 #include "MediaMetricsService.h"
 #include "StringUtils.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -51,7 +51,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::AudioTrackData metrics_proto;
+    ::android::stats::mediametrics_message::AudioTrackData metrics_proto;
 
     // flesh out the protobuf we'll hand off with our data
     //
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 2cfdf24..c1a5163 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -55,6 +55,11 @@
 
     // flesh out the protobuf we'll hand off with our data
     //
+    //android.media.mediacodec.log-session-id   string
+    std::string sessionId;
+    if (item->getString("android.media.mediacodec.log-session-id", &sessionId)) {
+        metrics_proto.set_log_session_id(sessionId);
+    }
     // android.media.mediacodec.codec   string
     std::string codec;
     if (item->getString("android.media.mediacodec.codec", &codec)) {
@@ -300,6 +305,48 @@
         metrics_proto.set_original_bitrate(originalBitrate);
     }
 
+    // android.media.mediacodec.shaped
+    int32_t shapingEnhanced = -1;
+    if ( item->getInt32("android.media.mediacodec.shaped", &shapingEnhanced)) {
+        metrics_proto.set_shaping_enhanced(shapingEnhanced);
+    }
+
+    // android.media.mediacodec.original-video-qp-i-min
+    int32_t qpIMinOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-i-min", &qpIMinOri)) {
+        metrics_proto.set_original_video_qp_i_min(qpIMinOri);
+    }
+
+    // android.media.mediacodec.original-video-qp-i-max
+    int32_t qpIMaxOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-i-max", &qpIMaxOri)) {
+        metrics_proto.set_original_video_qp_i_max(qpIMaxOri);
+    }
+
+    // android.media.mediacodec.original-video-qp-p-min
+    int32_t qpPMinOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-p-min", &qpPMinOri)) {
+        metrics_proto.set_original_video_qp_p_min(qpPMinOri);
+    }
+
+    // android.media.mediacodec.original-video-qp-p-max
+    int32_t qpPMaxOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-p-max", &qpPMaxOri)) {
+        metrics_proto.set_original_video_qp_p_max(qpPMaxOri);
+    }
+
+    // android.media.mediacodec.original-video-qp-b-min
+    int32_t qpBMinOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-b-min", &qpBMinOri)) {
+        metrics_proto.set_original_video_qp_b_min(qpIMinOri);
+    }
+
+    // android.media.mediacodec.original-video-qp-b-max
+    int32_t qpBMaxOri = -1;
+    if ( item->getInt32("android.media.mediacodec.original-video-qp-b-max", &qpBMaxOri)) {
+        metrics_proto.set_original_video_qp_b_max(qpBMaxOri);
+    }
+
     std::string serialized;
     if (!metrics_proto.SerializeToString(&serialized)) {
         ALOGE("Failed to serialize codec metrics");
@@ -345,9 +392,33 @@
             << " queue_secure_input_buffer_error:" << queue_secure_input_buffer_error
             << " bitrate_mode:" << bitrate_mode
             << " bitrate:" << bitrate
+            << " original_bitrate:" << originalBitrate
             << " lifetime_millis:" << lifetime_millis
-            // TODO: add when log_session_id is merged.
-            // << " log_session_id:" << log_session_id
+            << " log_session_id:" << sessionId
+            << " channel_count:" << channelCount
+            << " sample_rate:" << sampleRate
+            << " encode_bytes:" << bytes
+            << " encode_frames:" << frames
+            << " encode_duration_us:" << durationUs
+            << " color_format:" << colorFormat
+            << " frame_rate:" << frameRate
+            << " capture_rate:" << captureRate
+            << " operating_rate:" << operatingRate
+            << " priority:" << priority
+            << " shaping_enhanced:" << shapingEnhanced
+
+            << " qp_i_min:" << qpIMin
+            << " qp_i_max:" << qpIMax
+            << " qp_p_min:" << qpPMin
+            << " qp_p_max:" << qpPMax
+            << " qp_b_min:" << qpBMin
+            << " qp_b_max:" << qpBMax
+            << " original_qp_i_min:" << qpIMinOri
+            << " original_qp_i_max:" << qpIMaxOri
+            << " original_qp_p_min:" << qpPMinOri
+            << " original_qp_p_max:" << qpPMaxOri
+            << " original_qp_b_min:" << qpBMinOri
+            << " original_qp_b_max:" << qpBMaxOri
             << " }";
     statsdLog->log(android::util::MEDIAMETRICS_CODEC_REPORTED, log.str());
     return true;
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 2378f33..4ac5621 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -32,7 +32,7 @@
 #include <statslog.h>
 
 #include "MediaMetricsService.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -50,7 +50,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::ExtractorData metrics_proto;
+    ::android::stats::mediametrics_message::ExtractorData metrics_proto;
 
     std::string format;
     if (item->getString("android.media.mediaextractor.fmt", &format)) {
@@ -68,17 +68,17 @@
     }
 
     std::string entry_point_string;
-    stats::mediametrics::ExtractorData::EntryPoint entry_point =
-            stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+    stats::mediametrics_message::ExtractorData::EntryPoint entry_point =
+            stats::mediametrics_message::ExtractorData_EntryPoint_OTHER;
     if (item->getString("android.media.mediaextractor.entry", &entry_point_string)) {
       if (entry_point_string == "sdk") {
-        entry_point = stats::mediametrics::ExtractorData_EntryPoint_SDK;
+        entry_point = stats::mediametrics_message::ExtractorData_EntryPoint_SDK;
       } else if (entry_point_string == "ndk-with-jvm") {
-        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_WITH_JVM;
+        entry_point = stats::mediametrics_message::ExtractorData_EntryPoint_NDK_WITH_JVM;
       } else if (entry_point_string == "ndk-no-jvm") {
-        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_NO_JVM;
+        entry_point = stats::mediametrics_message::ExtractorData_EntryPoint_NDK_NO_JVM;
       } else {
-        entry_point = stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+        entry_point = stats::mediametrics_message::ExtractorData_EntryPoint_OTHER;
       }
       metrics_proto.set_entry_point(entry_point);
     }
diff --git a/services/mediametrics/statsd_nuplayer.cpp b/services/mediametrics/statsd_nuplayer.cpp
index 33da81e..bdee1f2 100644
--- a/services/mediametrics/statsd_nuplayer.cpp
+++ b/services/mediametrics/statsd_nuplayer.cpp
@@ -32,7 +32,7 @@
 #include <statslog.h>
 
 #include "MediaMetricsService.h"
-#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
+#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
 #include "iface_statsd.h"
 
 namespace android {
@@ -54,7 +54,7 @@
 
     // the rest into our own proto
     //
-    ::android::stats::mediametrics::NuPlayerData metrics_proto;
+    ::android::stats::mediametrics_message::NuPlayerData metrics_proto;
 
     // flesh out the protobuf we'll hand off with our data
     //
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index db61061..f31202b 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -65,6 +65,7 @@
             enabled: true,
         },
     },
+    versions: ["1"],
 }
 
 cc_library {
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/.hash b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/.hash
new file mode 100644
index 0000000..df90ffb
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/.hash
@@ -0,0 +1 @@
+7e198281434e9c679b02265e95c51ea25ed180d3
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserver.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserver.aidl
new file mode 100644
index 0000000..73e0e0b
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserver.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserver {
+  oneway void onStatusChanged(android.media.MediaObservableEvent event, int uid, int pid, in android.media.MediaObservableParcel[] observables);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserverService.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserverService.aidl
new file mode 100644
index 0000000..c2d60af
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/IResourceObserverService.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserverService {
+  void registerObserver(android.media.IResourceObserver observer, in android.media.MediaObservableFilter[] filters);
+  void unregisterObserver(android.media.IResourceObserver observer);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableEvent.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableEvent.aidl
new file mode 100644
index 0000000..a45f0ba
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableEvent.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="long")
+enum MediaObservableEvent {
+  kBusy = 1,
+  kIdle = 2,
+  kAll = -1,
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableFilter.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableFilter.aidl
new file mode 100644
index 0000000..22ae284
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableFilter.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableFilter {
+  android.media.MediaObservableType type;
+  android.media.MediaObservableEvent eventFilter;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableParcel.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableParcel.aidl
new file mode 100644
index 0000000..2270d87
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableParcel.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableParcel {
+  android.media.MediaObservableType type;
+  long value = 0;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableType.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableType.aidl
new file mode 100644
index 0000000..eab3f3f
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/1/android/media/MediaObservableType.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="int")
+enum MediaObservableType {
+  kInvalid = 0,
+  kVideoSecureCodec = 1000,
+  kVideoNonSecureCodec = 1001,
+}
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index b80fe57..8b64134 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -131,10 +131,10 @@
 void MediaTranscodingService::instantiate() {
     std::shared_ptr<MediaTranscodingService> service =
             ::ndk::SharedRefBase::make<MediaTranscodingService>();
-    if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
-        // Once service is started, we want it to stay even is client side perished.
-        AServiceManager_forceLazyServicesPersist(true /*persist*/);
-        (void)AServiceManager_registerLazyService(service->asBinder().get(), getServiceName());
+    binder_status_t status =
+            AServiceManager_addService(service->asBinder().get(), getServiceName());
+    if (status != STATUS_OK) {
+        return;
     }
 }
 
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 0cb2fad..20e4bfb 100644
--- a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -481,7 +481,7 @@
         // Need thread pool to receive callbacks, otherwise oneway callbacks are
         // silently ignored.
         ABinderProcess_startThreadPool();
-        ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.transcoding"));
+        ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
         mService = IMediaTranscodingService::fromBinder(binder);
         if (mService == nullptr) {
             ALOGE("Failed to connect to the media.trascoding service.");
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index df2b4a3..cd11c88 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -32,8 +32,8 @@
         ":tv_tuner_aidl",
     ],
     imports: [
-        "android.hardware.common",
-        "android.hardware.common.fmq",
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
     ],
 
     backend: {