Merge "audio policy: default routing rules for BLE audio devices"
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index a04ab3f..d86094e 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -17,7 +17,10 @@
     manifest: "test_manifest.json",
     file_contexts: ":com.android.media-file_contexts",
     defaults: ["com.android.media-defaults"],
-    prebuilts: ["sdkinfo_45"],
+    prebuilts: [
+        "sdkinfo_45",
+        "media-linker-config",
+    ],
     installable: false,
 }
 
diff --git a/cmds/stagefright/AudioPlayer.cpp b/cmds/stagefright/AudioPlayer.cpp
index eb76953..55427ca 100644
--- a/cmds/stagefright/AudioPlayer.cpp
+++ b/cmds/stagefright/AudioPlayer.cpp
@@ -134,15 +134,18 @@
     success = format->findInt32(kKeySampleRate, &mSampleRate);
     CHECK(success);
 
-    int32_t numChannels, channelMask;
+    int32_t numChannels;
     success = format->findInt32(kKeyChannelCount, &numChannels);
     CHECK(success);
 
-    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
+    audio_channel_mask_t channelMask;
+    if (int32_t rawChannelMask; !format->findInt32(kKeyChannelMask, &rawChannelMask)) {
         // log only when there's a risk of ambiguity of channel mask selection
         ALOGI_IF(numChannels > 2,
                 "source format didn't specify channel mask, using (%d) channel order", numChannels);
         channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    } else {
+        channelMask = static_cast<audio_channel_mask_t>(rawChannelMask);
     }
 
     audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
diff --git a/drm/common/Android.bp b/drm/common/Android.bp
index 272684c..248570e 100644
--- a/drm/common/Android.bp
+++ b/drm/common/Android.bp
@@ -14,7 +14,7 @@
 // limitations under the License.
 //
 
-cc_library_static {
+cc_library {
     name: "libdrmframeworkcommon",
 
     srcs: [
@@ -35,7 +35,11 @@
 
     cflags: ["-Wall", "-Werror"],
 
-    shared_libs: ["libbinder"],
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils"
+    ],
 
     export_include_dirs: ["include"],
 }
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index fcd291f..8b7c551 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -31,12 +31,11 @@
         "liblog",
         "libbinder",
         "libdl",
+        "libdrmframeworkcommon",
         "libselinux",
         "libstagefright_foundation",
     ],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/drm/libdrmframework/Android.bp b/drm/libdrmframework/Android.bp
index 940c17d..b4a7b25 100644
--- a/drm/libdrmframework/Android.bp
+++ b/drm/libdrmframework/Android.bp
@@ -29,12 +29,11 @@
         "liblog",
         "libbinder",
         "libdl",
+        "libdrmframeworkcommon",
     ],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     export_include_dirs: ["include"],
-    export_static_lib_headers: ["libdrmframeworkcommon"],
+    export_shared_lib_headers: ["libdrmframeworkcommon"],
 
     cflags: ["-Werror"],
 }
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index bb9d7ec..9f52f7a 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -36,11 +36,11 @@
         "libcrypto",
         "libssl",
         "libdrmframework",
+        "libdrmframeworkcommon",
     ],
 
     static_libs: [
         "libdrmutility",
-        "libdrmframeworkcommon",
         "libfwdlock-common",
         "libfwdlock-converter",
         "libfwdlock-decoder",
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 05b6440..8045586 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -19,12 +19,11 @@
 
     srcs: ["src/DrmPassthruPlugIn.cpp"],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     shared_libs: [
         "libutils",
         "liblog",
         "libdl",
+        "libdrmframeworkcommon",
     ],
 
     local_include_dirs: ["include"],
diff --git a/media/OWNERS b/media/OWNERS
index bd83ad9..3e194f0 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -11,9 +11,11 @@
 lajos@google.com
 marcone@google.com
 mnaganov@google.com
+nchalko@google.com
 pawin@google.com
 philburk@google.com
 pmclean@google.com
+quxiangfang@google.com
 rachad@google.com
 rago@google.com
 robertshih@google.com
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 408db7e..72910c5 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -262,9 +262,10 @@
         work->result = C2_NO_MEMORY;
         return;
     }
-    C2WriteView wView = mOutputBlock->map().get();
-    if (wView.error()) {
-        ALOGE("write view map failed %d", wView.error());
+
+    err = mOutputBlock->map().get().error();
+    if (err) {
+        ALOGE("write view map failed %d", err);
         work->result = C2_CORRUPTED;
         return;
     }
diff --git a/media/codec2/core/include/C2Buffer.h b/media/codec2/core/include/C2Buffer.h
index 3d3587c..fe37b05 100644
--- a/media/codec2/core/include/C2Buffer.h
+++ b/media/codec2/core/include/C2Buffer.h
@@ -734,6 +734,22 @@
     }
 
     virtual ~C2Allocator() = default;
+
+    /**
+     * Returns a true if the handle looks valid for this allocator.
+     *
+     * It does not actually validate that the handle represents a valid allocation (by this
+     * allocator), only that the handle could have been returned by this allocator. As such,
+     * multiple allocators may return true for looksValid for the same handle.
+     *
+     * This method MUST be "non-blocking", MUST not access kernel and/or device drivers, and
+     * return within 1us.
+     *
+     * \param handle      the handle for an existing allocation (possibly from another
+     *                    allocator)
+     */
+    virtual bool checkHandle(const C2Handle *const handle) const = 0;
+
 protected:
     C2Allocator() = default;
 };
@@ -2156,9 +2172,12 @@
 };
 
 /**
- * An extension of C2Info objects that can contain arbitrary buffer data.
+ * A const metadata object that can contain arbitrary buffer data.
  *
- * \note This object is not describable and contains opaque data.
+ * This object is not an actual C2Info and is not attached to buffers (C2Buffer), but rather to
+ * frames (C2FrameData). It is not describable via C2ParamDescriptor.
+ *
+ * C2InfoBuffer is a const object that can be allocated on stack and is copiable.
  */
 class C2InfoBuffer {
 public:
@@ -2167,14 +2186,65 @@
      *
      * \return the parameter index.
      */
-    const C2Param::Index index() const;
+    const C2Param::Index index() const { return mIndex; }
 
     /**
      * Gets the buffer's data.
      *
      * \return the buffer's data.
      */
-    const C2BufferData data() const;
+    const C2BufferData data() const { return mData; }
+
+    /// Returns a clone of this as a global info buffer.
+    C2InfoBuffer asGlobal() const {
+        C2Param::Index index = mIndex;
+        index.convertToGlobal();
+        return C2InfoBuffer(index, mData);
+    }
+
+    /// Returns a clone of this as a port info buffer.
+    C2InfoBuffer asPort(bool output) const {
+        C2Param::Index index = mIndex;
+        index.convertToPort(output);
+        return C2InfoBuffer(index, mData);
+    }
+
+    /// Returns a clone of this as a stream info buffer.
+    C2InfoBuffer asStream(bool output, unsigned stream) const {
+        C2Param::Index index = mIndex;
+        index.convertToStream(output, stream);
+        return C2InfoBuffer(index, mData);
+    }
+
+    /**
+     * Creates a global info buffer containing a single linear block.
+     *
+     * \param index the core parameter index of this info buffer.
+     * \param block the content of the info buffer.
+     *
+     * \return shared pointer to the created info buffer.
+     */
+    static C2InfoBuffer CreateLinearBuffer(C2Param::CoreIndex index, const C2ConstLinearBlock &block);
+
+    /**
+     * Creates a global info buffer containing a single graphic block.
+     *
+     * \param index the core parameter index of this info buffer.
+     * \param block the content of the info buffer.
+     *
+     * \return shared pointer to the created info buffer.
+     */
+    static C2InfoBuffer CreateGraphicBuffer(C2Param::CoreIndex index, const C2ConstGraphicBlock &block);
+
+protected:
+    // no public constructor
+    explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks);
+    explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks);
+
+private:
+    C2Param::Index mIndex;
+    C2BufferData mData;
+    explicit C2InfoBuffer(C2Param::Index index, const C2BufferData &data);
 };
 
 /// @}
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 29bccd5..ebe7b40 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -249,6 +249,11 @@
 
     // low latency mode
     kParamIndexLowLatencyMode, // bool
+
+    // tunneled codec
+    kParamIndexTunneledMode, // struct
+    kParamIndexTunnelHandle, // int32[]
+    kParamIndexTunnelSystemTime, // int64
 };
 
 }
@@ -2182,6 +2187,79 @@
 typedef C2PortParam<C2Tuning, C2TimestampGapAdjustmentStruct> C2PortTimestampGapTuning;
 constexpr char C2_PARAMKEY_INPUT_SURFACE_TIMESTAMP_ADJUSTMENT[] = "input-surface.timestamp-adjustment";
 
+/* ===================================== TUNNELED CODEC ==================================== */
+
+/**
+ * Tunneled codec control.
+ */
+struct C2TunneledModeStruct {
+    /// mode
+    enum mode_t : uint32_t;
+    /// sync type
+    enum sync_type_t : uint32_t;
+
+    inline C2TunneledModeStruct() = default;
+
+    inline C2TunneledModeStruct(
+            size_t flexCount, mode_t mode_, sync_type_t type, std::vector<int32_t> id)
+        : mode(mode_), syncType(type) {
+        memcpy(&syncId, &id[0], c2_min(id.size(), flexCount) * FLEX_SIZE);
+    }
+
+    inline C2TunneledModeStruct(size_t flexCount, mode_t mode_, sync_type_t type, int32_t id)
+        : mode(mode_), syncType(type) {
+        if (flexCount >= 1) {
+            syncId[0] = id;
+        }
+    }
+
+    mode_t mode;          ///< tunneled mode
+    sync_type_t syncType; ///< type of sync used for tunneled mode
+    int32_t syncId[];     ///< sync id
+
+    DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(TunneledMode, syncId)
+    C2FIELD(mode, "mode")
+    C2FIELD(syncType, "sync-type")
+    C2FIELD(syncId, "sync-id")
+
+};
+
+C2ENUM(C2TunneledModeStruct::mode_t, uint32_t,
+    NONE,
+    SIDEBAND,
+);
+
+
+C2ENUM(C2TunneledModeStruct::sync_type_t, uint32_t,
+    REALTIME,
+    AUDIO_HW_SYNC,
+    HW_AV_SYNC,
+);
+
+/**
+ * Configure tunneled mode
+ */
+typedef C2PortParam<C2Tuning, C2TunneledModeStruct, kParamIndexTunneledMode>
+        C2PortTunneledModeTuning;
+constexpr char C2_PARAMKEY_TUNNELED_RENDER[] = "output.tunneled-render";
+
+/**
+ * Tunneled mode handle. The meaning of this is depends on the
+ * tunneled mode. If the tunneled mode is SIDEBAND, this is the
+ * sideband handle.
+ */
+typedef C2PortParam<C2Tuning, C2Int32Array, kParamIndexTunnelHandle> C2PortTunnelHandleTuning;
+constexpr char C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE[] = "output.tunnel-handle";
+
+/**
+ * The system time using CLOCK_MONOTONIC in nanoseconds at the tunnel endpoint.
+ * For decoders this is the render time for the output frame and
+ * this corresponds to the media timestamp of the output frame.
+ */
+typedef C2PortParam<C2Info, C2SimpleValueStruct<int64_t>, kParamIndexTunnelSystemTime>
+        C2PortTunnelSystemTime;
+constexpr char C2_PARAMKEY_OUTPUT_RENDER_TIME[] = "output.render-time";
+
 /// @}
 
 #endif  // C2CONFIG_H_
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 436269a..e938f96 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -317,7 +317,8 @@
         DEFINE_FIELD_BASED_COMPARISON_OPERATORS(Index, mIndex)
 
     private:
-        friend struct C2Param;           // for setStream, MakeStreamId, isValid
+        friend class C2InfoBuffer;       // for convertTo*
+        friend struct C2Param;           // for setStream, MakeStreamId, isValid, convertTo*
         friend struct _C2ParamInspector; // for testing
 
         /**
diff --git a/media/codec2/core/include/C2Work.h b/media/codec2/core/include/C2Work.h
index 6923f3e..67084cc 100644
--- a/media/codec2/core/include/C2Work.h
+++ b/media/codec2/core/include/C2Work.h
@@ -161,7 +161,7 @@
     //< for initial work item, these may also come from the parser - if provided
     //< for output buffers, these are the responses to requestedInfos
     std::vector<std::unique_ptr<C2Param>>      configUpdate;
-    std::vector<std::shared_ptr<C2InfoBuffer>> infoBuffers;
+    std::vector<C2InfoBuffer> infoBuffers;
 };
 
 struct C2Worklet {
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index c73cb52..1f0c856 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -943,14 +943,9 @@
 
     d->infoBuffers.resize(s.infoBuffers.size());
     i = 0;
-    for (const std::shared_ptr<C2InfoBuffer>& sInfoBuffer : s.infoBuffers) {
+    for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
         InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
-        if (!sInfoBuffer) {
-            LOG(ERROR) << "Null C2FrameData::infoBuffers["
-                       << i - 1 << "].";
-            return false;
-        }
-        if (!objcpy(&dInfoBuffer, *sInfoBuffer,
+        if (!objcpy(&dInfoBuffer, sInfoBuffer,
                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
             LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
                        << i - 1 << "].";
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
index 386f6e2..ab8635b 100644
--- a/media/codec2/hidl/1.1/utils/Android.bp
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -44,6 +44,12 @@
         "libstagefright_bufferpool@2.0.1",
         "libui",
     ],
+
+    // Device does not boot when global ThinLTO is enabled for this library.
+    // http://b/170595429
+    lto: {
+        never: true,
+    },
 }
 
 
diff --git a/media/codec2/tests/C2Param_test.cpp b/media/codec2/tests/C2Param_test.cpp
index c39605a..bb8130c 100644
--- a/media/codec2/tests/C2Param_test.cpp
+++ b/media/codec2/tests/C2Param_test.cpp
@@ -96,7 +96,7 @@
     const static std::vector<C2FieldDescriptor> _FIELD_LIST;
     static const std::vector<C2FieldDescriptor> FieldList();  // <= needed for C2FieldDescriptor
     const static FD::type_t TYPE = (FD::type_t)(CORE_INDEX | FD::STRUCT_FLAG);
-};
+} C2_PACK;
 
 DEFINE_NO_NAMED_VALUES_FOR(C2SizeStruct)
 
@@ -111,11 +111,13 @@
 
 struct C2TestStruct_A {
     int32_t signed32;
+    // 4-byte padding
     int64_t signed64[2];
     uint32_t unsigned32[1];
+    // 4-byte padding
     uint64_t unsigned64;
     float fp32;
-    C2SizeStruct sz[3];
+    C2SizeStruct sz[3]; // 8-byte structure, but 4-byte aligned
     uint8_t blob[100];
     char string[100];
     bool yesNo[100];
@@ -124,21 +126,21 @@
     static const std::vector<C2FieldDescriptor> FieldList();
     // enum : uint32_t { CORE_INDEX = kParamIndexTest };
     // typedef C2TestStruct_A _type;
-} __attribute__((packed));
+} __attribute__((aligned(4)));
 
 const std::vector<C2FieldDescriptor> C2TestStruct_A::FieldList() {
     return _FIELD_LIST;
 }
 const std::vector<C2FieldDescriptor> C2TestStruct_A::_FIELD_LIST =
     { { FD::INT32,    1, "s32",   0, 4 },
-      { FD::INT64,    2, "s64",   4, 8 },
-      { FD::UINT32,   1, "u32",  20, 4 },
-      { FD::UINT64,   1, "u64",  24, 8 },
-      { FD::FLOAT,    1, "fp",   32, 4 },
-      { C2SizeStruct::TYPE, 3, "size", 36, 8 },
-      { FD::BLOB,   100, "blob", 60, 1 },
-      { FD::STRING, 100, "str", 160, 1 },
-      { FD::BLOB,   100, "y-n", 260, 1 } };
+      { FD::INT64,    2, "s64",   8, 8 },
+      { FD::UINT32,   1, "u32",  24, 4 },
+      { FD::UINT64,   1, "u64",  32, 8 },
+      { FD::FLOAT,    1, "fp",   40, 4 },
+      { C2SizeStruct::TYPE, 3, "size", 44, 8 },
+      { FD::BLOB,   100, "blob", 68, 1 },
+      { FD::STRING, 100, "str", 168, 1 },
+      { FD::BLOB,   100, "y-n", 268, 1 } };
 
 TEST_P(C2ParamTest_ParamFieldList, VerifyStruct) {
     std::vector<C2FieldDescriptor> fields = GetParam(), expected = C2TestStruct_A::_FIELD_LIST;
@@ -198,11 +200,13 @@
 
 struct C2TestAStruct {
     int32_t signed32;
+    // 4-byte padding
     int64_t signed64[2];
     uint32_t unsigned32[1];
+    // 4-byte padding
     uint64_t unsigned64;
     float fp32;
-    C2SizeStruct sz[3];
+    C2SizeStruct sz[3]; // 8-byte structure, but 4-byte aligned
     uint8_t blob[100];
     char string[100];
     bool yesNo[100];
@@ -229,11 +233,13 @@
 
 struct C2TestBStruct {
     int32_t signed32;
+    // 4-byte padding
     int64_t signed64[2];
     uint32_t unsigned32[1];
+    // 4-byte padding
     uint64_t unsigned64;
     float fp32;
-    C2SizeStruct sz[3];
+    C2SizeStruct sz[3]; // 8-byte structure, but 4-byte aligned
     uint8_t blob[100];
     char string[100];
     bool yesNo[100];
@@ -286,7 +292,7 @@
         if (fields.size() > 1) {
             EXPECT_EQ(2u, fields.size());
             EXPECT_EQ(C2FieldDescriptor(FD::INT32, 1, "s32", 0, 4), fields[0]);
-            EXPECT_EQ(C2FieldDescriptor(this->FlexType, 0, "flex", 4, this->FLEX_SIZE),
+            EXPECT_EQ(C2FieldDescriptor(this->FlexType, 0, "flex", alignof(TypeParam) /* offset */, this->FLEX_SIZE),
                       fields[1]);
         } else {
             EXPECT_EQ(1u, fields.size());
@@ -392,6 +398,7 @@
 
 struct C2TestStruct_FlexEndS64 {
     int32_t signed32;
+    // 4-byte padding
     int64_t mSigned64Flex[];
 
     const static std::vector<C2FieldDescriptor> _FIELD_LIST;
@@ -406,7 +413,7 @@
 }
 const std::vector<C2FieldDescriptor> C2TestStruct_FlexEndS64::_FIELD_LIST = {
     { FD::INT32, 1, "s32", 0, 4 },
-    { FD::INT64, 0, "flex", 4, 8 },
+    { FD::INT64, 0, "flex", 8, 8 },
 };
 
 struct C2TestFlexS64Struct {
@@ -419,6 +426,7 @@
 
 struct C2TestFlexEndS64Struct {
     int32_t signed32;
+    // 4-byte padding
     int64_t mFlexSigned64[];
     C2TestFlexEndS64Struct() {}
 
@@ -468,7 +476,7 @@
     // enum : uint32_t { CORE_INDEX = C2TestStruct_FlexEndSize, FLEX_SIZE = 8 };
     // typedef C2TestStruct_FlexEndSize _type;
     // typedef C2SizeStruct FlexType;
-};
+} __attribute__((aligned(4)));
 
 const std::vector<C2FieldDescriptor> C2TestStruct_FlexEndSize::FieldList() {
     return _FIELD_LIST;
@@ -539,14 +547,14 @@
 TEST_F(C2ParamTest, FieldId) {
     // pointer constructor
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&((C2TestStruct_A*)0)->signed32));
-    EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&((C2TestStruct_A*)0)->signed64));
-    EXPECT_EQ(_C2FieldId(20, 4), _C2FieldId(&((C2TestStruct_A*)0)->unsigned32));
-    EXPECT_EQ(_C2FieldId(24, 8), _C2FieldId(&((C2TestStruct_A*)0)->unsigned64));
-    EXPECT_EQ(_C2FieldId(32, 4), _C2FieldId(&((C2TestStruct_A*)0)->fp32));
-    EXPECT_EQ(_C2FieldId(36, 8), _C2FieldId(&((C2TestStruct_A*)0)->sz));
-    EXPECT_EQ(_C2FieldId(60, 1), _C2FieldId(&((C2TestStruct_A*)0)->blob));
-    EXPECT_EQ(_C2FieldId(160, 1), _C2FieldId(&((C2TestStruct_A*)0)->string));
-    EXPECT_EQ(_C2FieldId(260, 1), _C2FieldId(&((C2TestStruct_A*)0)->yesNo));
+    EXPECT_EQ(_C2FieldId(8, 8), _C2FieldId(&((C2TestStruct_A*)0)->signed64));
+    EXPECT_EQ(_C2FieldId(24, 4), _C2FieldId(&((C2TestStruct_A*)0)->unsigned32));
+    EXPECT_EQ(_C2FieldId(32, 8), _C2FieldId(&((C2TestStruct_A*)0)->unsigned64));
+    EXPECT_EQ(_C2FieldId(40, 4), _C2FieldId(&((C2TestStruct_A*)0)->fp32));
+    EXPECT_EQ(_C2FieldId(44, 8), _C2FieldId(&((C2TestStruct_A*)0)->sz));
+    EXPECT_EQ(_C2FieldId(68, 1), _C2FieldId(&((C2TestStruct_A*)0)->blob));
+    EXPECT_EQ(_C2FieldId(168, 1), _C2FieldId(&((C2TestStruct_A*)0)->string));
+    EXPECT_EQ(_C2FieldId(268, 1), _C2FieldId(&((C2TestStruct_A*)0)->yesNo));
 
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&((C2TestFlexEndSizeStruct*)0)->signed32));
     EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&((C2TestFlexEndSizeStruct*)0)->mFlexSize));
@@ -556,14 +564,14 @@
 
     // member pointer constructor
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::signed32));
-    EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::signed64));
-    EXPECT_EQ(_C2FieldId(20, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::unsigned32));
-    EXPECT_EQ(_C2FieldId(24, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::unsigned64));
-    EXPECT_EQ(_C2FieldId(32, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::fp32));
-    EXPECT_EQ(_C2FieldId(36, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::sz));
-    EXPECT_EQ(_C2FieldId(60, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::blob));
-    EXPECT_EQ(_C2FieldId(160, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::string));
-    EXPECT_EQ(_C2FieldId(260, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::yesNo));
+    EXPECT_EQ(_C2FieldId(8, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::signed64));
+    EXPECT_EQ(_C2FieldId(24, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::unsigned32));
+    EXPECT_EQ(_C2FieldId(32, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::unsigned64));
+    EXPECT_EQ(_C2FieldId(40, 4), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::fp32));
+    EXPECT_EQ(_C2FieldId(44, 8), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::sz));
+    EXPECT_EQ(_C2FieldId(68, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::blob));
+    EXPECT_EQ(_C2FieldId(168, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::string));
+    EXPECT_EQ(_C2FieldId(268, 1), _C2FieldId((C2TestStruct_A*)0, &C2TestStruct_A::yesNo));
 
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId((C2TestFlexEndSizeStruct*)0, &C2TestFlexEndSizeStruct::signed32));
     EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId((C2TestFlexEndSizeStruct*)0, &C2TestFlexEndSizeStruct::mFlexSize));
@@ -573,14 +581,14 @@
 
     // member pointer sans type pointer
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&C2TestStruct_A::signed32));
-    EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&C2TestStruct_A::signed64));
-    EXPECT_EQ(_C2FieldId(20, 4), _C2FieldId(&C2TestStruct_A::unsigned32));
-    EXPECT_EQ(_C2FieldId(24, 8), _C2FieldId(&C2TestStruct_A::unsigned64));
-    EXPECT_EQ(_C2FieldId(32, 4), _C2FieldId(&C2TestStruct_A::fp32));
-    EXPECT_EQ(_C2FieldId(36, 8), _C2FieldId(&C2TestStruct_A::sz));
-    EXPECT_EQ(_C2FieldId(60, 1), _C2FieldId(&C2TestStruct_A::blob));
-    EXPECT_EQ(_C2FieldId(160, 1), _C2FieldId(&C2TestStruct_A::string));
-    EXPECT_EQ(_C2FieldId(260, 1), _C2FieldId(&C2TestStruct_A::yesNo));
+    EXPECT_EQ(_C2FieldId(8, 8), _C2FieldId(&C2TestStruct_A::signed64));
+    EXPECT_EQ(_C2FieldId(24, 4), _C2FieldId(&C2TestStruct_A::unsigned32));
+    EXPECT_EQ(_C2FieldId(32, 8), _C2FieldId(&C2TestStruct_A::unsigned64));
+    EXPECT_EQ(_C2FieldId(40, 4), _C2FieldId(&C2TestStruct_A::fp32));
+    EXPECT_EQ(_C2FieldId(44, 8), _C2FieldId(&C2TestStruct_A::sz));
+    EXPECT_EQ(_C2FieldId(68, 1), _C2FieldId(&C2TestStruct_A::blob));
+    EXPECT_EQ(_C2FieldId(168, 1), _C2FieldId(&C2TestStruct_A::string));
+    EXPECT_EQ(_C2FieldId(268, 1), _C2FieldId(&C2TestStruct_A::yesNo));
 
     EXPECT_EQ(_C2FieldId(0, 4), _C2FieldId(&C2TestFlexEndSizeStruct::signed32));
     EXPECT_EQ(_C2FieldId(4, 8), _C2FieldId(&C2TestFlexEndSizeStruct::mFlexSize));
@@ -594,14 +602,14 @@
 
     // pointer constructor in C2Param
     EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&((C2TestAInfo*)0)->signed32));
-    EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&((C2TestAInfo*)0)->signed64));
-    EXPECT_EQ(_C2FieldId(28, 4), _C2FieldId(&((C2TestAInfo*)0)->unsigned32));
-    EXPECT_EQ(_C2FieldId(32, 8), _C2FieldId(&((C2TestAInfo*)0)->unsigned64));
-    EXPECT_EQ(_C2FieldId(40, 4), _C2FieldId(&((C2TestAInfo*)0)->fp32));
-    EXPECT_EQ(_C2FieldId(44, 8), _C2FieldId(&((C2TestAInfo*)0)->sz));
-    EXPECT_EQ(_C2FieldId(68, 1), _C2FieldId(&((C2TestAInfo*)0)->blob));
-    EXPECT_EQ(_C2FieldId(168, 1), _C2FieldId(&((C2TestAInfo*)0)->string));
-    EXPECT_EQ(_C2FieldId(268, 1), _C2FieldId(&((C2TestAInfo*)0)->yesNo));
+    EXPECT_EQ(_C2FieldId(16, 8), _C2FieldId(&((C2TestAInfo*)0)->signed64));
+    EXPECT_EQ(_C2FieldId(32, 4), _C2FieldId(&((C2TestAInfo*)0)->unsigned32));
+    EXPECT_EQ(_C2FieldId(40, 8), _C2FieldId(&((C2TestAInfo*)0)->unsigned64));
+    EXPECT_EQ(_C2FieldId(48, 4), _C2FieldId(&((C2TestAInfo*)0)->fp32));
+    EXPECT_EQ(_C2FieldId(52, 8), _C2FieldId(&((C2TestAInfo*)0)->sz));
+    EXPECT_EQ(_C2FieldId(76, 1), _C2FieldId(&((C2TestAInfo*)0)->blob));
+    EXPECT_EQ(_C2FieldId(176, 1), _C2FieldId(&((C2TestAInfo*)0)->string));
+    EXPECT_EQ(_C2FieldId(276, 1), _C2FieldId(&((C2TestAInfo*)0)->yesNo));
 
     EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&((C2TestFlexEndSizeInfo*)0)->m.signed32));
     EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId(&((C2TestFlexEndSizeInfo*)0)->m.mFlexSize));
@@ -611,14 +619,14 @@
 
     // member pointer in C2Param
     EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::signed32));
-    EXPECT_EQ(_C2FieldId(12, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::signed64));
-    EXPECT_EQ(_C2FieldId(28, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::unsigned32));
-    EXPECT_EQ(_C2FieldId(32, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::unsigned64));
-    EXPECT_EQ(_C2FieldId(40, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::fp32));
-    EXPECT_EQ(_C2FieldId(44, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::sz));
-    EXPECT_EQ(_C2FieldId(68, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::blob));
-    EXPECT_EQ(_C2FieldId(168, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::string));
-    EXPECT_EQ(_C2FieldId(268, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::yesNo));
+    EXPECT_EQ(_C2FieldId(16, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::signed64));
+    EXPECT_EQ(_C2FieldId(32, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::unsigned32));
+    EXPECT_EQ(_C2FieldId(40, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::unsigned64));
+    EXPECT_EQ(_C2FieldId(48, 4), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::fp32));
+    EXPECT_EQ(_C2FieldId(52, 8), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::sz));
+    EXPECT_EQ(_C2FieldId(76, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::blob));
+    EXPECT_EQ(_C2FieldId(176, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::string));
+    EXPECT_EQ(_C2FieldId(276, 1), _C2FieldId((C2TestAInfo*)0, &C2TestAInfo::yesNo));
 
     // NOTE: cannot use a member pointer for flex params due to introduction of 'm'
     // EXPECT_EQ(_C2FieldId(8, 4), _C2FieldId(&C2TestFlexEndSizeInfo::m.signed32));
diff --git a/media/codec2/tests/vndk/C2BufferTest.cpp b/media/codec2/tests/vndk/C2BufferTest.cpp
index 780994a..a9f8e17 100644
--- a/media/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/codec2/tests/vndk/C2BufferTest.cpp
@@ -765,4 +765,54 @@
     }
 }
 
+TEST_F(C2BufferTest, InfoBufferTest) {
+    constexpr size_t kCapacity = 524288u;
+
+    // allocate a linear block
+    std::shared_ptr<C2BlockPool> linearPool(makeLinearBlockPool());
+    std::shared_ptr<C2LinearBlock> linearBlock;
+    ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
+            kCapacity,
+            { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
+            &linearBlock));
+
+    C2InfoBuffer info = C2InfoBuffer::CreateLinearBuffer(
+            kParamIndexNumber1, linearBlock->share(1024, kCapacity / 2, C2Fence()));
+    std::shared_ptr<C2InfoBuffer> spInfo(new C2InfoBuffer(info));
+    ASSERT_EQ(kParamIndexNumber1, spInfo->index().coreIndex());
+    ASSERT_TRUE(spInfo->index().isGlobal());
+    ASSERT_EQ(C2Param::INFO, spInfo->index().kind());
+    ASSERT_EQ(C2BufferData::LINEAR, spInfo->data().type());
+    ASSERT_EQ(1024, spInfo->data().linearBlocks()[0].offset());
+    ASSERT_EQ(kCapacity / 2, spInfo->data().linearBlocks()[0].size());
+    // handles must actually be identical after sharing into an info buffer
+    ASSERT_EQ(linearBlock->handle(), spInfo->data().linearBlocks()[0].handle());
+    ASSERT_EQ(linearPool->getAllocatorId(), spInfo->data().linearBlocks()[0].getAllocatorId());
+
+    C2InfoBuffer streamInfo = info.asStream(false /* output */,  1u);
+    ASSERT_EQ(kParamIndexNumber1, streamInfo.index().coreIndex());
+    ASSERT_TRUE(streamInfo.index().forStream());
+    ASSERT_TRUE(streamInfo.index().forInput());
+    ASSERT_EQ(1u, streamInfo.index().stream());
+    ASSERT_EQ(C2Param::INFO, streamInfo.index().kind());
+    ASSERT_EQ(C2BufferData::LINEAR, streamInfo.data().type());
+    ASSERT_EQ(1024, streamInfo.data().linearBlocks()[0].offset());
+    ASSERT_EQ(kCapacity / 2, streamInfo.data().linearBlocks()[0].size());
+    // handles must actually be identical after sharing into an info buffer
+    ASSERT_EQ(linearBlock->handle(), streamInfo.data().linearBlocks()[0].handle());
+    ASSERT_EQ(linearPool->getAllocatorId(), streamInfo.data().linearBlocks()[0].getAllocatorId());
+
+    C2InfoBuffer portInfo = streamInfo.asPort(true /* output */);
+    ASSERT_EQ(kParamIndexNumber1, portInfo.index().coreIndex());
+    ASSERT_TRUE(portInfo.index().forPort());
+    ASSERT_TRUE(portInfo.index().forOutput());
+    ASSERT_EQ(C2Param::INFO, portInfo.index().kind());
+    ASSERT_EQ(C2BufferData::LINEAR, portInfo.data().type());
+    ASSERT_EQ(1024, portInfo.data().linearBlocks()[0].offset());
+    ASSERT_EQ(kCapacity / 2, portInfo.data().linearBlocks()[0].size());
+    // handles must actually be identical after sharing into an info buffer
+    ASSERT_EQ(linearBlock->handle(), portInfo.data().linearBlocks()[0].handle());
+    ASSERT_EQ(linearPool->getAllocatorId(), portInfo.data().linearBlocks()[0].getAllocatorId());
+}
+
 } // namespace android
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
index 50c9e59..565137c 100644
--- a/media/codec2/vndk/C2AllocatorBlob.cpp
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -175,12 +175,12 @@
 }
 
 // static
-bool C2AllocatorBlob::isValid(const C2Handle* const o) {
+bool C2AllocatorBlob::CheckHandle(const C2Handle* const o) {
     size_t capacity;
     // Distinguish C2Handle purely allocated by C2AllocatorGralloc, or one allocated through
     // C2AllocatorBlob, by checking the handle's height is 1, and its format is
     // PixelFormat::BLOB by GetCapacityFromHandle().
-    return C2AllocatorGralloc::isValid(o) && GetCapacityFromHandle(o, &capacity) == C2_OK;
+    return C2AllocatorGralloc::CheckHandle(o) && GetCapacityFromHandle(o, &capacity) == C2_OK;
 }
 
 }  // namespace android
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index e1e1377..59471a2 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -25,6 +25,7 @@
 #include <hardware/gralloc.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
 
 #include <C2AllocatorGralloc.h>
 #include <C2Buffer.h>
@@ -103,7 +104,7 @@
     const static uint32_t MAGIC = '\xc2gr\x00';
 
     static
-    const ExtraData* getExtraData(const C2Handle *const handle) {
+    const ExtraData* GetExtraData(const C2Handle *const handle) {
         if (handle == nullptr
                 || native_handle_is_invalid(handle)
                 || handle->numInts < NUM_INTS) {
@@ -114,23 +115,23 @@
     }
 
     static
-    ExtraData *getExtraData(C2Handle *const handle) {
-        return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
+    ExtraData *GetExtraData(C2Handle *const handle) {
+        return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
     }
 
 public:
     void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
-        const ExtraData *ed = getExtraData(this);
+        const ExtraData *ed = GetExtraData(this);
         *generation = ed->generation;
         *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
         *igbp_slot = ed->igbp_slot;
     }
 
-    static bool isValid(const C2Handle *const o) {
+    static bool IsValid(const C2Handle *const o) {
         if (o == nullptr) { // null handle is always valid
             return true;
         }
-        const ExtraData *xd = getExtraData(o);
+        const ExtraData *xd = GetExtraData(o);
         // we cannot validate width/height/format/usage without accessing gralloc driver
         return xd != nullptr && xd->magic == MAGIC;
     }
@@ -152,7 +153,7 @@
         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
         if (res != nullptr) {
             memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
-            *getExtraData(res) = xd;
+            *GetExtraData(res) = xd;
         }
         return reinterpret_cast<C2HandleGralloc *>(res);
     }
@@ -180,10 +181,10 @@
     static bool MigrateNativeHandle(
             native_handle_t *handle,
             uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
-        if (handle == nullptr || !isValid(handle)) {
+        if (handle == nullptr || !IsValid(handle)) {
             return false;
         }
-        ExtraData *ed = getExtraData(handle);
+        ExtraData *ed = GetExtraData(handle);
         if (!ed) return false;
         ed->generation = generation;
         ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
@@ -195,7 +196,7 @@
 
     static native_handle_t* UnwrapNativeHandle(
             const C2Handle *const handle) {
-        const ExtraData *xd = getExtraData(handle);
+        const ExtraData *xd = GetExtraData(handle);
         if (xd == nullptr || xd->magic != MAGIC) {
             return nullptr;
         }
@@ -211,7 +212,7 @@
             uint32_t *width, uint32_t *height, uint32_t *format,
             uint64_t *usage, uint32_t *stride,
             uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
-        const ExtraData *xd = getExtraData(handle);
+        const ExtraData *xd = GetExtraData(handle);
         if (xd == nullptr) {
             return nullptr;
         }
@@ -253,7 +254,7 @@
     virtual ~C2AllocationGralloc() override;
 
     virtual c2_status_t map(
-            C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+            C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
             C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
     virtual c2_status_t unmap(
             uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
@@ -336,8 +337,12 @@
 }
 
 c2_status_t C2AllocationGralloc::map(
-        C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+        C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
         C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
+    const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
+                    (int32_t)(c2Rect.left + c2Rect.width) /* right */,
+                    (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
+
     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
     ALOGV("mapping buffer with usage %#llx => %#llx",
           (long long)usage.expected, (long long)grallocUsage);
@@ -386,10 +391,7 @@
             void *pointer = nullptr;
             // TODO: fence
             status_t err = GraphicBufferMapper::get().lock(
-                                const_cast<native_handle_t *>(mBuffer), grallocUsage,
-                                { (int32_t)rect.left, (int32_t)rect.top,
-                                  (int32_t)rect.width, (int32_t)rect.height },
-                                &pointer);
+                    const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
             if (err) {
                 ALOGE("failed transaction: lock(RGBA_1010102)");
                 return C2_CORRUPTED;
@@ -464,10 +466,7 @@
             void *pointer = nullptr;
             // TODO: fence
             status_t err = GraphicBufferMapper::get().lock(
-                                const_cast<native_handle_t*>(mBuffer), grallocUsage,
-                                { (int32_t)rect.left, (int32_t)rect.top,
-                                  (int32_t)rect.width, (int32_t)rect.height },
-                                &pointer);
+                    const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
             if (err) {
                 ALOGE("failed transaction: lock(RGBA_8888)");
                 return C2_CORRUPTED;
@@ -524,10 +523,7 @@
             void *pointer = nullptr;
             // TODO: fence
             status_t err = GraphicBufferMapper::get().lock(
-                                const_cast<native_handle_t*>(mBuffer), grallocUsage,
-                                { (int32_t)rect.left, (int32_t)rect.top,
-                                  (int32_t)rect.width, (int32_t)rect.height },
-                                &pointer);
+                    const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
             if (err) {
                 ALOGE("failed transaction: lock(BLOB)");
                 return C2_CORRUPTED;
@@ -544,10 +540,7 @@
             android_ycbcr ycbcrLayout;
 
             status_t err = GraphicBufferMapper::get().lockYCbCr(
-                        const_cast<native_handle_t*>(mBuffer), grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        &ycbcrLayout);
+                    const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
             if (err) {
                 ALOGE("failed transaction: lockYCbCr");
                 return C2_CORRUPTED;
@@ -784,8 +777,9 @@
     return mImpl->status();
 }
 
-bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
-    return C2HandleGralloc::isValid(o);
+// static
+bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
+    return C2HandleGralloc::IsValid(o);
 }
 
 } // namespace android
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 6d27a02..85623b8 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -73,7 +73,7 @@
 };
 
 // static
-bool C2HandleIon::isValid(const C2Handle * const o) {
+bool C2HandleIon::IsValid(const C2Handle * const o) {
     if (!o || memcmp(o, &cHeader, sizeof(cHeader))) {
         return false;
     }
@@ -579,7 +579,7 @@
         return mInit;
     }
 
-    if (!C2HandleIon::isValid(handle)) {
+    if (!C2HandleIon::IsValid(handle)) {
         return C2_BAD_VALUE;
     }
 
@@ -596,9 +596,8 @@
     return ret;
 }
 
-bool C2AllocatorIon::isValid(const C2Handle* const o) {
-    return C2HandleIon::isValid(o);
+bool C2AllocatorIon::CheckHandle(const C2Handle* const o) {
+    return C2HandleIon::IsValid(o);
 }
 
 } // namespace android
-
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 0b08f31..143355f 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -106,6 +106,7 @@
 class BufferDataBuddy : public C2BufferData {
     using C2BufferData::C2BufferData;
     friend class ::C2Buffer;
+    friend class ::C2InfoBuffer;
 };
 
 }  // namespace
@@ -396,26 +397,18 @@
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
         const C2Handle *handle) {
     // TODO: get proper allocator? and mutex?
-    static std::unique_ptr<C2Allocator> sAllocator = []{
-        std::unique_ptr<C2Allocator> allocator;
-        if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
-                android::C2PlatformAllocatorStore::BLOB) {
-            allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
-        } else {
-            allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
-        }
+    static std::shared_ptr<C2Allocator> sAllocator = []{
+        std::shared_ptr<C2Allocator> allocator;
+        std::shared_ptr<C2AllocatorStore> allocatorStore = android::GetCodec2PlatformAllocatorStore();
+        allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+
         return allocator;
     }();
 
     if (sAllocator == nullptr)
         return nullptr;
 
-    bool isValidHandle = false;
-    if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
-        isValidHandle = C2AllocatorBlob::isValid(handle);
-    } else {
-        isValidHandle = C2AllocatorIon::isValid(handle);
-    }
+    bool isValidHandle = sAllocator->checkHandle(handle);
 
     std::shared_ptr<C2LinearAllocation> alloc;
     if (isValidHandle) {
@@ -431,26 +424,18 @@
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
         const C2Handle *cHandle, const std::shared_ptr<BufferPoolData> &data) {
     // TODO: get proper allocator? and mutex?
-    static std::unique_ptr<C2Allocator> sAllocator = []{
-        std::unique_ptr<C2Allocator> allocator;
-        if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
-                android::C2PlatformAllocatorStore::BLOB) {
-            allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
-        } else {
-            allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
-        }
+    static std::shared_ptr<C2Allocator> sAllocator = []{
+        std::shared_ptr<C2Allocator> allocator;
+        std::shared_ptr<C2AllocatorStore> allocatorStore = android::GetCodec2PlatformAllocatorStore();
+        allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+
         return allocator;
     }();
 
     if (sAllocator == nullptr)
         return nullptr;
 
-    bool isValidHandle = false;
-    if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
-        isValidHandle = C2AllocatorBlob::isValid(cHandle);
-    } else {
-        isValidHandle = C2AllocatorIon::isValid(cHandle);
-    }
+    bool isValidHandle = sAllocator->checkHandle(cHandle);
 
     std::shared_ptr<C2LinearAllocation> alloc;
     if (isValidHandle) {
@@ -1148,7 +1133,7 @@
     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    if (C2AllocatorGralloc::isValid(cHandle)) {
+    if (sAllocator->isValid(cHandle)) {
         c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
         const std::shared_ptr<C2PooledBlockPoolData> poolData =
                 std::make_shared<C2PooledBlockPoolData>(data);
@@ -1185,6 +1170,7 @@
     type_t mType;
     std::vector<C2ConstLinearBlock> mLinearBlocks;
     std::vector<C2ConstGraphicBlock> mGraphicBlocks;
+    friend class C2InfoBuffer;
 };
 
 C2BufferData::C2BufferData(const std::vector<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
@@ -1200,6 +1186,35 @@
     return mImpl->graphicBlocks();
 }
 
+C2InfoBuffer::C2InfoBuffer(
+    C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks)
+    : mIndex(index), mData(BufferDataBuddy(blocks)) {
+}
+
+C2InfoBuffer::C2InfoBuffer(
+    C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks)
+    : mIndex(index), mData(BufferDataBuddy(blocks)) {
+}
+
+C2InfoBuffer::C2InfoBuffer(
+    C2Param::Index index, const C2BufferData &data)
+    : mIndex(index), mData(data) {
+}
+
+// static
+C2InfoBuffer C2InfoBuffer::CreateLinearBuffer(
+        C2Param::CoreIndex index, const C2ConstLinearBlock &block) {
+    return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
+                        { block });
+}
+
+// static
+C2InfoBuffer C2InfoBuffer::CreateGraphicBuffer(
+        C2Param::CoreIndex index, const C2ConstGraphicBlock &block) {
+    return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
+                        { block });
+}
+
 class C2Buffer::Impl {
 public:
     Impl(C2Buffer *thiz, const std::vector<C2ConstLinearBlock> &blocks)
@@ -1330,4 +1345,3 @@
 std::shared_ptr<C2Buffer> C2Buffer::CreateGraphicBuffer(const C2ConstGraphicBlock &block) {
     return std::shared_ptr<C2Buffer>(new C2Buffer({ block }));
 }
-
diff --git a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
index 4c330e5..bee028a 100644
--- a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
+++ b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
@@ -33,7 +33,8 @@
 }  // unnamed
 
 C2PlatformStorePluginLoader::C2PlatformStorePluginLoader(const char *libPath)
-    : mCreateBlockPool(nullptr) {
+    : mCreateBlockPool(nullptr),
+      mCreateAllocator(nullptr) {
     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
     if (mLibHandle == nullptr) {
         ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
diff --git a/media/codec2/vndk/include/C2AllocatorBlob.h b/media/codec2/vndk/include/C2AllocatorBlob.h
index 89ce949..fc67af7 100644
--- a/media/codec2/vndk/include/C2AllocatorBlob.h
+++ b/media/codec2/vndk/include/C2AllocatorBlob.h
@@ -44,7 +44,12 @@
 
     virtual ~C2AllocatorBlob() override;
 
-    static bool isValid(const C2Handle* const o);
+    virtual bool checkHandle(const C2Handle* const o) const override { return CheckHandle(o); }
+
+    static bool CheckHandle(const C2Handle* const o);
+
+    // deprecated
+    static bool isValid(const C2Handle* const o) { return CheckHandle(o); }
 
 private:
     std::shared_ptr<const Traits> mTraits;
diff --git a/media/codec2/vndk/include/C2AllocatorGralloc.h b/media/codec2/vndk/include/C2AllocatorGralloc.h
index ee7524e..578cf76 100644
--- a/media/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/codec2/vndk/include/C2AllocatorGralloc.h
@@ -84,7 +84,12 @@
 
     virtual ~C2AllocatorGralloc() override;
 
-    static bool isValid(const C2Handle* const o);
+    virtual bool checkHandle(const C2Handle* const o) const override { return CheckHandle(o); }
+
+    static bool CheckHandle(const C2Handle* const o);
+
+    // deprecated
+    static bool isValid(const C2Handle* const o) { return CheckHandle(o); }
 
 private:
     class Impl;
diff --git a/media/codec2/vndk/include/C2AllocatorIon.h b/media/codec2/vndk/include/C2AllocatorIon.h
index 1b2051f..6a49b7d 100644
--- a/media/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/codec2/vndk/include/C2AllocatorIon.h
@@ -57,7 +57,12 @@
 
     virtual ~C2AllocatorIon() override;
 
-    static bool isValid(const C2Handle* const o);
+    virtual bool checkHandle(const C2Handle* const o) const override { return CheckHandle(o); }
+
+    static bool CheckHandle(const C2Handle* const o);
+
+    // deprecated
+    static bool isValid(const C2Handle* const o) { return CheckHandle(o); }
 
     /**
      * Updates the usage mapper for subsequent new allocations, as well as the supported
diff --git a/media/codec2/vndk/internal/C2HandleIonInternal.h b/media/codec2/vndk/internal/C2HandleIonInternal.h
index c0e1d83..c67698c 100644
--- a/media/codec2/vndk/internal/C2HandleIonInternal.h
+++ b/media/codec2/vndk/internal/C2HandleIonInternal.h
@@ -28,7 +28,10 @@
           mFds{ bufferFd },
           mInts{ int(size & 0xFFFFFFFF), int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic } { }
 
-    static bool isValid(const C2Handle * const o);
+    static bool IsValid(const C2Handle * const o);
+
+    // deprecated
+    static bool isValid(const C2Handle * const o) { return IsValid(o); }
 
     int bufferFd() const { return mFds.mBuffer; }
     size_t size() const {
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 62936f6..fff12c4 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -223,7 +223,7 @@
     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
 
     std::shared_ptr<C2GraphicAllocation> alloc;
-    if (C2AllocatorGralloc::isValid(handle)) {
+    if (C2AllocatorGralloc::CheckHandle(handle)) {
         uint32_t width;
         uint32_t height;
         uint32_t format;
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index ab2b553..62f0808 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -1322,8 +1322,8 @@
                 || audioChannelCount <= 0 || audioChannelCount > FCC_8) {
             ALOGE("Invalid haptic channel count found in metadata: %d", mHapticChannelCount);
         } else {
-            const audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(
-                    audioChannelCount) | hapticChannelMask;
+            const audio_channel_mask_t channelMask = static_cast<audio_channel_mask_t>(
+                    audio_channel_out_mask_from_count(audioChannelCount) | hapticChannelMask);
             AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, channelMask);
             AMediaFormat_setInt32(
                     mMeta, AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT, mHapticChannelCount);
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 9007b10..dbb3d2b 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -231,7 +231,8 @@
         case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
             return AUDIO_FLAG_NO_MEDIA_PROJECTION;
         case AAUDIO_ALLOW_CAPTURE_BY_NONE:
-            return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+            return static_cast<audio_flags_mask_t>(
+                    AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE);
         default:
             ALOGE("%s() 0x%08X unrecognized", __func__, policy);
             return AUDIO_FLAG_NONE; //
diff --git a/media/libaaudio/tests/test_aaudio_monkey.cpp b/media/libaaudio/tests/test_aaudio_monkey.cpp
index be54835..cc29678 100644
--- a/media/libaaudio/tests/test_aaudio_monkey.cpp
+++ b/media/libaaudio/tests/test_aaudio_monkey.cpp
@@ -46,11 +46,10 @@
         int32_t numFrames);
 
 void AAudioMonkeyErrorCallbackProc(
-        AAudioStream *stream __unused,
-        void *userData __unused,
-        aaudio_result_t error) {
-    printf("Error Callback, error: %d\n",(int)error);
-}
+        AAudioStream * /* stream */,
+        void *userData,
+        aaudio_result_t error);
+
 
 // This function is not thread safe. Only use this from a single thread.
 double nextRandomDouble() {
@@ -99,6 +98,10 @@
         aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
         aaudio_result_t result = AAudioStream_waitForStateChange(getStream(),
             AAUDIO_STREAM_STATE_UNKNOWN, &state, 0);
+        if (result == AAUDIO_ERROR_DISCONNECTED) {
+            printf("WARNING - AAudioStream_waitForStateChange returned DISCONNECTED\n");
+            return true; // OK
+        }
         if (result != AAUDIO_OK) {
             printf("ERROR - AAudioStream_waitForStateChange returned %d\n", result);
             return false;
@@ -114,7 +117,7 @@
                (unsigned long long) framesRead,
                xRuns);
 
-        if (framesWritten < framesRead) {
+        if (state != AAUDIO_STREAM_STATE_STARTING && framesWritten < framesRead) {
             printf("WARNING - UNDERFLOW - diff = %d !!!!!!!!!!!!\n",
                    (int) (framesWritten - framesRead));
         }
@@ -132,8 +135,23 @@
             return -1;
         }
 
+        // update and query stream state
+        aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+        state = AAudioStream_getState(getStream());
+        if (state < 0) {
+            printf("ERROR - AAudioStream_getState returned %d\n", state);
+            return state;
+        }
+
+        if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
+            printf("#%d, Closing disconnected stream.\n", getIndex());
+            result = close();
+            return result;
+        }
+
         double dice = nextRandomDouble();
         // Select an action based on a weighted probability.
+        printf("    "); // indent action
         if (dice < PROB_START) {
             printf("start\n");
             result = AAudioStream_requestStart(getStream());
@@ -200,6 +218,10 @@
         return AAUDIO_CALLBACK_RESULT_CONTINUE;
     }
 
+    int getIndex() const {
+        return mIndex;
+    }
+
 private:
     const AAudioArgsParser  *mArgParser;
     const int                mIndex;
@@ -223,6 +245,13 @@
     return monkey->renderAudio(stream, audioData, numFrames);
 }
 
+void AAudioMonkeyErrorCallbackProc(
+        AAudioStream * /* stream */,
+        void *userData,
+        aaudio_result_t error) {
+    AAudioMonkey *monkey = (AAudioMonkey *) userData;
+    printf("#%d, Error Callback, error: %d\n", monkey->getIndex(), (int)error);
+}
 
 static void usage() {
     AAudioArgsParser::usage();
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index d6671e3..55b836f 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -279,7 +279,8 @@
         mAttributes.source = inputSource;
         if (inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION
                 || inputSource == AUDIO_SOURCE_CAMCORDER) {
-            mAttributes.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+            mAttributes.flags = static_cast<audio_flags_mask_t>(
+                    mAttributes.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
         }
     } else {
         // stream type shouldn't be looked at, this track has audio attributes
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 41af78c..2c40fbb 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -227,7 +227,7 @@
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
     mAttributes.usage = AUDIO_USAGE_UNKNOWN;
-    mAttributes.flags = 0x0;
+    mAttributes.flags = AUDIO_FLAG_NONE;
     strcpy(mAttributes.tags, "");
 }
 
@@ -467,7 +467,7 @@
     if (format == AUDIO_FORMAT_DEFAULT) {
         format = AUDIO_FORMAT_PCM_16_BIT;
     } else if (format == AUDIO_FORMAT_IEC61937) { // HDMI pass-through?
-        mAttributes.flags |= AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+        flags = static_cast<audio_output_flags_t>(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO);
     }
 
     // validate parameters
@@ -644,6 +644,36 @@
     return status;
 }
 
+
+status_t AudioTrack::set(
+        audio_stream_type_t streamType,
+        uint32_t sampleRate,
+        audio_format_t format,
+        uint32_t channelMask,
+        size_t frameCount,
+        audio_output_flags_t flags,
+        callback_t cbf,
+        void* user,
+        int32_t notificationFrames,
+        const sp<IMemory>& sharedBuffer,
+        bool threadCanCallJava,
+        audio_session_t sessionId,
+        transfer_type transferType,
+        const audio_offload_info_t *offloadInfo,
+        uid_t uid,
+        pid_t pid,
+        const audio_attributes_t* pAttributes,
+        bool doNotReconnect,
+        float maxRequiredSpeed,
+        audio_port_handle_t selectedDeviceId)
+{
+    return set(streamType, sampleRate, format,
+            static_cast<audio_channel_mask_t>(channelMask),
+            frameCount, flags, cbf, user, notificationFrames, sharedBuffer,
+            threadCanCallJava, sessionId, transferType, offloadInfo, uid, pid,
+            pAttributes, doNotReconnect, maxRequiredSpeed, selectedDeviceId);
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioTrack::start()
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index b4e07e0..7c304a1 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,6 +24,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
+#include <media/AudioSanitizer.h>
 #include <media/IAudioPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 #include <mediautils/TimeCheck.h>
@@ -1221,7 +1222,7 @@
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             uint32_t sampleRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
-            audio_channel_mask_t channelMask = data.readInt32();
+            audio_channel_mask_t channelMask = (audio_channel_mask_t) data.readInt32();
             reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) );
             return NO_ERROR;
         } break;
@@ -1495,10 +1496,15 @@
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_port port = {};
-            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+            status_t status = data.read(&port, sizeof(struct audio_port));
+            if (status != NO_ERROR) {
                 ALOGE("b/23905951");
+                return status;
             }
-            status_t status = getAudioPort(&port);
+            status = AudioSanitizer::sanitizeAudioPort(&port);
+            if (status == NO_ERROR) {
+                status = getAudioPort(&port);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&port, sizeof(struct audio_port));
@@ -1508,12 +1514,20 @@
         case CREATE_AUDIO_PATCH: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_patch patch;
-            data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
-                ALOGE("b/23905951");
+            status_t status = data.read(&patch, sizeof(struct audio_patch));
+            if (status != NO_ERROR) {
+                return status;
             }
-            status_t status = createAudioPatch(&patch, &handle);
+            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+            status = data.read(&handle, sizeof(audio_patch_handle_t));
+            if (status != NO_ERROR) {
+                ALOGE("b/23905951");
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPatch(&patch);
+            if (status == NO_ERROR) {
+                status = createAudioPatch(&patch, &handle);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -1558,8 +1572,14 @@
         case SET_AUDIO_PORT_CONFIG: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_port_config config;
-            data.read(&config, sizeof(struct audio_port_config));
-            status_t status = setAudioPortConfig(&config);
+            status_t status = data.read(&config, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPortConfig(&config);
+            if (status == NO_ERROR) {
+                status = setAudioPortConfig(&config);
+            }
             reply->writeInt32(status);
             return NO_ERROR;
         } break;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 9d3212b..81f9dff 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -26,6 +26,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <media/AudioEffect.h>
+#include <media/AudioSanitizer.h>
 #include <media/IAudioPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 #include <mediautils/TimeCheck.h>
@@ -1759,7 +1760,6 @@
             if (status != NO_ERROR) {
                 return status;
             }
-            sanetizeAudioAttributes(&attr);
             audio_session_t session = (audio_session_t)data.readInt32();
             audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
             bool hasStream = data.readInt32() != 0;
@@ -1777,10 +1777,14 @@
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
             audio_io_handle_t output = 0;
             std::vector<audio_io_handle_t> secondaryOutputs;
-            status = getOutputForAttr(&attr,
-                    &output, session, &stream, pid, uid,
-                    &config,
-                    flags, &selectedDeviceId, &portId, &secondaryOutputs);
+
+            status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+            if (status == NO_ERROR) {
+                status = getOutputForAttr(&attr,
+                                          &output, session, &stream, pid, uid,
+                                          &config,
+                                          flags, &selectedDeviceId, &portId, &secondaryOutputs);
+            }
             reply->writeInt32(status);
             status = reply->write(&attr, sizeof(audio_attributes_t));
             if (status != NO_ERROR) {
@@ -1819,8 +1823,11 @@
         case GET_INPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_attributes_t attr = {};
-            data.read(&attr, sizeof(audio_attributes_t));
-            sanetizeAudioAttributes(&attr);
+            status_t status = data.read(&attr, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+
             audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
             audio_unique_id_t riid = (audio_unique_id_t)data.readInt32();
             audio_session_t session = (audio_session_t)data.readInt32();
@@ -1833,9 +1840,13 @@
             audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
             audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32();
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
-            status_t status = getInputForAttr(&attr, &input, riid, session, pid, uid,
-                                              opPackageName, &config,
-                                              flags, &selectedDeviceId, &portId);
+
+            status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+            if (status == NO_ERROR) {
+                status = getInputForAttr(&attr, &input, riid, session, pid, uid,
+                                         opPackageName, &config,
+                                         flags, &selectedDeviceId, &portId);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->writeInt32(input);
@@ -1916,11 +1927,15 @@
             if (status != NO_ERROR) {
                 return status;
             }
+
             int index = data.readInt32();
             audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
 
-            reply->writeInt32(static_cast <uint32_t>(setVolumeIndexForAttributes(attributes,
-                                                                                 index, device)));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = setVolumeIndexForAttributes(attributes, index, device);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         } break;
 
@@ -1934,8 +1949,11 @@
             audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
 
             int index = 0;
-            status = getVolumeIndexForAttributes(attributes, index, device);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getVolumeIndexForAttributes(attributes, index, device);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1951,8 +1969,11 @@
             }
 
             int index = 0;
-            status = getMinVolumeIndexForAttributes(attributes, index);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getMinVolumeIndexForAttributes(attributes, index);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1968,8 +1989,11 @@
             }
 
             int index = 0;
-            status = getMaxVolumeIndexForAttributes(attributes, index);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getMaxVolumeIndexForAttributes(attributes, index);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1987,31 +2011,37 @@
         case GET_OUTPUT_FOR_EFFECT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc = {};
-            if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+            status_t status = data.read(&desc, sizeof(desc));
+            if (status != NO_ERROR) {
                 android_errorWriteLog(0x534e4554, "73126106");
+                return status;
             }
-            (void)sanitizeEffectDescriptor(&desc);
-            audio_io_handle_t output = getOutputForEffect(&desc);
-            reply->writeInt32(static_cast <int>(output));
+            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+            status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+            if (status == NO_ERROR) {
+                output = getOutputForEffect(&desc);
+            }
+            reply->writeInt32(static_cast <int32_t>(output));
             return NO_ERROR;
         } break;
 
         case REGISTER_EFFECT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc = {};
-            if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+            status_t status = data.read(&desc, sizeof(desc));
+            if (status != NO_ERROR) {
                 android_errorWriteLog(0x534e4554, "73126106");
+                return status;
             }
-            (void)sanitizeEffectDescriptor(&desc);
             audio_io_handle_t io = data.readInt32();
             uint32_t strategy = data.readInt32();
             audio_session_t session = (audio_session_t) data.readInt32();
             int id = data.readInt32();
-            reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
-                                                                   io,
-                                                                   strategy,
-                                                                   session,
-                                                                   id)));
+            status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+            if (status == NO_ERROR) {
+                status = registerEffect(&desc, io, strategy, session, id);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         } break;
 
@@ -2120,7 +2150,11 @@
             if (status != NO_ERROR) return status;
             status = data.read(&attributes, sizeof(audio_attributes_t));
             if (status != NO_ERROR) return status;
-            reply->writeInt32(isDirectOutputSupported(config, attributes));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = isDirectOutputSupported(config, attributes);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         }
 
@@ -2159,10 +2193,15 @@
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port port = {};
-            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+            status_t status = data.read(&port, sizeof(struct audio_port));
+            if (status != NO_ERROR) {
                 ALOGE("b/23912202");
+                return status;
             }
-            status_t status = getAudioPort(&port);
+            status = AudioSanitizer::sanitizeAudioPort(&port);
+            if (status == NO_ERROR) {
+                status = getAudioPort(&port);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&port, sizeof(struct audio_port));
@@ -2173,12 +2212,20 @@
         case CREATE_AUDIO_PATCH: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_patch patch = {};
-            data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
-                ALOGE("b/23912202");
+            status_t status = data.read(&patch, sizeof(struct audio_patch));
+            if (status != NO_ERROR) {
+                return status;
             }
-            status_t status = createAudioPatch(&patch, &handle);
+            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+            status = data.read(&handle, sizeof(audio_patch_handle_t));
+            if (status != NO_ERROR) {
+                ALOGE("b/23912202");
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPatch(&patch);
+            if (status == NO_ERROR) {
+                status = createAudioPatch(&patch, &handle);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -2228,9 +2275,12 @@
         case SET_AUDIO_PORT_CONFIG: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port_config config = {};
-            data.read(&config, sizeof(struct audio_port_config));
-            (void)sanitizeAudioPortConfig(&config);
-            status_t status = setAudioPortConfig(&config);
+            status_t status = data.read(&config, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            (void)AudioSanitizer::sanitizeAudioPortConfig(&config);
+            status = setAudioPortConfig(&config);
             reply->writeInt32(status);
             return NO_ERROR;
         }
@@ -2306,13 +2356,25 @@
         case START_AUDIO_SOURCE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port_config source = {};
-            data.read(&source, sizeof(struct audio_port_config));
-            (void)sanitizeAudioPortConfig(&source);
+            status_t status = data.read(&source, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
             audio_attributes_t attributes = {};
-            data.read(&attributes, sizeof(audio_attributes_t));
-            sanetizeAudioAttributes(&attributes);
+            status = data.read(&attributes, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPortConfig(&source);
+            if (status == NO_ERROR) {
+                // OK to not always sanitize attributes as startAudioSource() is not called if
+                // the port config is invalid.
+                status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "68953950");
+            }
             audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
-            status_t status = startAudioSource(&source, &attributes, &portId);
+            if (status == NO_ERROR) {
+                status = startAudioSource(&source, &attributes, &portId);
+            }
             reply->writeInt32(status);
             reply->writeInt32(portId);
             return NO_ERROR;
@@ -2696,7 +2758,7 @@
         case SET_ALLOWED_CAPTURE_POLICY: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             uid_t uid = data.readInt32();
-            audio_flags_mask_t flags = data.readInt32();
+            audio_flags_mask_t flags = static_cast<audio_flags_mask_t>(data.readInt32());
             status_t status = setAllowedCapturePolicy(uid, flags);
             reply->writeInt32(status);
             return NO_ERROR;
@@ -2898,44 +2960,6 @@
     }
 }
 
-/** returns true if string overflow was prevented by zero termination */
-template <size_t size>
-static bool preventStringOverflow(char (&s)[size]) {
-    if (strnlen(s, size) < size) return false;
-    s[size - 1] = '\0';
-    return true;
-}
-
-void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr)
-{
-    const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
-    if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
-        android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging
-    }
-    attr->tags[tagsMaxSize - 1] = '\0';
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeEffectDescriptor(effect_descriptor_t* desc)
-{
-    if (preventStringOverflow(desc->name)
-        | /* always */ preventStringOverflow(desc->implementor)) {
-        android_errorWriteLog(0x534e4554, "73126106"); // SafetyNet logging
-        return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeAudioPortConfig(struct audio_port_config* config)
-{
-    if (config->type == AUDIO_PORT_TYPE_DEVICE &&
-        preventStringOverflow(config->ext.device.address)) {
-        return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 } // namespace android
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index a9946da..de183d8 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -344,6 +344,27 @@
                             bool doNotReconnect = false,
                             float maxRequiredSpeed = 1.0f,
                             audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+    // FIXME(b/169889714): Vendor code depends on the old method signature at link time
+            status_t    set(audio_stream_type_t streamType,
+                            uint32_t sampleRate,
+                            audio_format_t format,
+                            uint32_t channelMask,
+                            size_t frameCount   = 0,
+                            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                            callback_t cbf      = NULL,
+                            void* user          = NULL,
+                            int32_t notificationFrames = 0,
+                            const sp<IMemory>& sharedBuffer = 0,
+                            bool threadCanCallJava = false,
+                            audio_session_t sessionId  = AUDIO_SESSION_ALLOCATE,
+                            transfer_type transferType = TRANSFER_DEFAULT,
+                            const audio_offload_info_t *offloadInfo = NULL,
+                            uid_t uid = AUDIO_UID_INVALID,
+                            pid_t pid = -1,
+                            const audio_attributes_t* pAttributes = NULL,
+                            bool doNotReconnect = false,
+                            float maxRequiredSpeed = 1.0f,
+                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
 
     /* Result of constructing the AudioTrack. This must be checked for successful initialization
      * before using any AudioTrack API (except for set()), because using
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 2d5f687..837375d 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -288,10 +288,6 @@
                                     const Parcel& data,
                                     Parcel* reply,
                                     uint32_t flags = 0);
-private:
-    void sanetizeAudioAttributes(audio_attributes_t* attr);
-    status_t sanitizeEffectDescriptor(effect_descriptor_t* desc);
-    status_t sanitizeAudioPortConfig(struct audio_port_config* config);
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
index d8fce38..a47337b 100644
--- a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -106,7 +106,9 @@
 
 status_t AudioDeviceTypeAddr::readFromParcel(const Parcel *parcel) {
     status_t status;
-    if ((status = parcel->readUint32(&mType)) != NO_ERROR) return status;
+    uint32_t rawDeviceType;
+    if ((status = parcel->readUint32(&rawDeviceType)) != NO_ERROR) return status;
+    mType = static_cast<audio_devices_t>(rawDeviceType);
     status = parcel->readUtf8FromUtf16(&mAddress);
     return status;
 }
@@ -153,4 +155,4 @@
     return stream.str();
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 0d28335..759140e 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -152,8 +152,12 @@
     if ((status = parcel->readInt32(&mIndex)) != NO_ERROR) return status;
     if ((status = parcel->readBool(&mUseInChannelMask)) != NO_ERROR) return status;
     if ((status = parcel->readBool(&mUseForVolume)) != NO_ERROR) return status;
-    if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
-    if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+    uint32_t rawGainMode;
+    if ((status = parcel->readUint32(&rawGainMode)) != NO_ERROR) return status;
+    mGain.mode = static_cast<audio_gain_mode_t>(rawGainMode);
+    uint32_t rawChannelMask;
+    if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+    mGain.channel_mask = static_cast<audio_channel_mask_t>(rawChannelMask);
     if ((status = parcel->readInt32(&mGain.min_value)) != NO_ERROR) return status;
     if ((status = parcel->readInt32(&mGain.max_value)) != NO_ERROR) return status;
     if ((status = parcel->readInt32(&mGain.default_value)) != NO_ERROR) return status;
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index f988690..1846a6b 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -268,12 +268,17 @@
     if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
         return status;
     }
-    if ((status = parcel->readUint32(&mChannelMask)) != NO_ERROR) return status;
+    uint32_t rawChannelMask;
+    if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+    mChannelMask = static_cast<audio_channel_mask_t>(rawChannelMask);
     if ((status = parcel->readInt32(&mId)) != NO_ERROR) return status;
     // Read mGain from parcel.
     if ((status = parcel->readInt32(&mGain.index)) != NO_ERROR) return status;
-    if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
-    if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+    uint32_t rawGainMode;
+    if ((status = parcel->readUint32(&rawGainMode)) != NO_ERROR) return status;
+    mGain.mode = static_cast<audio_gain_mode_t>(rawGainMode);
+    if ((status = parcel->readUint32(&rawChannelMask)) != NO_ERROR) return status;
+    mGain.channel_mask = static_cast<audio_channel_mask_t>(rawChannelMask);
     if ((status = parcel->readUint32(&mGain.ramp_duration_ms)) != NO_ERROR) return status;
     std::vector<int> values;
     if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 91be346..67b600e 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -157,7 +157,9 @@
     std::vector<int> values;
     if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
     mChannelMasks.clear();
-    mChannelMasks.insert(values.begin(), values.end());
+    for (auto raw : values) {
+        mChannelMasks.insert(static_cast<audio_channel_mask_t>(raw));
+    }
     values.clear();
     if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
     mSamplingRates.clear();
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 72fda49..aa7ca69 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -96,7 +96,7 @@
 static inline audio_devices_t deviceTypesToBitMask(const DeviceTypeSet& deviceTypes) {
     audio_devices_t types = AUDIO_DEVICE_NONE;
     for (auto deviceType : deviceTypes) {
-        types |= deviceType;
+        types = static_cast<audio_devices_t>(types | deviceType);
     }
     return types;
 }
@@ -131,4 +131,4 @@
 std::string toString(const DeviceTypeSet& deviceTypes);
 
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 2ea215f..d85e2e9 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -79,10 +79,14 @@
             && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
         return false;  // no need to change
     }
-    const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
-    trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
-    const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
-    mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+    const audio_channel_mask_t hapticChannelMask =
+            static_cast<audio_channel_mask_t>(trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+    trackChannelMask = static_cast<audio_channel_mask_t>(
+            trackChannelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
+    const audio_channel_mask_t mixerHapticChannelMask = static_cast<audio_channel_mask_t>(
+            mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+    mixerChannelMask = static_cast<audio_channel_mask_t>(
+            mixerChannelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
     // always recompute for both channel masks even if only one has changed.
     const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
     const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
@@ -362,7 +366,8 @@
             const audio_channel_mask_t trackChannelMask =
                 static_cast<audio_channel_mask_t>(valueInt);
             if (setChannelMasks(name, trackChannelMask,
-                    (track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
+                    static_cast<audio_channel_mask_t>(
+                            track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
                 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
                 invalidate();
             }
@@ -407,7 +412,8 @@
         case MIXER_CHANNEL_MASK: {
             const audio_channel_mask_t mixerChannelMask =
                     static_cast<audio_channel_mask_t>(valueInt);
-            if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask,
+            if (setChannelMasks(name, static_cast<audio_channel_mask_t>(
+                                    track->channelMask | track->mHapticChannelMask),
                     mixerChannelMask)) {
                 ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
                 invalidate();
@@ -533,9 +539,10 @@
     Track* t = static_cast<Track*>(track);
 
     audio_channel_mask_t channelMask = t->channelMask;
-    t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+    t->mHapticChannelMask = static_cast<audio_channel_mask_t>(
+            channelMask & AUDIO_CHANNEL_HAPTIC_ALL);
     t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
-    channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+    channelMask = static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
     t->channelCount = audio_channel_count_from_out_mask(channelMask);
     ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
             "Non-stereo channel mask: %d\n", channelMask);
diff --git a/media/libaudioprocessing/tests/test-mixer.cpp b/media/libaudioprocessing/tests/test-mixer.cpp
index bc9d2a6..1bbb863 100644
--- a/media/libaudioprocessing/tests/test-mixer.cpp
+++ b/media/libaudioprocessing/tests/test-mixer.cpp
@@ -241,7 +241,8 @@
     // set up the tracks.
     for (size_t i = 0; i < providers.size(); ++i) {
         //printf("track %d out of %d\n", i, providers.size());
-        uint32_t channelMask = audio_channel_out_mask_from_count(providers[i].getNumChannels());
+        audio_channel_mask_t channelMask =
+                audio_channel_out_mask_from_count(providers[i].getNumChannels());
         const int name = i;
         const status_t status = mixer->create(
                 name, channelMask, formats[i], AUDIO_SESSION_OUTPUT_MIX);
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index a1520af..5c5f646 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -94,21 +94,21 @@
         AUDIO_CHANNEL_OUT_QUAD_BACK,
         AUDIO_CHANNEL_OUT_QUAD_SIDE,
         AUDIO_CHANNEL_OUT_SURROUND,
-        (1 << 4) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_4,
         AUDIO_CHANNEL_OUT_2POINT1POINT2,
         AUDIO_CHANNEL_OUT_3POINT0POINT2,
         AUDIO_CHANNEL_OUT_PENTA,
-        (1 << 5) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_5,
         AUDIO_CHANNEL_OUT_3POINT1POINT2,
         AUDIO_CHANNEL_OUT_5POINT1,
         AUDIO_CHANNEL_OUT_5POINT1_BACK,
         AUDIO_CHANNEL_OUT_5POINT1_SIDE,
-        (1 << 6) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_6,
         AUDIO_CHANNEL_OUT_6POINT1,
-        (1 << 7) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_7,
         AUDIO_CHANNEL_OUT_5POINT1POINT2,
         AUDIO_CHANNEL_OUT_7POINT1,
-        (1 << 8) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_8,
 };
 
 void printUsage() {
diff --git a/media/libeffects/lvm/tests/reverb_test.cpp b/media/libeffects/lvm/tests/reverb_test.cpp
index 768f655..7cbca9b 100644
--- a/media/libeffects/lvm/tests/reverb_test.cpp
+++ b/media/libeffects/lvm/tests/reverb_test.cpp
@@ -79,21 +79,21 @@
         AUDIO_CHANNEL_OUT_QUAD_BACK,
         AUDIO_CHANNEL_OUT_QUAD_SIDE,
         AUDIO_CHANNEL_OUT_SURROUND,
-        (1 << 4) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_4,
         AUDIO_CHANNEL_OUT_2POINT1POINT2,
         AUDIO_CHANNEL_OUT_3POINT0POINT2,
         AUDIO_CHANNEL_OUT_PENTA,
-        (1 << 5) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_5,
         AUDIO_CHANNEL_OUT_3POINT1POINT2,
         AUDIO_CHANNEL_OUT_5POINT1,
         AUDIO_CHANNEL_OUT_5POINT1_BACK,
         AUDIO_CHANNEL_OUT_5POINT1_SIDE,
-        (1 << 6) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_6,
         AUDIO_CHANNEL_OUT_6POINT1,
-        (1 << 7) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_7,
         AUDIO_CHANNEL_OUT_5POINT1POINT2,
         AUDIO_CHANNEL_OUT_7POINT1,
-        (1 << 8) - 1,
+        AUDIO_CHANNEL_INDEX_MASK_8,
 };
 
 constexpr int kReverbConfigChMaskCount = std::size(kReverbConfigChMask);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 973a164..670b415 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -3394,8 +3394,8 @@
                 return -EINVAL;
             }
 
-            uint32_t device = *(uint32_t*)pCmdData;
-            pContext->pBundledContext->nOutputDevice = (audio_devices_t)device;
+            audio_devices_t device = *(audio_devices_t *)pCmdData;
+            pContext->pBundledContext->nOutputDevice = device;
 
             if (pContext->EffectType == LVM_BASS_BOOST) {
                 if ((device == AUDIO_DEVICE_OUT_SPEAKER) ||
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 138a014..1fe6ffc 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -73,6 +73,7 @@
     METADATA_KEY_COLOR_RANGE     = 37,
     METADATA_KEY_SAMPLERATE      = 38,
     METADATA_KEY_BITS_PER_SAMPLE = 39,
+    METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40,
 
     // Add more here...
 };
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index b46c98a..0779a8e 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -18,7 +18,11 @@
         enabled: true,
     },
     double_loadable: true,
-    srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
+    srcs: [
+        "AudioParameter.cpp",
+        "AudioSanitizer.cpp",
+        "TypeConverter.cpp",
+    ],
     cflags: [
         "-Werror",
         "-Wextra",
diff --git a/media/libmediahelper/AudioSanitizer.cpp b/media/libmediahelper/AudioSanitizer.cpp
new file mode 100644
index 0000000..44ca956
--- /dev/null
+++ b/media/libmediahelper/AudioSanitizer.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#include <media/AudioSanitizer.h>
+
+namespace android {
+
+    /** returns true if string overflow was prevented by zero termination */
+template <size_t size>
+bool preventStringOverflow(char (&s)[size]) {
+    if (strnlen(s, size) < size) return false;
+    s[size - 1] = '\0';
+    return true;
+}
+
+status_t safetyNetLog(status_t status, const char *bugNumber) {
+    if (status != NO_ERROR && bugNumber != nullptr) {
+        android_errorWriteLog(0x534e4554, bugNumber); // SafetyNet logging
+    }
+    return status;
+}
+
+status_t AudioSanitizer::sanitizeAudioAttributes(
+        audio_attributes_t *attr, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
+    if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
+        status = BAD_VALUE;
+    }
+    attr->tags[tagsMaxSize - 1] = '\0';
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeEffectDescriptor(
+        effect_descriptor_t *desc, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (preventStringOverflow(desc->name)
+        | /* always */ preventStringOverflow(desc->implementor)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPortConfig(
+        struct audio_port_config *config, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (config->type == AUDIO_PORT_TYPE_DEVICE &&
+        preventStringOverflow(config->ext.device.address)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPort(
+        struct audio_port *port, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (preventStringOverflow(port->name)) {
+        status = BAD_VALUE;
+    }
+    if (sanitizeAudioPortConfig(&port->active_config) != NO_ERROR) {
+        status = BAD_VALUE;
+    }
+    if (port->type == AUDIO_PORT_TYPE_DEVICE &&
+        preventStringOverflow(port->ext.device.address)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPatch(
+        struct audio_patch *patch, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (patch->num_sources > AUDIO_PATCH_PORTS_MAX) {
+        patch->num_sources = AUDIO_PATCH_PORTS_MAX;
+        status = BAD_VALUE;
+    }
+    if (patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
+        patch->num_sinks = AUDIO_PATCH_PORTS_MAX;
+        status = BAD_VALUE;
+    }
+    for (size_t i = 0; i < patch->num_sources; i++) {
+        if (sanitizeAudioPortConfig(&patch->sources[i]) != NO_ERROR) {
+            status = BAD_VALUE;
+        }
+    }
+    for (size_t i = 0; i < patch->num_sinks; i++) {
+        if (sanitizeAudioPortConfig(&patch->sinks[i]) != NO_ERROR) {
+            status = BAD_VALUE;
+        }
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+}; // namespace android
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
index 705959a..876dc45 100644
--- a/media/libmediahelper/TypeConverter.cpp
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -32,18 +32,21 @@
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
+    // TODO(mnaganov): Remove from here, use 'audio_is_bluetooth_out_sco_device' function.
+    { "AUDIO_DEVICE_OUT_ALL_SCO", static_cast<audio_devices_t>(AUDIO_DEVICE_OUT_ALL_SCO) },
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
+    // TODO(mnaganov): Remove from here, use 'audio_is_a2dp_out_device' function.
+    { "AUDIO_DEVICE_OUT_ALL_A2DP", static_cast<audio_devices_t>(AUDIO_DEVICE_OUT_ALL_A2DP) },
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
+    // TODO(mnaganov): Remove from here, use 'audio_is_usb_out_device' function.
+    { "AUDIO_DEVICE_OUT_ALL_USB", static_cast<audio_devices_t>(AUDIO_DEVICE_OUT_ALL_USB) },
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_LINE),
@@ -72,7 +75,8 @@
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
+    // TODO(mnaganov): Remove from here, use 'audio_is_bluetooth_in_sco_device' function.
+    { "AUDIO_DEVICE_IN_ALL_SCO", static_cast<audio_devices_t>(AUDIO_DEVICE_IN_ALL_SCO) },
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
@@ -85,7 +89,8 @@
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_USB),
+    // TODO(mnaganov): Remove from here, use 'audio_is_usb_in_device' function.
+    { "AUDIO_DEVICE_IN_ALL_USB", static_cast<audio_devices_t>(AUDIO_DEVICE_IN_ALL_USB) },
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
diff --git a/media/libmediahelper/include/media/AudioSanitizer.h b/media/libmediahelper/include/media/AudioSanitizer.h
new file mode 100644
index 0000000..1475c7b
--- /dev/null
+++ b/media/libmediahelper/include/media/AudioSanitizer.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AUDIO_SANITIZER_H_
+#define ANDROID_AUDIO_SANITIZER_H_
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+namespace android {
+
+class AudioSanitizer {
+public:
+    static status_t sanitizeAudioAttributes(
+            audio_attributes_t *attr, const char *bugNumber = nullptr);
+
+    static status_t sanitizeEffectDescriptor(
+            effect_descriptor_t *desc, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPortConfig(
+            struct audio_port_config *config, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPort(
+            struct audio_port *port, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPatch(
+            struct audio_patch *patch, const char *bugNumber = nullptr);
+};
+
+}; // namespace android
+
+#endif  /*ANDROID_AUDIO_SANITIZER_H_*/
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 41b6f72..09b9145 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -538,7 +538,7 @@
 
     // The overall duration is the duration of the longest track.
     int64_t maxDurationUs = 0;
-    String8 timedTextLang;
+    String8 timedTextLang, videoMime;
     for (size_t i = 0; i < numTracks; ++i) {
         sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
         if (!trackMeta) {
@@ -575,6 +575,7 @@
                 }
             } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
                 hasVideo = true;
+                videoMime = String8(mime);
 
                 CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
                 CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
@@ -637,6 +638,8 @@
         sprintf(tmp, "%d", rotationAngle);
         mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp));
 
+        mMetaData.add(METADATA_KEY_VIDEO_CODEC_MIME_TYPE, videoMime);
+
         if (videoFrameCount > 0) {
             sprintf(tmp, "%d", videoFrameCount);
             mMetaData.add(METADATA_KEY_VIDEO_FRAME_COUNT, String8(tmp));
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 02ae456..3e7ee50 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1318,7 +1318,7 @@
     if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
         if (attr.source == AUDIO_SOURCE_VOICE_COMMUNICATION
                 || attr.source == AUDIO_SOURCE_CAMCORDER) {
-            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+            attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
             mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
         } else {
             mPrivacySensitive = PRIVACY_SENSITIVE_DISABLED;
@@ -1334,7 +1334,7 @@
             return NULL;
         }
         if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
-            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+            attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
         }
     }
 
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 1b5cb4b..8d94698 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -60,7 +60,7 @@
 #define DEFAULT_AUDIOSINK_SAMPLERATE 44100
 
 // when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open()
-#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
+#define CHANNEL_MASK_USE_CHANNEL_ORDER AUDIO_CHANNEL_NONE
 
 // duration below which we do not allow deep audio buffering
 #define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index c30f048..13e1933 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1928,11 +1928,12 @@
     int32_t numChannels;
     CHECK(format->findInt32("channel-count", &numChannels));
 
-    int32_t channelMask;
-    if (!format->findInt32("channel-mask", &channelMask)) {
-        // signal to the AudioSink to derive the mask from count.
-        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
-    }
+    int32_t rawChannelMask;
+    audio_channel_mask_t channelMask =
+            format->findInt32("channel-mask", &rawChannelMask) ?
+                    static_cast<audio_channel_mask_t>(rawChannelMask)
+                    // signal to the AudioSink to derive the mask from count.
+                    : CHANNEL_MASK_USE_CHANNEL_ORDER;
 
     int32_t sampleRate;
     CHECK(format->findInt32("sample-rate", &sampleRate));
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index 128d0d8..7329c63 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -21,12 +21,12 @@
         "aidl/android/media/ITranscodingClient.aidl",
         "aidl/android/media/ITranscodingClientCallback.aidl",
         "aidl/android/media/TranscodingErrorCode.aidl",
-        "aidl/android/media/TranscodingJobPriority.aidl",
-        "aidl/android/media/TranscodingJobStats.aidl",
+        "aidl/android/media/TranscodingSessionPriority.aidl",
+        "aidl/android/media/TranscodingSessionStats.aidl",
         "aidl/android/media/TranscodingType.aidl",
         "aidl/android/media/TranscodingVideoCodecType.aidl",
         "aidl/android/media/TranscodingVideoTrackFormat.aidl",
-        "aidl/android/media/TranscodingJobParcel.aidl",
+        "aidl/android/media/TranscodingSessionParcel.aidl",
         "aidl/android/media/TranscodingRequestParcel.aidl",
         "aidl/android/media/TranscodingResultParcel.aidl",
         "aidl/android/media/TranscodingTestConfig.aidl",
@@ -53,7 +53,7 @@
 
     srcs: [
         "TranscodingClientManager.cpp",
-        "TranscodingJobScheduler.cpp",
+        "TranscodingSessionController.cpp",
         "TranscodingResourcePolicy.cpp",
         "TranscodingUidPolicy.cpp",
         "TranscoderWrapper.cpp",
diff --git a/media/libmediatranscoding/TranscoderWrapper.cpp b/media/libmediatranscoding/TranscoderWrapper.cpp
index 8062fcf..61e767c 100644
--- a/media/libmediatranscoding/TranscoderWrapper.cpp
+++ b/media/libmediatranscoding/TranscoderWrapper.cpp
@@ -117,7 +117,7 @@
         return "(unknown)";
     }
     std::string result;
-    result = "job {" + std::to_string(event.clientId) + "," + std::to_string(event.jobId) +
+    result = "session {" + std::to_string(event.clientId) + "," + std::to_string(event.sessionId) +
              "}: " + typeStr;
     if (event.type == Event::Error || event.type == Event::Progress) {
         result += " " + std::to_string(event.arg);
@@ -128,13 +128,13 @@
 class TranscoderWrapper::CallbackImpl : public MediaTranscoder::CallbackInterface {
 public:
     CallbackImpl(const std::shared_ptr<TranscoderWrapper>& owner, ClientIdType clientId,
-                 JobIdType jobId)
-          : mOwner(owner), mClientId(clientId), mJobId(jobId) {}
+                 SessionIdType sessionId)
+          : mOwner(owner), mClientId(clientId), mSessionId(sessionId) {}
 
     virtual void onFinished(const MediaTranscoder* transcoder __unused) override {
         auto owner = mOwner.lock();
         if (owner != nullptr) {
-            owner->onFinish(mClientId, mJobId);
+            owner->onFinish(mClientId, mSessionId);
         }
     }
 
@@ -142,7 +142,7 @@
                          media_status_t error) override {
         auto owner = mOwner.lock();
         if (owner != nullptr) {
-            owner->onError(mClientId, mJobId, error);
+            owner->onError(mClientId, mSessionId, error);
         }
     }
 
@@ -150,23 +150,23 @@
                                   int32_t progress) override {
         auto owner = mOwner.lock();
         if (owner != nullptr) {
-            owner->onProgress(mClientId, mJobId, progress);
+            owner->onProgress(mClientId, mSessionId, progress);
         }
     }
 
     virtual void onCodecResourceLost(const MediaTranscoder* transcoder __unused,
                                      const std::shared_ptr<const Parcel>& pausedState
                                              __unused) override {
-        ALOGV("%s: job {%lld, %d}", __FUNCTION__, (long long)mClientId, mJobId);
+        ALOGV("%s: session {%lld, %d}", __FUNCTION__, (long long)mClientId, mSessionId);
     }
 
 private:
     std::weak_ptr<TranscoderWrapper> mOwner;
     ClientIdType mClientId;
-    JobIdType mJobId;
+    SessionIdType mSessionId;
 };
 
-TranscoderWrapper::TranscoderWrapper() : mCurrentClientId(0), mCurrentJobId(-1) {
+TranscoderWrapper::TranscoderWrapper() : mCurrentClientId(0), mCurrentSessionId(-1) {
     std::thread(&TranscoderWrapper::threadLoop, this).detach();
 }
 
@@ -178,83 +178,85 @@
     return err == AMEDIACODEC_ERROR_RECLAIMED || err == AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
 }
 
-void TranscoderWrapper::reportError(ClientIdType clientId, JobIdType jobId, media_status_t err) {
+void TranscoderWrapper::reportError(ClientIdType clientId, SessionIdType sessionId,
+                                    media_status_t err) {
     auto callback = mCallback.lock();
     if (callback != nullptr) {
         if (isResourceError(err)) {
             // Add a placeholder pause state to mPausedStateMap. This is required when resuming.
             // TODO: remove this when transcoder pause/resume logic is ready. New logic will
             // no longer use the pause states.
-            auto it = mPausedStateMap.find(JobKeyType(clientId, jobId));
+            auto it = mPausedStateMap.find(SessionKeyType(clientId, sessionId));
             if (it == mPausedStateMap.end()) {
-                mPausedStateMap.emplace(JobKeyType(clientId, jobId),
+                mPausedStateMap.emplace(SessionKeyType(clientId, sessionId),
                                         std::shared_ptr<const Parcel>());
             }
 
             callback->onResourceLost();
         } else {
-            callback->onError(clientId, jobId, toTranscodingError(err));
+            callback->onError(clientId, sessionId, toTranscodingError(err));
         }
     }
 }
 
-void TranscoderWrapper::start(ClientIdType clientId, JobIdType jobId,
+void TranscoderWrapper::start(ClientIdType clientId, SessionIdType sessionId,
                               const TranscodingRequestParcel& request,
                               const std::shared_ptr<ITranscodingClientCallback>& clientCb) {
-    queueEvent(Event::Start, clientId, jobId, [=] {
-        media_status_t err = handleStart(clientId, jobId, request, clientCb);
+    queueEvent(Event::Start, clientId, sessionId, [=] {
+        media_status_t err = handleStart(clientId, sessionId, request, clientCb);
 
         if (err != AMEDIA_OK) {
             cleanup();
-            reportError(clientId, jobId, err);
+            reportError(clientId, sessionId, err);
         } else {
             auto callback = mCallback.lock();
             if (callback != nullptr) {
-                callback->onStarted(clientId, jobId);
+                callback->onStarted(clientId, sessionId);
             }
         }
     });
 }
 
-void TranscoderWrapper::pause(ClientIdType clientId, JobIdType jobId) {
-    queueEvent(Event::Pause, clientId, jobId, [=] {
-        media_status_t err = handlePause(clientId, jobId);
+void TranscoderWrapper::pause(ClientIdType clientId, SessionIdType sessionId) {
+    queueEvent(Event::Pause, clientId, sessionId, [=] {
+        media_status_t err = handlePause(clientId, sessionId);
 
         cleanup();
 
         if (err != AMEDIA_OK) {
-            reportError(clientId, jobId, err);
+            reportError(clientId, sessionId, err);
         } else {
             auto callback = mCallback.lock();
             if (callback != nullptr) {
-                callback->onPaused(clientId, jobId);
+                callback->onPaused(clientId, sessionId);
             }
         }
     });
 }
 
-void TranscoderWrapper::resume(ClientIdType clientId, JobIdType jobId,
+void TranscoderWrapper::resume(ClientIdType clientId, SessionIdType sessionId,
                                const TranscodingRequestParcel& request,
                                const std::shared_ptr<ITranscodingClientCallback>& clientCb) {
-    queueEvent(Event::Resume, clientId, jobId, [=] {
-        media_status_t err = handleResume(clientId, jobId, request, clientCb);
+    queueEvent(Event::Resume, clientId, sessionId, [=] {
+        media_status_t err = handleResume(clientId, sessionId, request, clientCb);
 
         if (err != AMEDIA_OK) {
             cleanup();
-            reportError(clientId, jobId, err);
+            reportError(clientId, sessionId, err);
         } else {
             auto callback = mCallback.lock();
             if (callback != nullptr) {
-                callback->onResumed(clientId, jobId);
+                callback->onResumed(clientId, sessionId);
             }
         }
     });
 }
 
-void TranscoderWrapper::stop(ClientIdType clientId, JobIdType jobId) {
-    queueEvent(Event::Stop, clientId, jobId, [=] {
-        if (mTranscoder != nullptr && clientId == mCurrentClientId && jobId == mCurrentJobId) {
-            // Cancelling the currently running job.
+void TranscoderWrapper::stop(ClientIdType clientId, SessionIdType sessionId) {
+    queueEvent(Event::Stop, clientId, sessionId, [=] {
+        if (mTranscoder != nullptr && clientId == mCurrentClientId &&
+            sessionId == mCurrentSessionId) {
+            // Cancelling the currently running session.
             media_status_t err = mTranscoder->cancel();
             if (err != AMEDIA_OK) {
                 ALOGW("failed to stop transcoder: %d", err);
@@ -263,53 +265,56 @@
             }
             cleanup();
         } else {
-            // For jobs that's not currently running, release any pausedState for the job.
-            mPausedStateMap.erase(JobKeyType(clientId, jobId));
+            // For sessions that's not currently running, release any pausedState for the session.
+            mPausedStateMap.erase(SessionKeyType(clientId, sessionId));
         }
         // No callback needed for stop.
     });
 }
 
-void TranscoderWrapper::onFinish(ClientIdType clientId, JobIdType jobId) {
-    queueEvent(Event::Finish, clientId, jobId, [=] {
-        if (mTranscoder != nullptr && clientId == mCurrentClientId && jobId == mCurrentJobId) {
+void TranscoderWrapper::onFinish(ClientIdType clientId, SessionIdType sessionId) {
+    queueEvent(Event::Finish, clientId, sessionId, [=] {
+        if (mTranscoder != nullptr && clientId == mCurrentClientId &&
+            sessionId == mCurrentSessionId) {
             cleanup();
         }
 
         auto callback = mCallback.lock();
         if (callback != nullptr) {
-            callback->onFinish(clientId, jobId);
+            callback->onFinish(clientId, sessionId);
         }
     });
 }
 
-void TranscoderWrapper::onError(ClientIdType clientId, JobIdType jobId, media_status_t error) {
+void TranscoderWrapper::onError(ClientIdType clientId, SessionIdType sessionId,
+                                media_status_t error) {
     queueEvent(
-            Event::Error, clientId, jobId,
+            Event::Error, clientId, sessionId,
             [=] {
                 if (mTranscoder != nullptr && clientId == mCurrentClientId &&
-                    jobId == mCurrentJobId) {
+                    sessionId == mCurrentSessionId) {
                     cleanup();
                 }
-                reportError(clientId, jobId, error);
+                reportError(clientId, sessionId, error);
             },
             error);
 }
 
-void TranscoderWrapper::onProgress(ClientIdType clientId, JobIdType jobId, int32_t progress) {
+void TranscoderWrapper::onProgress(ClientIdType clientId, SessionIdType sessionId,
+                                   int32_t progress) {
     queueEvent(
-            Event::Progress, clientId, jobId,
+            Event::Progress, clientId, sessionId,
             [=] {
                 auto callback = mCallback.lock();
                 if (callback != nullptr) {
-                    callback->onProgressUpdate(clientId, jobId, progress);
+                    callback->onProgressUpdate(clientId, sessionId, progress);
                 }
             },
             progress);
 }
 
 media_status_t TranscoderWrapper::setupTranscoder(
-        ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+        ClientIdType clientId, SessionIdType sessionId, const TranscodingRequestParcel& request,
         const std::shared_ptr<ITranscodingClientCallback>& clientCb,
         const std::shared_ptr<const Parcel>& pausedState) {
     if (clientCb == nullptr) {
@@ -340,8 +345,8 @@
     }
 
     mCurrentClientId = clientId;
-    mCurrentJobId = jobId;
-    mTranscoderCb = std::make_shared<CallbackImpl>(shared_from_this(), clientId, jobId);
+    mCurrentSessionId = sessionId;
+    mTranscoderCb = std::make_shared<CallbackImpl>(shared_from_this(), clientId, sessionId);
     mTranscoder = MediaTranscoder::create(mTranscoderCb, pausedState);
     if (mTranscoder == nullptr) {
         ALOGE("failed to create transcoder");
@@ -389,10 +394,10 @@
 }
 
 media_status_t TranscoderWrapper::handleStart(
-        ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+        ClientIdType clientId, SessionIdType sessionId, const TranscodingRequestParcel& request,
         const std::shared_ptr<ITranscodingClientCallback>& clientCb) {
     ALOGI("%s: setting up transcoder for start", __FUNCTION__);
-    media_status_t err = setupTranscoder(clientId, jobId, request, clientCb);
+    media_status_t err = setupTranscoder(clientId, sessionId, request, clientCb);
     if (err != AMEDIA_OK) {
         ALOGI("%s: failed to setup transcoder", __FUNCTION__);
         return err;
@@ -408,15 +413,15 @@
     return AMEDIA_OK;
 }
 
-media_status_t TranscoderWrapper::handlePause(ClientIdType clientId, JobIdType jobId) {
+media_status_t TranscoderWrapper::handlePause(ClientIdType clientId, SessionIdType sessionId) {
     if (mTranscoder == nullptr) {
         ALOGE("%s: transcoder is not running", __FUNCTION__);
         return AMEDIA_ERROR_INVALID_OPERATION;
     }
 
-    if (clientId != mCurrentClientId || jobId != mCurrentJobId) {
-        ALOGW("%s: stopping job {%lld, %d} that's not current job {%lld, %d}", __FUNCTION__,
-              (long long)clientId, jobId, (long long)mCurrentClientId, mCurrentJobId);
+    if (clientId != mCurrentClientId || sessionId != mCurrentSessionId) {
+        ALOGW("%s: stopping session {%lld, %d} that's not current session {%lld, %d}", __FUNCTION__,
+              (long long)clientId, sessionId, (long long)mCurrentClientId, mCurrentSessionId);
     }
 
     ALOGI("%s: pausing transcoder", __FUNCTION__);
@@ -427,17 +432,17 @@
         ALOGE("%s: failed to pause transcoder: %d", __FUNCTION__, err);
         return err;
     }
-    mPausedStateMap[JobKeyType(clientId, jobId)] = pauseStates;
+    mPausedStateMap[SessionKeyType(clientId, sessionId)] = pauseStates;
 
     ALOGI("%s: transcoder paused", __FUNCTION__);
     return AMEDIA_OK;
 }
 
 media_status_t TranscoderWrapper::handleResume(
-        ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+        ClientIdType clientId, SessionIdType sessionId, const TranscodingRequestParcel& request,
         const std::shared_ptr<ITranscodingClientCallback>& clientCb) {
     std::shared_ptr<const Parcel> pausedState;
-    auto it = mPausedStateMap.find(JobKeyType(clientId, jobId));
+    auto it = mPausedStateMap.find(SessionKeyType(clientId, sessionId));
     if (it != mPausedStateMap.end()) {
         pausedState = it->second;
         mPausedStateMap.erase(it);
@@ -447,7 +452,7 @@
     }
 
     ALOGI("%s: setting up transcoder for resume", __FUNCTION__);
-    media_status_t err = setupTranscoder(clientId, jobId, request, clientCb, pausedState);
+    media_status_t err = setupTranscoder(clientId, sessionId, request, clientCb, pausedState);
     if (err != AMEDIA_OK) {
         ALOGE("%s: failed to setup transcoder: %d", __FUNCTION__, err);
         return err;
@@ -465,16 +470,16 @@
 
 void TranscoderWrapper::cleanup() {
     mCurrentClientId = 0;
-    mCurrentJobId = -1;
+    mCurrentSessionId = -1;
     mTranscoderCb = nullptr;
     mTranscoder = nullptr;
 }
 
-void TranscoderWrapper::queueEvent(Event::Type type, ClientIdType clientId, JobIdType jobId,
+void TranscoderWrapper::queueEvent(Event::Type type, ClientIdType clientId, SessionIdType sessionId,
                                    const std::function<void()> runnable, int32_t arg) {
     std::scoped_lock lock{mLock};
 
-    mQueue.push_back({type, clientId, jobId, runnable, arg});
+    mQueue.push_back({type, clientId, sessionId, runnable, arg});
     mCondition.notify_one();
 }
 
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
index 3f79705..b57baa5 100644
--- a/media/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -23,16 +23,20 @@
 #include <inttypes.h>
 #include <media/TranscodingClientManager.h>
 #include <media/TranscodingRequest.h>
+#include <media/TranscodingUidPolicy.h>
 #include <private/android_filesystem_config.h>
 #include <utils/Log.h>
+#include <utils/String16.h>
 namespace android {
 
 static_assert(sizeof(ClientIdType) == sizeof(void*), "ClientIdType should be pointer-sized");
 
+static constexpr const char* MEDIA_PROVIDER_PKG_NAME = "com.google.android.providers.media.module";
+
 using ::aidl::android::media::BnTranscodingClient;
 using ::aidl::android::media::IMediaTranscodingService;  // For service error codes
-using ::aidl::android::media::TranscodingJobParcel;
 using ::aidl::android::media::TranscodingRequestParcel;
+using ::aidl::android::media::TranscodingSessionParcel;
 using Status = ::ndk::ScopedAStatus;
 using ::ndk::SpAIBinder;
 
@@ -51,20 +55,6 @@
             errorCode,                                \
             String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, ##__VA_ARGS__))
 
-// Can MediaTranscoding service trust the caller based on the calling UID?
-// TODO(hkuang): Add MediaProvider's UID.
-static bool isTrustedCallingUid(uid_t uid) {
-    switch (uid) {
-    case AID_ROOT:  // root user
-    case AID_SYSTEM:
-    case AID_SHELL:
-    case AID_MEDIA:  // mediaserver
-        return true;
-    default:
-        return false;
-    }
-}
-
 /**
  * ClientImpl implements a single client and contains all its information.
  */
@@ -84,8 +74,8 @@
     std::string mClientName;
     std::string mClientOpPackageName;
 
-    // Next jobId to assign.
-    std::atomic<int32_t> mNextJobId;
+    // Next sessionId to assign.
+    std::atomic<int32_t> mNextSessionId;
     // Whether this client has been unregistered already.
     std::atomic<bool> mAbandoned;
     // Weak pointer to the client manager for this client.
@@ -96,12 +86,13 @@
                const std::weak_ptr<TranscodingClientManager>& owner);
 
     Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
-                         TranscodingJobParcel* /*out_job*/, bool* /*_aidl_return*/) override;
+                         TranscodingSessionParcel* /*out_session*/,
+                         bool* /*_aidl_return*/) override;
 
-    Status cancelJob(int32_t /*in_jobId*/, bool* /*_aidl_return*/) override;
+    Status cancelSession(int32_t /*in_sessionId*/, bool* /*_aidl_return*/) override;
 
-    Status getJobWithId(int32_t /*in_jobId*/, TranscodingJobParcel* /*out_job*/,
-                        bool* /*_aidl_return*/) override;
+    Status getSessionWithId(int32_t /*in_sessionId*/, TranscodingSessionParcel* /*out_session*/,
+                            bool* /*_aidl_return*/) override;
 
     Status unregister() override;
 };
@@ -114,12 +105,12 @@
         mClientId(sCookieCounter.fetch_add(1, std::memory_order_relaxed)),
         mClientName(clientName),
         mClientOpPackageName(opPackageName),
-        mNextJobId(0),
+        mNextSessionId(0),
         mAbandoned(false),
         mOwner(owner) {}
 
 Status TranscodingClientManager::ClientImpl::submitRequest(
-        const TranscodingRequestParcel& in_request, TranscodingJobParcel* out_job,
+        const TranscodingRequestParcel& in_request, TranscodingSessionParcel* out_session,
         bool* _aidl_return) {
     *_aidl_return = false;
 
@@ -143,7 +134,7 @@
         in_clientUid = callingUid;
     } else if (in_clientUid < 0) {
         return Status::ok();
-    } else if (in_clientUid != callingUid && !isTrustedCallingUid(callingUid)) {
+    } else if (in_clientUid != callingUid && !owner->isTrustedCallingUid(callingUid)) {
         ALOGE("MediaTranscodingService::registerClient rejected (clientPid %d, clientUid %d) "
               "(don't trust callingUid %d)",
               in_clientPid, in_clientUid, callingUid);
@@ -160,7 +151,7 @@
         in_clientPid = callingPid;
     } else if (in_clientPid < 0) {
         return Status::ok();
-    } else if (in_clientPid != callingPid && !isTrustedCallingUid(callingUid)) {
+    } else if (in_clientPid != callingPid && !owner->isTrustedCallingUid(callingUid)) {
         ALOGE("MediaTranscodingService::registerClient rejected (clientPid %d, clientUid %d) "
               "(don't trust callingUid %d)",
               in_clientPid, in_clientUid, callingUid);
@@ -171,23 +162,24 @@
                 in_clientPid, in_clientUid, callingUid);
     }
 
-    int32_t jobId = mNextJobId.fetch_add(1);
+    int32_t sessionId = mNextSessionId.fetch_add(1);
 
-    *_aidl_return = owner->mJobScheduler->submit(mClientId, jobId, in_clientUid, in_request,
-                                                 mClientCallback);
+    *_aidl_return = owner->mSessionController->submit(mClientId, sessionId, in_clientUid,
+                                                      in_request, mClientCallback);
 
     if (*_aidl_return) {
-        out_job->jobId = jobId;
+        out_session->sessionId = sessionId;
 
-        // TODO(chz): is some of this coming from JobScheduler?
-        *(TranscodingRequest*)&out_job->request = in_request;
-        out_job->awaitNumberOfJobs = 0;
+        // TODO(chz): is some of this coming from SessionController?
+        *(TranscodingRequest*)&out_session->request = in_request;
+        out_session->awaitNumberOfSessions = 0;
     }
 
     return Status::ok();
 }
 
-Status TranscodingClientManager::ClientImpl::cancelJob(int32_t in_jobId, bool* _aidl_return) {
+Status TranscodingClientManager::ClientImpl::cancelSession(int32_t in_sessionId,
+                                                           bool* _aidl_return) {
     *_aidl_return = false;
 
     std::shared_ptr<TranscodingClientManager> owner;
@@ -195,17 +187,17 @@
         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
     }
 
-    if (in_jobId < 0) {
+    if (in_sessionId < 0) {
         return Status::ok();
     }
 
-    *_aidl_return = owner->mJobScheduler->cancel(mClientId, in_jobId);
+    *_aidl_return = owner->mSessionController->cancel(mClientId, in_sessionId);
     return Status::ok();
 }
 
-Status TranscodingClientManager::ClientImpl::getJobWithId(int32_t in_jobId,
-                                                          TranscodingJobParcel* out_job,
-                                                          bool* _aidl_return) {
+Status TranscodingClientManager::ClientImpl::getSessionWithId(int32_t in_sessionId,
+                                                              TranscodingSessionParcel* out_session,
+                                                              bool* _aidl_return) {
     *_aidl_return = false;
 
     std::shared_ptr<TranscodingClientManager> owner;
@@ -213,15 +205,16 @@
         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
     }
 
-    if (in_jobId < 0) {
+    if (in_sessionId < 0) {
         return Status::ok();
     }
 
-    *_aidl_return = owner->mJobScheduler->getJob(mClientId, in_jobId, &out_job->request);
+    *_aidl_return =
+            owner->mSessionController->getSession(mClientId, in_sessionId, &out_session->request);
 
     if (*_aidl_return) {
-        out_job->jobId = in_jobId;
-        out_job->awaitNumberOfJobs = 0;
+        out_session->sessionId = in_sessionId;
+        out_session->awaitNumberOfSessions = 0;
     }
     return Status::ok();
 }
@@ -234,8 +227,8 @@
         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
     }
 
-    // Use jobId == -1 to cancel all realtime jobs for this client with the scheduler.
-    owner->mJobScheduler->cancel(mClientId, -1);
+    // Use sessionId == -1 to cancel all realtime sessions for this client with the controller.
+    owner->mSessionController->cancel(mClientId, -1);
     owner->removeClient(mClientId);
 
     return Status::ok();
@@ -266,9 +259,19 @@
 }
 
 TranscodingClientManager::TranscodingClientManager(
-        const std::shared_ptr<SchedulerClientInterface>& scheduler)
-      : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)), mJobScheduler(scheduler) {
+        const std::shared_ptr<ControllerClientInterface>& controller)
+      : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
+        mSessionController(controller),
+        mMediaProviderUid(-1) {
     ALOGD("TranscodingClientManager started");
+    uid_t mpuid;
+    if (TranscodingUidPolicy::getUidForPackage(String16(MEDIA_PROVIDER_PKG_NAME), mpuid) ==
+        NO_ERROR) {
+        ALOGI("Found MediaProvider uid: %d", mpuid);
+        mMediaProviderUid = mpuid;
+    } else {
+        ALOGW("Couldn't get uid for MediaProvider.");
+    }
 }
 
 TranscodingClientManager::~TranscodingClientManager() {
@@ -299,6 +302,22 @@
     write(fd, result.string(), result.size());
 }
 
+bool TranscodingClientManager::isTrustedCallingUid(uid_t uid) {
+    if (uid > 0 && uid == mMediaProviderUid) {
+        return true;
+    }
+
+    switch (uid) {
+    case AID_ROOT:  // root user
+    case AID_SYSTEM:
+    case AID_SHELL:
+    case AID_MEDIA:  // mediaserver
+        return true;
+    default:
+        return false;
+    }
+}
+
 status_t TranscodingClientManager::addClient(
         const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
         const std::string& opPackageName, std::shared_ptr<ITranscodingClient>* outClient) {
diff --git a/media/libmediatranscoding/TranscodingJobScheduler.cpp b/media/libmediatranscoding/TranscodingJobScheduler.cpp
deleted file mode 100644
index d3a1836..0000000
--- a/media/libmediatranscoding/TranscodingJobScheduler.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "TranscodingJobScheduler"
-
-#define VALIDATE_STATE 1
-
-#include <inttypes.h>
-#include <media/TranscodingJobScheduler.h>
-#include <media/TranscodingUidPolicy.h>
-#include <utils/Log.h>
-
-#include <utility>
-
-namespace android {
-
-static_assert((JobIdType)-1 < 0, "JobIdType should be signed");
-
-constexpr static uid_t OFFLINE_UID = -1;
-
-//static
-String8 TranscodingJobScheduler::jobToString(const JobKeyType& jobKey) {
-    return String8::format("{client:%lld, job:%d}", (long long)jobKey.first, jobKey.second);
-}
-
-//static
-const char* TranscodingJobScheduler::jobStateToString(const Job::State jobState) {
-    switch (jobState) {
-    case Job::State::NOT_STARTED:
-        return "NOT_STARTED";
-    case Job::State::RUNNING:
-        return "RUNNING";
-    case Job::State::PAUSED:
-        return "PAUSED";
-    default:
-        break;
-    }
-    return "(unknown)";
-}
-
-TranscodingJobScheduler::TranscodingJobScheduler(
-        const std::shared_ptr<TranscoderInterface>& transcoder,
-        const std::shared_ptr<UidPolicyInterface>& uidPolicy,
-        const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy)
-      : mTranscoder(transcoder),
-        mUidPolicy(uidPolicy),
-        mResourcePolicy(resourcePolicy),
-        mCurrentJob(nullptr),
-        mResourceLost(false) {
-    // Only push empty offline queue initially. Realtime queues are added when requests come in.
-    mUidSortedList.push_back(OFFLINE_UID);
-    mOfflineUidIterator = mUidSortedList.begin();
-    mJobQueues.emplace(OFFLINE_UID, JobQueueType());
-}
-
-TranscodingJobScheduler::~TranscodingJobScheduler() {}
-
-void TranscodingJobScheduler::dumpAllJobs(int fd, const Vector<String16>& args __unused) {
-    String8 result;
-
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    std::scoped_lock lock{mLock};
-
-    snprintf(buffer, SIZE, "\n========== Dumping all jobs queues =========\n");
-    result.append(buffer);
-    snprintf(buffer, SIZE, "  Total num of Jobs: %zu\n", mJobMap.size());
-    result.append(buffer);
-
-    std::vector<int32_t> uids(mUidSortedList.begin(), mUidSortedList.end());
-    // Exclude last uid, which is for offline queue
-    uids.pop_back();
-    std::vector<std::string> packageNames;
-    if (TranscodingUidPolicy::getNamesForUids(uids, &packageNames)) {
-        uids.push_back(OFFLINE_UID);
-        packageNames.push_back("(offline)");
-    }
-
-    for (int32_t i = 0; i < uids.size(); i++) {
-        const uid_t uid = uids[i];
-
-        if (mJobQueues[uid].empty()) {
-            continue;
-        }
-        snprintf(buffer, SIZE, "    Uid: %d, pkg: %s\n", uid,
-                 packageNames.empty() ? "(unknown)" : packageNames[i].c_str());
-        result.append(buffer);
-        snprintf(buffer, SIZE, "      Num of jobs: %zu\n", mJobQueues[uid].size());
-        result.append(buffer);
-        for (auto& jobKey : mJobQueues[uid]) {
-            auto jobIt = mJobMap.find(jobKey);
-            if (jobIt == mJobMap.end()) {
-                snprintf(buffer, SIZE, "Failed to look up Job %s  \n", jobToString(jobKey).c_str());
-                result.append(buffer);
-                continue;
-            }
-            Job& job = jobIt->second;
-            TranscodingRequestParcel& request = job.request;
-            snprintf(buffer, SIZE, "      Job: %s, %s, %d%%\n", jobToString(jobKey).c_str(),
-                     jobStateToString(job.state), job.lastProgress);
-            result.append(buffer);
-            snprintf(buffer, SIZE, "        Src: %s\n", request.sourceFilePath.c_str());
-            result.append(buffer);
-            snprintf(buffer, SIZE, "        Dst: %s\n", request.destinationFilePath.c_str());
-            result.append(buffer);
-        }
-    }
-
-    write(fd, result.string(), result.size());
-}
-
-TranscodingJobScheduler::Job* TranscodingJobScheduler::getTopJob_l() {
-    if (mJobMap.empty()) {
-        return nullptr;
-    }
-    uid_t topUid = *mUidSortedList.begin();
-    JobKeyType topJobKey = *mJobQueues[topUid].begin();
-    return &mJobMap[topJobKey];
-}
-
-void TranscodingJobScheduler::updateCurrentJob_l() {
-    Job* topJob = getTopJob_l();
-    Job* curJob = mCurrentJob;
-    ALOGV("updateCurrentJob: topJob is %s, curJob is %s",
-          topJob == nullptr ? "null" : jobToString(topJob->key).c_str(),
-          curJob == nullptr ? "null" : jobToString(curJob->key).c_str());
-
-    // If we found a topJob that should be run, and it's not already running,
-    // take some actions to ensure it's running.
-    if (topJob != nullptr && (topJob != curJob || topJob->state != Job::RUNNING)) {
-        // If another job is currently running, pause it first.
-        if (curJob != nullptr && curJob->state == Job::RUNNING) {
-            mTranscoder->pause(curJob->key.first, curJob->key.second);
-            curJob->state = Job::PAUSED;
-        }
-        // If we are not experiencing resource loss, we can start or resume
-        // the topJob now.
-        if (!mResourceLost) {
-            if (topJob->state == Job::NOT_STARTED) {
-                mTranscoder->start(topJob->key.first, topJob->key.second, topJob->request,
-                                   topJob->callback.lock());
-            } else if (topJob->state == Job::PAUSED) {
-                mTranscoder->resume(topJob->key.first, topJob->key.second, topJob->request,
-                                    topJob->callback.lock());
-            }
-            topJob->state = Job::RUNNING;
-        }
-    }
-    mCurrentJob = topJob;
-}
-
-void TranscodingJobScheduler::removeJob_l(const JobKeyType& jobKey) {
-    ALOGV("%s: job %s", __FUNCTION__, jobToString(jobKey).c_str());
-
-    if (mJobMap.count(jobKey) == 0) {
-        ALOGE("job %s doesn't exist", jobToString(jobKey).c_str());
-        return;
-    }
-
-    // Remove job from uid's queue.
-    const uid_t uid = mJobMap[jobKey].uid;
-    JobQueueType& jobQueue = mJobQueues[uid];
-    auto it = std::find(jobQueue.begin(), jobQueue.end(), jobKey);
-    if (it == jobQueue.end()) {
-        ALOGE("couldn't find job %s in queue for uid %d", jobToString(jobKey).c_str(), uid);
-        return;
-    }
-    jobQueue.erase(it);
-
-    // If this is the last job in a real-time queue, remove this uid's queue.
-    if (uid != OFFLINE_UID && jobQueue.empty()) {
-        mUidSortedList.remove(uid);
-        mJobQueues.erase(uid);
-        mUidPolicy->unregisterMonitorUid(uid);
-
-        std::unordered_set<uid_t> topUids = mUidPolicy->getTopUids();
-        moveUidsToTop_l(topUids, false /*preserveTopUid*/);
-    }
-
-    // Clear current job.
-    if (mCurrentJob == &mJobMap[jobKey]) {
-        mCurrentJob = nullptr;
-    }
-
-    // Remove job from job map.
-    mJobMap.erase(jobKey);
-}
-
-/**
- * Moves the set of uids to the front of mUidSortedList (which is used to pick
- * the next job to run).
- *
- * This is called when 1) we received a onTopUidsChanged() callbcak from UidPolicy,
- * or 2) we removed the job queue for a uid because it becomes empty.
- *
- * In case of 1), if there are multiple uids in the set, and the current front
- * uid in mUidSortedList is still in the set, we try to keep that uid at front
- * so that current job run is not interrupted. (This is not a concern for case 2)
- * because the queue for a uid was just removed entirely.)
- */
-void TranscodingJobScheduler::moveUidsToTop_l(const std::unordered_set<uid_t>& uids,
-                                              bool preserveTopUid) {
-    // If uid set is empty, nothing to do. Do not change the queue status.
-    if (uids.empty()) {
-        return;
-    }
-
-    // Save the current top uid.
-    uid_t curTopUid = *mUidSortedList.begin();
-    bool pushCurTopToFront = false;
-    int32_t numUidsMoved = 0;
-
-    // Go through the sorted uid list once, and move the ones in top set to front.
-    for (auto it = mUidSortedList.begin(); it != mUidSortedList.end();) {
-        uid_t uid = *it;
-
-        if (uid != OFFLINE_UID && uids.count(uid) > 0) {
-            it = mUidSortedList.erase(it);
-
-            // If this is the top we're preserving, don't push it here, push
-            // it after the for-loop.
-            if (uid == curTopUid && preserveTopUid) {
-                pushCurTopToFront = true;
-            } else {
-                mUidSortedList.push_front(uid);
-            }
-
-            // If we found all uids in the set, break out.
-            if (++numUidsMoved == uids.size()) {
-                break;
-            }
-        } else {
-            ++it;
-        }
-    }
-
-    if (pushCurTopToFront) {
-        mUidSortedList.push_front(curTopUid);
-    }
-}
-
-bool TranscodingJobScheduler::submit(ClientIdType clientId, JobIdType jobId, uid_t uid,
-                                     const TranscodingRequestParcel& request,
-                                     const std::weak_ptr<ITranscodingClientCallback>& callback) {
-    JobKeyType jobKey = std::make_pair(clientId, jobId);
-
-    ALOGV("%s: job %s, uid %d, prioirty %d", __FUNCTION__, jobToString(jobKey).c_str(), uid,
-          (int32_t)request.priority);
-
-    std::scoped_lock lock{mLock};
-
-    if (mJobMap.count(jobKey) > 0) {
-        ALOGE("job %s already exists", jobToString(jobKey).c_str());
-        return false;
-    }
-
-    // TODO(chz): only support offline vs real-time for now. All kUnspecified jobs
-    // go to offline queue.
-    if (request.priority == TranscodingJobPriority::kUnspecified) {
-        uid = OFFLINE_UID;
-    }
-
-    // Add job to job map.
-    mJobMap[jobKey].key = jobKey;
-    mJobMap[jobKey].uid = uid;
-    mJobMap[jobKey].state = Job::NOT_STARTED;
-    mJobMap[jobKey].lastProgress = 0;
-    mJobMap[jobKey].request = request;
-    mJobMap[jobKey].callback = callback;
-
-    // If it's an offline job, the queue was already added in constructor.
-    // If it's a real-time jobs, check if a queue is already present for the uid,
-    // and add a new queue if needed.
-    if (uid != OFFLINE_UID) {
-        if (mJobQueues.count(uid) == 0) {
-            mUidPolicy->registerMonitorUid(uid);
-            if (mUidPolicy->isUidOnTop(uid)) {
-                mUidSortedList.push_front(uid);
-            } else {
-                // Shouldn't be submitting real-time requests from non-top app,
-                // put it in front of the offline queue.
-                mUidSortedList.insert(mOfflineUidIterator, uid);
-            }
-        } else if (uid != *mUidSortedList.begin()) {
-            if (mUidPolicy->isUidOnTop(uid)) {
-                mUidSortedList.remove(uid);
-                mUidSortedList.push_front(uid);
-            }
-        }
-    }
-    // Append this job to the uid's queue.
-    mJobQueues[uid].push_back(jobKey);
-
-    updateCurrentJob_l();
-
-    validateState_l();
-    return true;
-}
-
-bool TranscodingJobScheduler::cancel(ClientIdType clientId, JobIdType jobId) {
-    JobKeyType jobKey = std::make_pair(clientId, jobId);
-
-    ALOGV("%s: job %s", __FUNCTION__, jobToString(jobKey).c_str());
-
-    std::list<JobKeyType> jobsToRemove;
-
-    std::scoped_lock lock{mLock};
-
-    if (jobId < 0) {
-        for (auto it = mJobMap.begin(); it != mJobMap.end(); ++it) {
-            if (it->first.first == clientId && it->second.uid != OFFLINE_UID) {
-                jobsToRemove.push_back(it->first);
-            }
-        }
-    } else {
-        if (mJobMap.count(jobKey) == 0) {
-            ALOGE("job %s doesn't exist", jobToString(jobKey).c_str());
-            return false;
-        }
-        jobsToRemove.push_back(jobKey);
-    }
-
-    for (auto it = jobsToRemove.begin(); it != jobsToRemove.end(); ++it) {
-        // If the job has ever been started, stop it now.
-        // Note that stop() is needed even if the job is currently paused. This instructs
-        // the transcoder to discard any states for the job, otherwise the states may
-        // never be discarded.
-        if (mJobMap[*it].state != Job::NOT_STARTED) {
-            mTranscoder->stop(it->first, it->second);
-        }
-
-        // Remove the job.
-        removeJob_l(*it);
-    }
-
-    // Start next job.
-    updateCurrentJob_l();
-
-    validateState_l();
-    return true;
-}
-
-bool TranscodingJobScheduler::getJob(ClientIdType clientId, JobIdType jobId,
-                                     TranscodingRequestParcel* request) {
-    JobKeyType jobKey = std::make_pair(clientId, jobId);
-
-    std::scoped_lock lock{mLock};
-
-    if (mJobMap.count(jobKey) == 0) {
-        ALOGE("job %s doesn't exist", jobToString(jobKey).c_str());
-        return false;
-    }
-
-    *(TranscodingRequest*)request = mJobMap[jobKey].request;
-    return true;
-}
-
-void TranscodingJobScheduler::notifyClient(ClientIdType clientId, JobIdType jobId,
-                                           const char* reason,
-                                           std::function<void(const JobKeyType&)> func) {
-    JobKeyType jobKey = std::make_pair(clientId, jobId);
-
-    std::scoped_lock lock{mLock};
-
-    if (mJobMap.count(jobKey) == 0) {
-        ALOGW("%s: ignoring %s for job %s that doesn't exist", __FUNCTION__, reason,
-              jobToString(jobKey).c_str());
-        return;
-    }
-
-    // Only ignore if job was never started. In particular, propagate the status
-    // to client if the job is paused. Transcoder could have posted finish when
-    // we're pausing it, and the finish arrived after we changed current job.
-    if (mJobMap[jobKey].state == Job::NOT_STARTED) {
-        ALOGW("%s: ignoring %s for job %s that was never started", __FUNCTION__, reason,
-              jobToString(jobKey).c_str());
-        return;
-    }
-
-    ALOGV("%s: job %s %s", __FUNCTION__, jobToString(jobKey).c_str(), reason);
-    func(jobKey);
-}
-
-void TranscodingJobScheduler::onStarted(ClientIdType clientId, JobIdType jobId) {
-    notifyClient(clientId, jobId, "started", [=](const JobKeyType& jobKey) {
-        auto callback = mJobMap[jobKey].callback.lock();
-        if (callback != nullptr) {
-            callback->onTranscodingStarted(jobId);
-        }
-    });
-}
-
-void TranscodingJobScheduler::onPaused(ClientIdType clientId, JobIdType jobId) {
-    notifyClient(clientId, jobId, "paused", [=](const JobKeyType& jobKey) {
-        auto callback = mJobMap[jobKey].callback.lock();
-        if (callback != nullptr) {
-            callback->onTranscodingPaused(jobId);
-        }
-    });
-}
-
-void TranscodingJobScheduler::onResumed(ClientIdType clientId, JobIdType jobId) {
-    notifyClient(clientId, jobId, "resumed", [=](const JobKeyType& jobKey) {
-        auto callback = mJobMap[jobKey].callback.lock();
-        if (callback != nullptr) {
-            callback->onTranscodingResumed(jobId);
-        }
-    });
-}
-
-void TranscodingJobScheduler::onFinish(ClientIdType clientId, JobIdType jobId) {
-    notifyClient(clientId, jobId, "finish", [=](const JobKeyType& jobKey) {
-        {
-            auto clientCallback = mJobMap[jobKey].callback.lock();
-            if (clientCallback != nullptr) {
-                clientCallback->onTranscodingFinished(
-                        jobId, TranscodingResultParcel({jobId, -1 /*actualBitrateBps*/,
-                                                        std::nullopt /*jobStats*/}));
-            }
-        }
-
-        // Remove the job.
-        removeJob_l(jobKey);
-
-        // Start next job.
-        updateCurrentJob_l();
-
-        validateState_l();
-    });
-}
-
-void TranscodingJobScheduler::onError(ClientIdType clientId, JobIdType jobId,
-                                      TranscodingErrorCode err) {
-    notifyClient(clientId, jobId, "error", [=](const JobKeyType& jobKey) {
-        {
-            auto clientCallback = mJobMap[jobKey].callback.lock();
-            if (clientCallback != nullptr) {
-                clientCallback->onTranscodingFailed(jobId, err);
-            }
-        }
-
-        // Remove the job.
-        removeJob_l(jobKey);
-
-        // Start next job.
-        updateCurrentJob_l();
-
-        validateState_l();
-    });
-}
-
-void TranscodingJobScheduler::onProgressUpdate(ClientIdType clientId, JobIdType jobId,
-                                               int32_t progress) {
-    notifyClient(clientId, jobId, "progress", [=](const JobKeyType& jobKey) {
-        auto callback = mJobMap[jobKey].callback.lock();
-        if (callback != nullptr) {
-            callback->onProgressUpdate(jobId, progress);
-        }
-        mJobMap[jobKey].lastProgress = progress;
-    });
-}
-
-void TranscodingJobScheduler::onResourceLost() {
-    ALOGI("%s", __FUNCTION__);
-
-    std::scoped_lock lock{mLock};
-
-    if (mResourceLost) {
-        return;
-    }
-
-    // If we receive a resource loss event, the TranscoderLibrary already paused
-    // the transcoding, so we don't need to call onPaused to notify it to pause.
-    // Only need to update the job state here.
-    if (mCurrentJob != nullptr && mCurrentJob->state == Job::RUNNING) {
-        mCurrentJob->state = Job::PAUSED;
-        // Notify the client as a paused event.
-        auto clientCallback = mCurrentJob->callback.lock();
-        if (clientCallback != nullptr) {
-            clientCallback->onTranscodingPaused(mCurrentJob->key.second);
-        }
-    }
-    mResourceLost = true;
-
-    validateState_l();
-}
-
-void TranscodingJobScheduler::onTopUidsChanged(const std::unordered_set<uid_t>& uids) {
-    if (uids.empty()) {
-        ALOGW("%s: ignoring empty uids", __FUNCTION__);
-        return;
-    }
-
-    std::string uidStr;
-    for (auto it = uids.begin(); it != uids.end(); it++) {
-        if (!uidStr.empty()) {
-            uidStr += ", ";
-        }
-        uidStr += std::to_string(*it);
-    }
-
-    ALOGD("%s: topUids: size %zu, uids: %s", __FUNCTION__, uids.size(), uidStr.c_str());
-
-    std::scoped_lock lock{mLock};
-
-    moveUidsToTop_l(uids, true /*preserveTopUid*/);
-
-    updateCurrentJob_l();
-
-    validateState_l();
-}
-
-void TranscodingJobScheduler::onResourceAvailable() {
-    std::scoped_lock lock{mLock};
-
-    if (!mResourceLost) {
-        return;
-    }
-
-    ALOGI("%s", __FUNCTION__);
-
-    mResourceLost = false;
-    updateCurrentJob_l();
-
-    validateState_l();
-}
-
-void TranscodingJobScheduler::validateState_l() {
-#ifdef VALIDATE_STATE
-    LOG_ALWAYS_FATAL_IF(mJobQueues.count(OFFLINE_UID) != 1,
-                        "mJobQueues offline queue number is not 1");
-    LOG_ALWAYS_FATAL_IF(*mOfflineUidIterator != OFFLINE_UID,
-                        "mOfflineUidIterator not pointing to offline uid");
-    LOG_ALWAYS_FATAL_IF(mUidSortedList.size() != mJobQueues.size(),
-                        "mUidList and mJobQueues size mismatch");
-
-    int32_t totalJobs = 0;
-    for (auto uid : mUidSortedList) {
-        LOG_ALWAYS_FATAL_IF(mJobQueues.count(uid) != 1, "mJobQueues count for uid %d is not 1",
-                            uid);
-        for (auto& jobKey : mJobQueues[uid]) {
-            LOG_ALWAYS_FATAL_IF(mJobMap.count(jobKey) != 1, "mJobs count for job %s is not 1",
-                                jobToString(jobKey).c_str());
-        }
-
-        totalJobs += mJobQueues[uid].size();
-    }
-    LOG_ALWAYS_FATAL_IF(mJobMap.size() != totalJobs,
-                        "mJobs size doesn't match total jobs counted from uid queues");
-#endif  // VALIDATE_STATE
-}
-
-}  // namespace android
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/libmediatranscoding/TranscodingSessionController.cpp
new file mode 100644
index 0000000..2306395
--- /dev/null
+++ b/media/libmediatranscoding/TranscodingSessionController.cpp
@@ -0,0 +1,574 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TranscodingSessionController"
+
+#define VALIDATE_STATE 1
+
+#include <inttypes.h>
+#include <media/TranscodingSessionController.h>
+#include <media/TranscodingUidPolicy.h>
+#include <utils/Log.h>
+
+#include <utility>
+
+namespace android {
+
+static_assert((SessionIdType)-1 < 0, "SessionIdType should be signed");
+
+constexpr static uid_t OFFLINE_UID = -1;
+
+//static
+String8 TranscodingSessionController::sessionToString(const SessionKeyType& sessionKey) {
+    return String8::format("{client:%lld, session:%d}", (long long)sessionKey.first,
+                           sessionKey.second);
+}
+
+//static
+const char* TranscodingSessionController::sessionStateToString(const Session::State sessionState) {
+    switch (sessionState) {
+    case Session::State::NOT_STARTED:
+        return "NOT_STARTED";
+    case Session::State::RUNNING:
+        return "RUNNING";
+    case Session::State::PAUSED:
+        return "PAUSED";
+    default:
+        break;
+    }
+    return "(unknown)";
+}
+
+TranscodingSessionController::TranscodingSessionController(
+        const std::shared_ptr<TranscoderInterface>& transcoder,
+        const std::shared_ptr<UidPolicyInterface>& uidPolicy,
+        const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy)
+      : mTranscoder(transcoder),
+        mUidPolicy(uidPolicy),
+        mResourcePolicy(resourcePolicy),
+        mCurrentSession(nullptr),
+        mResourceLost(false) {
+    // Only push empty offline queue initially. Realtime queues are added when requests come in.
+    mUidSortedList.push_back(OFFLINE_UID);
+    mOfflineUidIterator = mUidSortedList.begin();
+    mSessionQueues.emplace(OFFLINE_UID, SessionQueueType());
+}
+
+TranscodingSessionController::~TranscodingSessionController() {}
+
+void TranscodingSessionController::dumpAllSessions(int fd, const Vector<String16>& args __unused) {
+    String8 result;
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    std::scoped_lock lock{mLock};
+
+    snprintf(buffer, SIZE, "\n========== Dumping all sessions queues =========\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "  Total num of Sessions: %zu\n", mSessionMap.size());
+    result.append(buffer);
+
+    std::vector<int32_t> uids(mUidSortedList.begin(), mUidSortedList.end());
+    // Exclude last uid, which is for offline queue
+    uids.pop_back();
+    std::vector<std::string> packageNames;
+    if (TranscodingUidPolicy::getNamesForUids(uids, &packageNames)) {
+        uids.push_back(OFFLINE_UID);
+        packageNames.push_back("(offline)");
+    }
+
+    for (int32_t i = 0; i < uids.size(); i++) {
+        const uid_t uid = uids[i];
+
+        if (mSessionQueues[uid].empty()) {
+            continue;
+        }
+        snprintf(buffer, SIZE, "    Uid: %d, pkg: %s\n", uid,
+                 packageNames.empty() ? "(unknown)" : packageNames[i].c_str());
+        result.append(buffer);
+        snprintf(buffer, SIZE, "      Num of sessions: %zu\n", mSessionQueues[uid].size());
+        result.append(buffer);
+        for (auto& sessionKey : mSessionQueues[uid]) {
+            auto sessionIt = mSessionMap.find(sessionKey);
+            if (sessionIt == mSessionMap.end()) {
+                snprintf(buffer, SIZE, "Failed to look up Session %s  \n",
+                         sessionToString(sessionKey).c_str());
+                result.append(buffer);
+                continue;
+            }
+            Session& session = sessionIt->second;
+            TranscodingRequestParcel& request = session.request;
+            snprintf(buffer, SIZE, "      Session: %s, %s, %d%%\n",
+                     sessionToString(sessionKey).c_str(), sessionStateToString(session.state),
+                     session.lastProgress);
+            result.append(buffer);
+            snprintf(buffer, SIZE, "        Src: %s\n", request.sourceFilePath.c_str());
+            result.append(buffer);
+            snprintf(buffer, SIZE, "        Dst: %s\n", request.destinationFilePath.c_str());
+            result.append(buffer);
+        }
+    }
+
+    write(fd, result.string(), result.size());
+}
+
+TranscodingSessionController::Session* TranscodingSessionController::getTopSession_l() {
+    if (mSessionMap.empty()) {
+        return nullptr;
+    }
+    uid_t topUid = *mUidSortedList.begin();
+    SessionKeyType topSessionKey = *mSessionQueues[topUid].begin();
+    return &mSessionMap[topSessionKey];
+}
+
+void TranscodingSessionController::updateCurrentSession_l() {
+    Session* topSession = getTopSession_l();
+    Session* curSession = mCurrentSession;
+    ALOGV("updateCurrentSession: topSession is %s, curSession is %s",
+          topSession == nullptr ? "null" : sessionToString(topSession->key).c_str(),
+          curSession == nullptr ? "null" : sessionToString(curSession->key).c_str());
+
+    // If we found a topSession that should be run, and it's not already running,
+    // take some actions to ensure it's running.
+    if (topSession != nullptr &&
+        (topSession != curSession || topSession->state != Session::RUNNING)) {
+        // If another session is currently running, pause it first.
+        if (curSession != nullptr && curSession->state == Session::RUNNING) {
+            mTranscoder->pause(curSession->key.first, curSession->key.second);
+            curSession->state = Session::PAUSED;
+        }
+        // If we are not experiencing resource loss, we can start or resume
+        // the topSession now.
+        if (!mResourceLost) {
+            if (topSession->state == Session::NOT_STARTED) {
+                mTranscoder->start(topSession->key.first, topSession->key.second,
+                                   topSession->request, topSession->callback.lock());
+            } else if (topSession->state == Session::PAUSED) {
+                mTranscoder->resume(topSession->key.first, topSession->key.second,
+                                    topSession->request, topSession->callback.lock());
+            }
+            topSession->state = Session::RUNNING;
+        }
+    }
+    mCurrentSession = topSession;
+}
+
+void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey) {
+    ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());
+
+    if (mSessionMap.count(sessionKey) == 0) {
+        ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
+        return;
+    }
+
+    // Remove session from uid's queue.
+    const uid_t uid = mSessionMap[sessionKey].uid;
+    SessionQueueType& sessionQueue = mSessionQueues[uid];
+    auto it = std::find(sessionQueue.begin(), sessionQueue.end(), sessionKey);
+    if (it == sessionQueue.end()) {
+        ALOGE("couldn't find session %s in queue for uid %d", sessionToString(sessionKey).c_str(),
+              uid);
+        return;
+    }
+    sessionQueue.erase(it);
+
+    // If this is the last session in a real-time queue, remove this uid's queue.
+    if (uid != OFFLINE_UID && sessionQueue.empty()) {
+        mUidSortedList.remove(uid);
+        mSessionQueues.erase(uid);
+        mUidPolicy->unregisterMonitorUid(uid);
+
+        std::unordered_set<uid_t> topUids = mUidPolicy->getTopUids();
+        moveUidsToTop_l(topUids, false /*preserveTopUid*/);
+    }
+
+    // Clear current session.
+    if (mCurrentSession == &mSessionMap[sessionKey]) {
+        mCurrentSession = nullptr;
+    }
+
+    // Remove session from session map.
+    mSessionMap.erase(sessionKey);
+}
+
+/**
+ * Moves the set of uids to the front of mUidSortedList (which is used to pick
+ * the next session to run).
+ *
+ * This is called when 1) we received a onTopUidsChanged() callback from UidPolicy,
+ * or 2) we removed the session queue for a uid because it becomes empty.
+ *
+ * In case of 1), if there are multiple uids in the set, and the current front
+ * uid in mUidSortedList is still in the set, we try to keep that uid at front
+ * so that current session run is not interrupted. (This is not a concern for case 2)
+ * because the queue for a uid was just removed entirely.)
+ */
+void TranscodingSessionController::moveUidsToTop_l(const std::unordered_set<uid_t>& uids,
+                                                   bool preserveTopUid) {
+    // If uid set is empty, nothing to do. Do not change the queue status.
+    if (uids.empty()) {
+        return;
+    }
+
+    // Save the current top uid.
+    uid_t curTopUid = *mUidSortedList.begin();
+    bool pushCurTopToFront = false;
+    int32_t numUidsMoved = 0;
+
+    // Go through the sorted uid list once, and move the ones in top set to front.
+    for (auto it = mUidSortedList.begin(); it != mUidSortedList.end();) {
+        uid_t uid = *it;
+
+        if (uid != OFFLINE_UID && uids.count(uid) > 0) {
+            it = mUidSortedList.erase(it);
+
+            // If this is the top we're preserving, don't push it here, push
+            // it after the for-loop.
+            if (uid == curTopUid && preserveTopUid) {
+                pushCurTopToFront = true;
+            } else {
+                mUidSortedList.push_front(uid);
+            }
+
+            // If we found all uids in the set, break out.
+            if (++numUidsMoved == uids.size()) {
+                break;
+            }
+        } else {
+            ++it;
+        }
+    }
+
+    if (pushCurTopToFront) {
+        mUidSortedList.push_front(curTopUid);
+    }
+}
+
+bool TranscodingSessionController::submit(
+        ClientIdType clientId, SessionIdType sessionId, uid_t uid,
+        const TranscodingRequestParcel& request,
+        const std::weak_ptr<ITranscodingClientCallback>& callback) {
+    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+
+    ALOGV("%s: session %s, uid %d, prioirty %d", __FUNCTION__, sessionToString(sessionKey).c_str(),
+          uid, (int32_t)request.priority);
+
+    std::scoped_lock lock{mLock};
+
+    if (mSessionMap.count(sessionKey) > 0) {
+        ALOGE("session %s already exists", sessionToString(sessionKey).c_str());
+        return false;
+    }
+
+    // TODO(chz): only support offline vs real-time for now. All kUnspecified sessions
+    // go to offline queue.
+    if (request.priority == TranscodingSessionPriority::kUnspecified) {
+        uid = OFFLINE_UID;
+    }
+
+    // Add session to session map.
+    mSessionMap[sessionKey].key = sessionKey;
+    mSessionMap[sessionKey].uid = uid;
+    mSessionMap[sessionKey].state = Session::NOT_STARTED;
+    mSessionMap[sessionKey].lastProgress = 0;
+    mSessionMap[sessionKey].request = request;
+    mSessionMap[sessionKey].callback = callback;
+
+    // If it's an offline session, the queue was already added in constructor.
+    // If it's a real-time sessions, check if a queue is already present for the uid,
+    // and add a new queue if needed.
+    if (uid != OFFLINE_UID) {
+        if (mSessionQueues.count(uid) == 0) {
+            mUidPolicy->registerMonitorUid(uid);
+            if (mUidPolicy->isUidOnTop(uid)) {
+                mUidSortedList.push_front(uid);
+            } else {
+                // Shouldn't be submitting real-time requests from non-top app,
+                // put it in front of the offline queue.
+                mUidSortedList.insert(mOfflineUidIterator, uid);
+            }
+        } else if (uid != *mUidSortedList.begin()) {
+            if (mUidPolicy->isUidOnTop(uid)) {
+                mUidSortedList.remove(uid);
+                mUidSortedList.push_front(uid);
+            }
+        }
+    }
+    // Append this session to the uid's queue.
+    mSessionQueues[uid].push_back(sessionKey);
+
+    updateCurrentSession_l();
+
+    validateState_l();
+    return true;
+}
+
+bool TranscodingSessionController::cancel(ClientIdType clientId, SessionIdType sessionId) {
+    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+
+    ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());
+
+    std::list<SessionKeyType> sessionsToRemove;
+
+    std::scoped_lock lock{mLock};
+
+    if (sessionId < 0) {
+        for (auto it = mSessionMap.begin(); it != mSessionMap.end(); ++it) {
+            if (it->first.first == clientId && it->second.uid != OFFLINE_UID) {
+                sessionsToRemove.push_back(it->first);
+            }
+        }
+    } else {
+        if (mSessionMap.count(sessionKey) == 0) {
+            ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
+            return false;
+        }
+        sessionsToRemove.push_back(sessionKey);
+    }
+
+    for (auto it = sessionsToRemove.begin(); it != sessionsToRemove.end(); ++it) {
+        // If the session has ever been started, stop it now.
+        // Note that stop() is needed even if the session is currently paused. This instructs
+        // the transcoder to discard any states for the session, otherwise the states may
+        // never be discarded.
+        if (mSessionMap[*it].state != Session::NOT_STARTED) {
+            mTranscoder->stop(it->first, it->second);
+        }
+
+        // Remove the session.
+        removeSession_l(*it);
+    }
+
+    // Start next session.
+    updateCurrentSession_l();
+
+    validateState_l();
+    return true;
+}
+
+bool TranscodingSessionController::getSession(ClientIdType clientId, SessionIdType sessionId,
+                                              TranscodingRequestParcel* request) {
+    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+
+    std::scoped_lock lock{mLock};
+
+    if (mSessionMap.count(sessionKey) == 0) {
+        ALOGE("session %s doesn't exist", sessionToString(sessionKey).c_str());
+        return false;
+    }
+
+    *(TranscodingRequest*)request = mSessionMap[sessionKey].request;
+    return true;
+}
+
+void TranscodingSessionController::notifyClient(ClientIdType clientId, SessionIdType sessionId,
+                                                const char* reason,
+                                                std::function<void(const SessionKeyType&)> func) {
+    SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+
+    std::scoped_lock lock{mLock};
+
+    if (mSessionMap.count(sessionKey) == 0) {
+        ALOGW("%s: ignoring %s for session %s that doesn't exist", __FUNCTION__, reason,
+              sessionToString(sessionKey).c_str());
+        return;
+    }
+
+    // Only ignore if session was never started. In particular, propagate the status
+    // to client if the session is paused. Transcoder could have posted finish when
+    // we're pausing it, and the finish arrived after we changed current session.
+    if (mSessionMap[sessionKey].state == Session::NOT_STARTED) {
+        ALOGW("%s: ignoring %s for session %s that was never started", __FUNCTION__, reason,
+              sessionToString(sessionKey).c_str());
+        return;
+    }
+
+    ALOGV("%s: session %s %s", __FUNCTION__, sessionToString(sessionKey).c_str(), reason);
+    func(sessionKey);
+}
+
+void TranscodingSessionController::onStarted(ClientIdType clientId, SessionIdType sessionId) {
+    notifyClient(clientId, sessionId, "started", [=](const SessionKeyType& sessionKey) {
+        auto callback = mSessionMap[sessionKey].callback.lock();
+        if (callback != nullptr) {
+            callback->onTranscodingStarted(sessionId);
+        }
+    });
+}
+
+void TranscodingSessionController::onPaused(ClientIdType clientId, SessionIdType sessionId) {
+    notifyClient(clientId, sessionId, "paused", [=](const SessionKeyType& sessionKey) {
+        auto callback = mSessionMap[sessionKey].callback.lock();
+        if (callback != nullptr) {
+            callback->onTranscodingPaused(sessionId);
+        }
+    });
+}
+
+void TranscodingSessionController::onResumed(ClientIdType clientId, SessionIdType sessionId) {
+    notifyClient(clientId, sessionId, "resumed", [=](const SessionKeyType& sessionKey) {
+        auto callback = mSessionMap[sessionKey].callback.lock();
+        if (callback != nullptr) {
+            callback->onTranscodingResumed(sessionId);
+        }
+    });
+}
+
+void TranscodingSessionController::onFinish(ClientIdType clientId, SessionIdType sessionId) {
+    notifyClient(clientId, sessionId, "finish", [=](const SessionKeyType& sessionKey) {
+        {
+            auto clientCallback = mSessionMap[sessionKey].callback.lock();
+            if (clientCallback != nullptr) {
+                clientCallback->onTranscodingFinished(
+                        sessionId, TranscodingResultParcel({sessionId, -1 /*actualBitrateBps*/,
+                                                            std::nullopt /*sessionStats*/}));
+            }
+        }
+
+        // Remove the session.
+        removeSession_l(sessionKey);
+
+        // Start next session.
+        updateCurrentSession_l();
+
+        validateState_l();
+    });
+}
+
+void TranscodingSessionController::onError(ClientIdType clientId, SessionIdType sessionId,
+                                           TranscodingErrorCode err) {
+    notifyClient(clientId, sessionId, "error", [=](const SessionKeyType& sessionKey) {
+        {
+            auto clientCallback = mSessionMap[sessionKey].callback.lock();
+            if (clientCallback != nullptr) {
+                clientCallback->onTranscodingFailed(sessionId, err);
+            }
+        }
+
+        // Remove the session.
+        removeSession_l(sessionKey);
+
+        // Start next session.
+        updateCurrentSession_l();
+
+        validateState_l();
+    });
+}
+
+void TranscodingSessionController::onProgressUpdate(ClientIdType clientId, SessionIdType sessionId,
+                                                    int32_t progress) {
+    notifyClient(clientId, sessionId, "progress", [=](const SessionKeyType& sessionKey) {
+        auto callback = mSessionMap[sessionKey].callback.lock();
+        if (callback != nullptr) {
+            callback->onProgressUpdate(sessionId, progress);
+        }
+        mSessionMap[sessionKey].lastProgress = progress;
+    });
+}
+
+void TranscodingSessionController::onResourceLost() {
+    ALOGI("%s", __FUNCTION__);
+
+    std::scoped_lock lock{mLock};
+
+    if (mResourceLost) {
+        return;
+    }
+
+    // If we receive a resource loss event, the TranscoderLibrary already paused
+    // the transcoding, so we don't need to call onPaused to notify it to pause.
+    // Only need to update the session state here.
+    if (mCurrentSession != nullptr && mCurrentSession->state == Session::RUNNING) {
+        mCurrentSession->state = Session::PAUSED;
+        // Notify the client as a paused event.
+        auto clientCallback = mCurrentSession->callback.lock();
+        if (clientCallback != nullptr) {
+            clientCallback->onTranscodingPaused(mCurrentSession->key.second);
+        }
+    }
+    mResourceLost = true;
+
+    validateState_l();
+}
+
+void TranscodingSessionController::onTopUidsChanged(const std::unordered_set<uid_t>& uids) {
+    if (uids.empty()) {
+        ALOGW("%s: ignoring empty uids", __FUNCTION__);
+        return;
+    }
+
+    std::string uidStr;
+    for (auto it = uids.begin(); it != uids.end(); it++) {
+        if (!uidStr.empty()) {
+            uidStr += ", ";
+        }
+        uidStr += std::to_string(*it);
+    }
+
+    ALOGD("%s: topUids: size %zu, uids: %s", __FUNCTION__, uids.size(), uidStr.c_str());
+
+    std::scoped_lock lock{mLock};
+
+    moveUidsToTop_l(uids, true /*preserveTopUid*/);
+
+    updateCurrentSession_l();
+
+    validateState_l();
+}
+
+void TranscodingSessionController::onResourceAvailable() {
+    std::scoped_lock lock{mLock};
+
+    if (!mResourceLost) {
+        return;
+    }
+
+    ALOGI("%s", __FUNCTION__);
+
+    mResourceLost = false;
+    updateCurrentSession_l();
+
+    validateState_l();
+}
+
+void TranscodingSessionController::validateState_l() {
+#ifdef VALIDATE_STATE
+    LOG_ALWAYS_FATAL_IF(mSessionQueues.count(OFFLINE_UID) != 1,
+                        "mSessionQueues offline queue number is not 1");
+    LOG_ALWAYS_FATAL_IF(*mOfflineUidIterator != OFFLINE_UID,
+                        "mOfflineUidIterator not pointing to offline uid");
+    LOG_ALWAYS_FATAL_IF(mUidSortedList.size() != mSessionQueues.size(),
+                        "mUidList and mSessionQueues size mismatch");
+
+    int32_t totalSessions = 0;
+    for (auto uid : mUidSortedList) {
+        LOG_ALWAYS_FATAL_IF(mSessionQueues.count(uid) != 1,
+                            "mSessionQueues count for uid %d is not 1", uid);
+        for (auto& sessionKey : mSessionQueues[uid]) {
+            LOG_ALWAYS_FATAL_IF(mSessionMap.count(sessionKey) != 1,
+                                "mSessions count for session %s is not 1",
+                                sessionToString(sessionKey).c_str());
+        }
+
+        totalSessions += mSessionQueues[uid].size();
+    }
+    LOG_ALWAYS_FATAL_IF(mSessionMap.size() != totalSessions,
+                        "mSessions size doesn't match total sessions counted from uid queues");
+#endif  // VALIDATE_STATE
+}
+
+}  // namespace android
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/libmediatranscoding/TranscodingUidPolicy.cpp
index f0d4945..9763921 100644
--- a/media/libmediatranscoding/TranscodingUidPolicy.cpp
+++ b/media/libmediatranscoding/TranscodingUidPolicy.cpp
@@ -24,7 +24,9 @@
 #include <android/content/pm/IPackageManagerNative.h>
 #include <binder/ActivityManager.h>
 #include <binder/IServiceManager.h>
+#include <binder/PermissionController.h>
 #include <cutils/misc.h>  // FIRST_APPLICATION_UID
+#include <cutils/multiuser.h>
 #include <inttypes.h>
 #include <media/TranscodingUidPolicy.h>
 #include <utils/Log.h>
@@ -133,6 +135,19 @@
     return true;
 }
 
+//static
+status_t TranscodingUidPolicy::getUidForPackage(String16 packageName, /*inout*/ uid_t& uid) {
+    PermissionController pc;
+    uid = pc.getPackageUid(packageName, 0);
+    if (uid <= 0) {
+        ALOGE("Unknown package: '%s'", String8(packageName).string());
+        return BAD_VALUE;
+    }
+
+    uid = multiuser_get_uid(0 /*userId*/, uid);
+    return NO_ERROR;
+}
+
 TranscodingUidPolicy::TranscodingUidPolicy()
       : mAm(std::make_shared<ActivityManager>()),
         mUidObserver(new UidObserver(this)),
diff --git a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
index 7fc7748..ad2358e 100644
--- a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
+++ b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
@@ -18,7 +18,7 @@
 
 import android.media.ITranscodingClient;
 import android.media.ITranscodingClientCallback;
-import android.media.TranscodingJobParcel;
+import android.media.TranscodingSessionParcel;
 import android.media.TranscodingRequestParcel;
 
 /**
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl b/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
index 37b5147..151e3d0 100644
--- a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
+++ b/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.TranscodingJobParcel;
+import android.media.TranscodingSessionParcel;
 import android.media.TranscodingRequestParcel;
 
 /**
@@ -31,28 +31,28 @@
      * Submits a transcoding request to MediaTranscodingService.
      *
      * @param request a TranscodingRequest contains transcoding configuration.
-     * @param job(output variable) a TranscodingJob generated by the MediaTranscodingService.
+     * @param session(output variable) a TranscodingSession generated by MediaTranscodingService.
      * @return true if success, false otherwise.
      */
     boolean submitRequest(in TranscodingRequestParcel request,
-                          out TranscodingJobParcel job);
+                          out TranscodingSessionParcel session);
 
     /**
-     * Cancels a transcoding job.
+     * Cancels a transcoding session.
      *
-     * @param jobId a TranscodingJob generated by the MediaTranscodingService.
+     * @param sessionId a TranscodingSession generated by the MediaTranscodingService.
      * @return true if succeeds, false otherwise.
      */
-    boolean cancelJob(in int jobId);
+    boolean cancelSession(in int sessionId);
 
     /**
-     * Queries the job detail associated with a jobId.
+     * Queries the session detail associated with a sessionId.
      *
-     * @param jobId a TranscodingJob generated by the MediaTranscodingService.
-     * @param job(output variable) the TranscodingJob associated with the jobId.
+     * @param sessionId a TranscodingSession generated by the MediaTranscodingService.
+     * @param session(output variable) the TranscodingSession associated with the sessionId.
      * @return true if succeeds, false otherwise.
      */
-    boolean getJobWithId(in int jobId, out TranscodingJobParcel job);
+    boolean getSessionWithId(in int sessionId, out TranscodingSessionParcel session);
 
     /**
     * Unregister the client with the MediaTranscodingService.
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl b/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
index 73edb95..d7d9b6f 100644
--- a/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
+++ b/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
@@ -17,7 +17,7 @@
 package android.media;
 
 import android.media.TranscodingErrorCode;
-import android.media.TranscodingJobParcel;
+import android.media.TranscodingSessionParcel;
 import android.media.TranscodingResultParcel;
 import android.os.ParcelFileDescriptor;
 
@@ -40,68 +40,68 @@
                                             in @utf8InCpp String mode);
 
     /**
-    * Called when the transcoding associated with the jobId finished.
-    * This will only be called if client request to get all the status of the job.
+    * Called when the transcoding associated with the sessionId finished.
+    * This will only be called if client request to get all the status of the session.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     */
-    oneway void onTranscodingStarted(in int jobId);
+    oneway void onTranscodingStarted(in int sessionId);
 
     /**
-    * Called when the transcoding associated with the jobId is paused.
-    * This will only be called if client request to get all the status of the job.
+    * Called when the transcoding associated with the sessionId is paused.
+    * This will only be called if client request to get all the status of the session.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     */
-    oneway void onTranscodingPaused(in int jobId);
+    oneway void onTranscodingPaused(in int sessionId);
 
     /**
-    * Called when the transcoding associated with the jobId is resumed.
-    * This will only be called if client request to get all the status of the job.
+    * Called when the transcoding associated with the sessionId is resumed.
+    * This will only be called if client request to get all the status of the session.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     */
-    oneway void onTranscodingResumed(in int jobId);
+    oneway void onTranscodingResumed(in int sessionId);
 
     /**
-    * Called when the transcoding associated with the jobId finished.
+    * Called when the transcoding associated with the sessionId finished.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     * @param result contains the transcoded file stats and other transcoding metrics if requested.
     */
-    oneway void onTranscodingFinished(in int jobId, in TranscodingResultParcel result);
+    oneway void onTranscodingFinished(in int sessionId, in TranscodingResultParcel result);
 
     /**
-    * Called when the transcoding associated with the jobId failed.
+    * Called when the transcoding associated with the sessionId failed.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     * @param errorCode error code that indicates the error.
     */
-    oneway void onTranscodingFailed(in int jobId, in TranscodingErrorCode errorCode);
+    oneway void onTranscodingFailed(in int sessionId, in TranscodingErrorCode errorCode);
 
     /**
-    * Called when the transcoding configuration associated with the jobId gets updated, i.e. wait
-    * number in the job queue.
+    * Called when the transcoding configuration associated with the sessionId gets updated, i.e. wait
+    * number in the session queue.
     *
     * <p> This will only be called if client set requestUpdate to be true in the TranscodingRequest
     * submitted to the MediaTranscodingService.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
-    * @param oldAwaitNumber previous number of jobs ahead of current job.
-    * @param newAwaitNumber updated number of jobs ahead of current job.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
+    * @param oldAwaitNumber previous number of sessions ahead of current session.
+    * @param newAwaitNumber updated number of sessions ahead of current session.
     */
-    oneway void onAwaitNumberOfJobsChanged(in int jobId,
+    oneway void onAwaitNumberOfSessionsChanged(in int sessionId,
                                            in int oldAwaitNumber,
                                            in int newAwaitNumber);
 
     /**
-    * Called when there is an update on the progress of the TranscodingJob.
+    * Called when there is an update on the progress of the TranscodingSession.
     *
     * <p> This will only be called if client set requestUpdate to be true in the TranscodingRequest
     * submitted to the MediaTranscodingService.
     *
-    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param sessionId sessionId assigned by the MediaTranscodingService upon receiving request.
     * @param progress an integer number ranging from 0 ~ 100 inclusive.
     */
-    oneway void onProgressUpdate(in int jobId, in int progress);
+    oneway void onProgressUpdate(in int sessionId, in int progress);
 }
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
index 14d19ba..03c24f0 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.TranscodingJobPriority;
+import android.media.TranscodingSessionPriority;
 import android.media.TranscodingTestConfig;
 import android.media.TranscodingType;
 import android.media.TranscodingVideoTrackFormat;
@@ -61,26 +61,26 @@
      * Requested video track format for the transcoding.
      * Note that the transcoding service will try to fulfill the requested format as much as
      * possbile, while subject to hardware and software limitation. The final video track format
-     * will be available in the TranscodingJobParcel when the job is finished.
+     * will be available in the TranscodingSessionParcel when the session is finished.
      */
     @nullable TranscodingVideoTrackFormat requestedVideoTrackFormat;
 
     /**
      * Priority of this transcoding. Service will schedule the transcoding based on the priority.
      */
-    TranscodingJobPriority priority;
+    TranscodingSessionPriority priority;
 
     /**
-     * Whether to receive update on progress and change of awaitNumJobs.
+     * Whether to receive update on progress and change of awaitNumSessions.
      * Default to false.
      */
     boolean requestProgressUpdate = false;
 
     /**
-     * Whether to receive update on job's start/stop/pause/resume.
+     * Whether to receive update on session's start/stop/pause/resume.
      * Default to false.
      */
-    boolean requestJobEventUpdate = false;
+    boolean requestSessionEventUpdate = false;
 
     /**
      * Whether this request is for testing.
@@ -94,7 +94,7 @@
 
      /**
       * Whether to get the stats of the transcoding.
-      * If this is enabled, the TranscodingJobStats will be returned in TranscodingResultParcel
+      * If this is enabled, the TranscodingSessionStats will be returned in TranscodingResultParcel
       * upon transcoding finishes.
       */
     boolean enableStats = false;
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
index a20c8b1..7826e25 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.TranscodingJobStats;
+import android.media.TranscodingSessionStats;
 
 /**
  * Result of the transcoding.
@@ -26,9 +26,9 @@
 //TODO(hkuang): Implement the parcelable.
 parcelable TranscodingResultParcel {
     /**
-     * The jobId associated with the TranscodingResult.
+     * The sessionId associated with the TranscodingResult.
      */
-    int jobId;
+    int sessionId;
 
     /**
      * Actual bitrate of the transcoded video in bits per second. This will only present for video
@@ -37,8 +37,8 @@
     int actualBitrateBps;
 
     /**
-     * Stats of the transcoding job. This will only be available when client requests to get the
+     * Stats of the transcoding session. This will only be available when client requests to get the
      * stats in TranscodingRequestParcel.
      */
-    @nullable TranscodingJobStats jobStats;
+    @nullable TranscodingSessionStats sessionStats;
 }
\ No newline at end of file
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
similarity index 61%
rename from media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl
rename to media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
index baf4381..3a4a500 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
@@ -20,34 +20,34 @@
 import android.media.TranscodingVideoTrackFormat;
 
 /**
- * TranscodingJob is generated by the MediaTranscodingService upon receiving a TranscodingRequest.
- * It contains all the necessary configuration generated by the MediaTranscodingService for the
- * TranscodingRequest.
+ * TranscodingSession is generated by the MediaTranscodingService upon receiving a
+ * TranscodingRequest. It contains all the necessary configuration generated by the
+ * MediaTranscodingService for the TranscodingRequest.
  *
  * {@hide}
  */
 //TODO(hkuang): Implement the parcelable.
-parcelable TranscodingJobParcel {
+parcelable TranscodingSessionParcel {
     /**
      * A unique positive Id generated by the MediaTranscodingService.
      */
-    int jobId;
+    int sessionId;
 
     /**
-     * The request associated with the TranscodingJob.
+     * The request associated with the TranscodingSession.
      */
     TranscodingRequestParcel request;
 
     /**
      * Output video track's format. This will only be avaiable for video transcoding and it will
-     * be avaiable when the job is finished.
+     * be avaiable when the session is finished.
      */
     @nullable TranscodingVideoTrackFormat videoTrackFormat;
 
     /**
-    * Current number of jobs ahead of this job. The service schedules the job based on the priority
-    * passed from the client. Client could specify whether to receive updates when the
-    * awaitNumberOfJobs changes through setting requestProgressUpdate in the TranscodingRequest.
+    * Current number of sessions ahead of this session. The service schedules the session based on
+    * the priority passed from the client. Client could specify whether to receive updates when the
+    * awaitNumberOfSessions changes through setting requestProgressUpdate in the TranscodingRequest.
     */
-    int awaitNumberOfJobs;
+    int awaitNumberOfSessions;
 }
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
similarity index 92%
rename from media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl
rename to media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
index 1a5d81a..f001484 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
@@ -17,12 +17,12 @@
 package android.media;
 
 /**
- * Priority of a transcoding job.
+ * Priority of a transcoding session.
  *
  * {@hide}
  */
 @Backing(type="int")
-enum TranscodingJobPriority {
+enum TranscodingSessionPriority {
     // TODO(hkuang): define what each priority level actually mean.
     kUnspecified = 0,
     kLow = 1,
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingJobStats.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
similarity index 65%
rename from media/libmediatranscoding/aidl/android/media/TranscodingJobStats.aidl
rename to media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
index 1b41b87..b3e7eea 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingJobStats.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
@@ -17,20 +17,20 @@
 package android.media;
 
 /**
- * TranscodingJobStats encapsulated the stats of the a TranscodingJob.
+ * TranscodingSessionStats encapsulated the stats of the a TranscodingSession.
  *
  * {@hide}
  */
-parcelable TranscodingJobStats {
+parcelable TranscodingSessionStats {
     /**
-     * System time of when the job is created.
+     * System time of when the session is created.
      */
-    long jobCreatedTimeUs;
+    long sessionCreatedTimeUs;
 
     /**
-     * System time of when the job is finished.
+     * System time of when the session is finished.
      */
-    long jobFinishedTimeUs;
+    long sessionFinishedTimeUs;
 
     /**
      * Total time spend on transcoding, exclude the time in pause.
@@ -38,8 +38,8 @@
     long totalProcessingTimeUs;
 
     /**
-     * Total time spend on handling the job, include the time in pause.
-     * The totaltimeUs is actually the same as jobFinishedTimeUs - jobCreatedTimeUs.
+     * Total time spend on handling the session, include the time in pause.
+     * The totaltimeUs is actually the same as sessionFinishedTimeUs - sessionCreatedTimeUs.
      */
     long totalTimeUs;
 }
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
index a564799..12e0e94 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
@@ -24,7 +24,7 @@
 parcelable TranscodingTestConfig {
     /**
      * Whether to use SimulatedTranscoder for testing. Note that SimulatedTranscoder does not send
-     * transcoding jobs to real MediaTranscoder.
+     * transcoding sessions to real MediaTranscoder.
      */
     boolean useSimulatedTranscoder = false;
 
@@ -35,9 +35,10 @@
     boolean passThroughMode = false;
 
     /**
-     * Time of processing the job in milliseconds. Service will return the job result at least after
-     * processingTotalTimeMs from the time it starts to process the job. Note that if service uses
-     * real MediaTranscoder to do transcoding, the time spent on transcoding may be more than that.
+     * Time of processing the session in milliseconds. Service will return the session result at
+     * least after processingTotalTimeMs from the time it starts to process the session. Note that
+     * if service uses real MediaTranscoder to do transcoding, the time spent on transcoding may be
+     * more than that.
      */
     int processingTotalTimeMs = 0;
 }
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
index 90502cd..8ed241a 100644
--- a/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
@@ -25,13 +25,13 @@
  * aidl_interface
  *
  * Note that TranscodingVideoTrackFormat is used in TranscodingRequestParcel for the  client to
- * specify the desired transcoded video format, and is also used in TranscodingJobParcel for the
+ * specify the desired transcoded video format, and is also used in TranscodingSessionParcel for the
  * service to notify client of the final video format for transcoding.
  * When used as input in TranscodingRequestParcel, the client only needs to specify the config that
  * they want to change, e.g. codec or resolution, and all the missing configs will be extracted
  * from the source video and applied to the destination video.
- * When used as output in TranscodingJobParcel, all the configs will be populated to indicate the
- * final encoder configs used for transcoding.
+ * When used as output in TranscodingSessionParcel, all the configs will be populated to indicate
+ * the final encoder configs used for transcoding.
  *
  * {@hide}
  */
diff --git a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
index 9ca2ee9..5ba1ee2 100644
--- a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
+++ b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
@@ -26,7 +26,7 @@
 namespace android {
 
 /*
- * AdjustableMaxPriorityQueue is a custom max priority queue that helps managing jobs for
+ * AdjustableMaxPriorityQueue is a custom max priority queue that helps managing sessions for
  * MediaTranscodingService.
  *
  * AdjustableMaxPriorityQueue is a wrapper template around the STL's *_heap() functions.
diff --git a/media/libmediatranscoding/include/media/ControllerClientInterface.h b/media/libmediatranscoding/include/media/ControllerClientInterface.h
new file mode 100644
index 0000000..3fd4f0c
--- /dev/null
+++ b/media/libmediatranscoding/include/media/ControllerClientInterface.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_CONTROLLER_CLIENT_INTERFACE_H
+#define ANDROID_MEDIA_CONTROLLER_CLIENT_INTERFACE_H
+
+#include <aidl/android/media/ITranscodingClientCallback.h>
+#include <aidl/android/media/TranscodingRequestParcel.h>
+#include <media/TranscodingDefs.h>
+
+namespace android {
+
+using ::aidl::android::media::ITranscodingClientCallback;
+using ::aidl::android::media::TranscodingRequestParcel;
+
+// Interface for a client to call the controller to schedule or retrieve
+// the status of a session.
+class ControllerClientInterface {
+public:
+    /**
+     * Submits one request to the controller.
+     *
+     * Returns true on success and false on failure. This call will fail is a session identified
+     * by <clientId, sessionId> already exists.
+     */
+    virtual bool submit(ClientIdType clientId, SessionIdType sessionId, uid_t uid,
+                        const TranscodingRequestParcel& request,
+                        const std::weak_ptr<ITranscodingClientCallback>& clientCallback) = 0;
+
+    /**
+     * Cancels a session identified by <clientId, sessionId>.
+     *
+     * If sessionId is negative (<0), all sessions with a specified priority (that's not
+     * TranscodingSessionPriority::kUnspecified) will be cancelled. Otherwise, only the single
+     * session <clientId, sessionId> will be cancelled.
+     *
+     * Returns false if a single session is being cancelled but it doesn't exist. Returns
+     * true otherwise.
+     */
+    virtual bool cancel(ClientIdType clientId, SessionIdType sessionId) = 0;
+
+    /**
+     * Retrieves information about a session.
+     *
+     * Returns true and the session if it exists, and false otherwise.
+     */
+    virtual bool getSession(ClientIdType clientId, SessionIdType sessionId,
+                            TranscodingRequestParcel* request) = 0;
+
+protected:
+    virtual ~ControllerClientInterface() = default;
+};
+
+}  // namespace android
+#endif  // ANDROID_MEDIA_CONTROLLER_CLIENT_INTERFACE_H
diff --git a/media/libmediatranscoding/include/media/ResourcePolicyInterface.h b/media/libmediatranscoding/include/media/ResourcePolicyInterface.h
index 8bd7d6b..4a92af8 100644
--- a/media/libmediatranscoding/include/media/ResourcePolicyInterface.h
+++ b/media/libmediatranscoding/include/media/ResourcePolicyInterface.h
@@ -21,7 +21,7 @@
 
 class ResourcePolicyCallbackInterface;
 
-// Interface for the JobScheduler to control the resource status updates.
+// Interface for the SessionController to control the resource status updates.
 class ResourcePolicyInterface {
 public:
     // Set the associated callback interface to send the events when resource
@@ -32,11 +32,11 @@
     virtual ~ResourcePolicyInterface() = default;
 };
 
-// Interface for notifying the JobScheduler of a change in resource status.
+// Interface for notifying the SessionController of a change in resource status.
 class ResourcePolicyCallbackInterface {
 public:
-    // Called when codec resources become available. The scheduler may use this
-    // as a signal to attempt restart transcoding jobs that were previously
+    // Called when codec resources become available. The controller may use this
+    // as a signal to attempt restart transcoding sessions that were previously
     // paused due to temporary resource loss.
     virtual void onResourceAvailable() = 0;
 
diff --git a/media/libmediatranscoding/include/media/SchedulerClientInterface.h b/media/libmediatranscoding/include/media/SchedulerClientInterface.h
deleted file mode 100644
index e00cfb2..0000000
--- a/media/libmediatranscoding/include/media/SchedulerClientInterface.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_MEDIA_SCHEDULER_CLIENT_INTERFACE_H
-#define ANDROID_MEDIA_SCHEDULER_CLIENT_INTERFACE_H
-
-#include <aidl/android/media/ITranscodingClientCallback.h>
-#include <aidl/android/media/TranscodingRequestParcel.h>
-#include <media/TranscodingDefs.h>
-
-namespace android {
-
-using ::aidl::android::media::ITranscodingClientCallback;
-using ::aidl::android::media::TranscodingRequestParcel;
-
-// Interface for a client to call the scheduler to schedule or retrieve
-// the status of a job.
-class SchedulerClientInterface {
-public:
-    /**
-     * Submits one request to the scheduler.
-     *
-     * Returns true on success and false on failure. This call will fail is a job identified
-     * by <clientId, jobId> already exists.
-     */
-    virtual bool submit(ClientIdType clientId, JobIdType jobId, uid_t uid,
-                        const TranscodingRequestParcel& request,
-                        const std::weak_ptr<ITranscodingClientCallback>& clientCallback) = 0;
-
-    /**
-     * Cancels a job identified by <clientId, jobId>.
-     *
-     * If jobId is negative (<0), all jobs with a specified priority (that's not
-     * TranscodingJobPriority::kUnspecified) will be cancelled. Otherwise, only the single job
-     * <clientId, jobId> will be cancelled.
-     *
-     * Returns false if a single job is being cancelled but it doesn't exist. Returns
-     * true otherwise.
-     */
-    virtual bool cancel(ClientIdType clientId, JobIdType jobId) = 0;
-
-    /**
-     * Retrieves information about a job.
-     *
-     * Returns true and the job if it exists, and false otherwise.
-     */
-    virtual bool getJob(ClientIdType clientId, JobIdType jobId,
-                        TranscodingRequestParcel* request) = 0;
-
-protected:
-    virtual ~SchedulerClientInterface() = default;
-};
-
-}  // namespace android
-#endif  // ANDROID_MEDIA_SCHEDULER_CLIENT_INTERFACE_H
diff --git a/media/libmediatranscoding/include/media/TranscoderInterface.h b/media/libmediatranscoding/include/media/TranscoderInterface.h
index 1a3f505..e17cd5a 100644
--- a/media/libmediatranscoding/include/media/TranscoderInterface.h
+++ b/media/libmediatranscoding/include/media/TranscoderInterface.h
@@ -29,39 +29,41 @@
 using ::aidl::android::media::TranscodingRequestParcel;
 class TranscoderCallbackInterface;
 
-// Interface for the scheduler to call the transcoder to take actions.
+// Interface for the controller to call the transcoder to take actions.
 class TranscoderInterface {
 public:
     virtual void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& cb) = 0;
-    virtual void start(ClientIdType clientId, JobIdType jobId,
+    virtual void start(ClientIdType clientId, SessionIdType sessionId,
                        const TranscodingRequestParcel& request,
                        const std::shared_ptr<ITranscodingClientCallback>& clientCallback) = 0;
-    virtual void pause(ClientIdType clientId, JobIdType jobId) = 0;
-    virtual void resume(ClientIdType clientId, JobIdType jobId,
+    virtual void pause(ClientIdType clientId, SessionIdType sessionId) = 0;
+    virtual void resume(ClientIdType clientId, SessionIdType sessionId,
                         const TranscodingRequestParcel& request,
                         const std::shared_ptr<ITranscodingClientCallback>& clientCallback) = 0;
-    virtual void stop(ClientIdType clientId, JobIdType jobId) = 0;
+    virtual void stop(ClientIdType clientId, SessionIdType sessionId) = 0;
 
 protected:
     virtual ~TranscoderInterface() = default;
 };
 
-// Interface for the transcoder to notify the scheduler of the status of
-// the currently running job, or temporary loss of transcoding resources.
+// Interface for the transcoder to notify the controller of the status of
+// the currently running session, or temporary loss of transcoding resources.
 class TranscoderCallbackInterface {
 public:
     // TODO(chz): determine what parameters are needed here.
-    virtual void onStarted(ClientIdType clientId, JobIdType jobId) = 0;
-    virtual void onPaused(ClientIdType clientId, JobIdType jobId) = 0;
-    virtual void onResumed(ClientIdType clientId, JobIdType jobId) = 0;
-    virtual void onFinish(ClientIdType clientId, JobIdType jobId) = 0;
-    virtual void onError(ClientIdType clientId, JobIdType jobId, TranscodingErrorCode err) = 0;
-    virtual void onProgressUpdate(ClientIdType clientId, JobIdType jobId, int32_t progress) = 0;
+    virtual void onStarted(ClientIdType clientId, SessionIdType sessionId) = 0;
+    virtual void onPaused(ClientIdType clientId, SessionIdType sessionId) = 0;
+    virtual void onResumed(ClientIdType clientId, SessionIdType sessionId) = 0;
+    virtual void onFinish(ClientIdType clientId, SessionIdType sessionId) = 0;
+    virtual void onError(ClientIdType clientId, SessionIdType sessionId,
+                         TranscodingErrorCode err) = 0;
+    virtual void onProgressUpdate(ClientIdType clientId, SessionIdType sessionId,
+                                  int32_t progress) = 0;
 
     // Called when transcoding becomes temporarily inaccessible due to loss of resource.
-    // If there is any job currently running, it will be paused. When resource contention
-    // is solved, the scheduler should call TranscoderInterface's to either start a new job,
-    // or resume a paused job.
+    // If there is any session currently running, it will be paused. When resource contention
+    // is solved, the controller should call TranscoderInterface's to either start a new session,
+    // or resume a paused session.
     virtual void onResourceLost() = 0;
 
 protected:
diff --git a/media/libmediatranscoding/include/media/TranscoderWrapper.h b/media/libmediatranscoding/include/media/TranscoderWrapper.h
index c956042..6bf6b56 100644
--- a/media/libmediatranscoding/include/media/TranscoderWrapper.h
+++ b/media/libmediatranscoding/include/media/TranscoderWrapper.h
@@ -32,7 +32,7 @@
 
 /*
  * Wrapper class around MediaTranscoder.
- * Implements TranscoderInterface for TranscodingJobScheduler to use.
+ * Implements TranscoderInterface for TranscodingSessionController to use.
  */
 class TranscoderWrapper : public TranscoderInterface,
                           public std::enable_shared_from_this<TranscoderWrapper> {
@@ -40,25 +40,25 @@
     TranscoderWrapper();
 
     virtual void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& cb) override;
-    virtual void start(ClientIdType clientId, JobIdType jobId,
+    virtual void start(ClientIdType clientId, SessionIdType sessionId,
                        const TranscodingRequestParcel& request,
                        const std::shared_ptr<ITranscodingClientCallback>& clientCallback) override;
-    virtual void pause(ClientIdType clientId, JobIdType jobId) override;
-    virtual void resume(ClientIdType clientId, JobIdType jobId,
+    virtual void pause(ClientIdType clientId, SessionIdType sessionId) override;
+    virtual void resume(ClientIdType clientId, SessionIdType sessionId,
                         const TranscodingRequestParcel& request,
                         const std::shared_ptr<ITranscodingClientCallback>& clientCallback) override;
-    virtual void stop(ClientIdType clientId, JobIdType jobId) override;
+    virtual void stop(ClientIdType clientId, SessionIdType sessionId) override;
 
 private:
     class CallbackImpl;
     struct Event {
         enum Type { NoEvent, Start, Pause, Resume, Stop, Finish, Error, Progress } type;
         ClientIdType clientId;
-        JobIdType jobId;
+        SessionIdType sessionId;
         std::function<void()> runnable;
         int32_t arg;
     };
-    using JobKeyType = std::pair<ClientIdType, JobIdType>;
+    using SessionKeyType = std::pair<ClientIdType, SessionIdType>;
 
     std::shared_ptr<CallbackImpl> mTranscoderCb;
     std::shared_ptr<MediaTranscoder> mTranscoder;
@@ -66,30 +66,30 @@
     std::mutex mLock;
     std::condition_variable mCondition;
     std::list<Event> mQueue;  // GUARDED_BY(mLock);
-    std::map<JobKeyType, std::shared_ptr<const Parcel>> mPausedStateMap;
+    std::map<SessionKeyType, std::shared_ptr<const Parcel>> mPausedStateMap;
     ClientIdType mCurrentClientId;
-    JobIdType mCurrentJobId;
+    SessionIdType mCurrentSessionId;
 
     static std::string toString(const Event& event);
-    void onFinish(ClientIdType clientId, JobIdType jobId);
-    void onError(ClientIdType clientId, JobIdType jobId, media_status_t status);
-    void onProgress(ClientIdType clientId, JobIdType jobId, int32_t progress);
+    void onFinish(ClientIdType clientId, SessionIdType sessionId);
+    void onError(ClientIdType clientId, SessionIdType sessionId, media_status_t status);
+    void onProgress(ClientIdType clientId, SessionIdType sessionId, int32_t progress);
 
-    media_status_t handleStart(ClientIdType clientId, JobIdType jobId,
+    media_status_t handleStart(ClientIdType clientId, SessionIdType sessionId,
                                const TranscodingRequestParcel& request,
                                const std::shared_ptr<ITranscodingClientCallback>& callback);
-    media_status_t handlePause(ClientIdType clientId, JobIdType jobId);
-    media_status_t handleResume(ClientIdType clientId, JobIdType jobId,
+    media_status_t handlePause(ClientIdType clientId, SessionIdType sessionId);
+    media_status_t handleResume(ClientIdType clientId, SessionIdType sessionId,
                                 const TranscodingRequestParcel& request,
                                 const std::shared_ptr<ITranscodingClientCallback>& callback);
-    media_status_t setupTranscoder(ClientIdType clientId, JobIdType jobId,
+    media_status_t setupTranscoder(ClientIdType clientId, SessionIdType sessionId,
                                    const TranscodingRequestParcel& request,
                                    const std::shared_ptr<ITranscodingClientCallback>& callback,
                                    const std::shared_ptr<const Parcel>& pausedState = nullptr);
 
     void cleanup();
-    void reportError(ClientIdType clientId, JobIdType jobId, media_status_t err);
-    void queueEvent(Event::Type type, ClientIdType clientId, JobIdType jobId,
+    void reportError(ClientIdType clientId, SessionIdType sessionId, media_status_t err);
+    void queueEvent(Event::Type type, ClientIdType clientId, SessionIdType sessionId,
                     const std::function<void()> runnable, int32_t arg = 0);
     void threadLoop();
 };
diff --git a/media/libmediatranscoding/include/media/TranscodingClientManager.h b/media/libmediatranscoding/include/media/TranscodingClientManager.h
index 015a83a..5feeae9 100644
--- a/media/libmediatranscoding/include/media/TranscodingClientManager.h
+++ b/media/libmediatranscoding/include/media/TranscodingClientManager.h
@@ -29,7 +29,7 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include "SchedulerClientInterface.h"
+#include "ControllerClientInterface.h"
 
 namespace android {
 
@@ -84,7 +84,10 @@
     struct ClientImpl;
 
     // Only allow MediaTranscodingService and unit tests to instantiate.
-    TranscodingClientManager(const std::shared_ptr<SchedulerClientInterface>& scheduler);
+    TranscodingClientManager(const std::shared_ptr<ControllerClientInterface>& controller);
+
+    // Checks if a user is trusted (and allowed to submit sessions on behalf of other uids)
+    bool isTrustedCallingUid(uid_t uid);
 
     /**
      * Removes an existing client from the manager.
@@ -105,7 +108,8 @@
 
     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
 
-    std::shared_ptr<SchedulerClientInterface> mJobScheduler;
+    std::shared_ptr<ControllerClientInterface> mSessionController;
+    uid_t mMediaProviderUid;
 
     static std::atomic<ClientIdType> sCookieCounter;
     static std::mutex sCookie2ClientLock;
diff --git a/media/libmediatranscoding/include/media/TranscodingDefs.h b/media/libmediatranscoding/include/media/TranscodingDefs.h
index 31d83ac..8e02dd2 100644
--- a/media/libmediatranscoding/include/media/TranscodingDefs.h
+++ b/media/libmediatranscoding/include/media/TranscodingDefs.h
@@ -23,7 +23,7 @@
 namespace android {
 
 using ClientIdType = uintptr_t;
-using JobIdType = int32_t;
+using SessionIdType = int32_t;
 
 }  // namespace android
 #endif  // ANDROID_MEDIA_TRANSCODING_DEFS_H
diff --git a/media/libmediatranscoding/include/media/TranscodingJobScheduler.h b/media/libmediatranscoding/include/media/TranscodingJobScheduler.h
deleted file mode 100644
index 7a656d5..0000000
--- a/media/libmediatranscoding/include/media/TranscodingJobScheduler.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_MEDIA_TRANSCODING_JOB_SCHEDULER_H
-#define ANDROID_MEDIA_TRANSCODING_JOB_SCHEDULER_H
-
-#include <aidl/android/media/TranscodingJobPriority.h>
-#include <media/ResourcePolicyInterface.h>
-#include <media/SchedulerClientInterface.h>
-#include <media/TranscoderInterface.h>
-#include <media/TranscodingRequest.h>
-#include <media/UidPolicyInterface.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-
-#include <list>
-#include <map>
-#include <mutex>
-
-namespace android {
-using ::aidl::android::media::TranscodingJobPriority;
-using ::aidl::android::media::TranscodingResultParcel;
-
-class TranscodingJobScheduler : public UidPolicyCallbackInterface,
-                                public SchedulerClientInterface,
-                                public TranscoderCallbackInterface,
-                                public ResourcePolicyCallbackInterface {
-public:
-    virtual ~TranscodingJobScheduler();
-
-    // SchedulerClientInterface
-    bool submit(ClientIdType clientId, JobIdType jobId, uid_t uid,
-                const TranscodingRequestParcel& request,
-                const std::weak_ptr<ITranscodingClientCallback>& clientCallback) override;
-    bool cancel(ClientIdType clientId, JobIdType jobId) override;
-    bool getJob(ClientIdType clientId, JobIdType jobId, TranscodingRequestParcel* request) override;
-    // ~SchedulerClientInterface
-
-    // TranscoderCallbackInterface
-    void onStarted(ClientIdType clientId, JobIdType jobId) override;
-    void onPaused(ClientIdType clientId, JobIdType jobId) override;
-    void onResumed(ClientIdType clientId, JobIdType jobId) override;
-    void onFinish(ClientIdType clientId, JobIdType jobId) override;
-    void onError(ClientIdType clientId, JobIdType jobId, TranscodingErrorCode err) override;
-    void onProgressUpdate(ClientIdType clientId, JobIdType jobId, int32_t progress) override;
-    void onResourceLost() override;
-    // ~TranscoderCallbackInterface
-
-    // UidPolicyCallbackInterface
-    void onTopUidsChanged(const std::unordered_set<uid_t>& uids) override;
-    // ~UidPolicyCallbackInterface
-
-    // ResourcePolicyCallbackInterface
-    void onResourceAvailable() override;
-    // ~ResourcePolicyCallbackInterface
-
-    /**
-     * Dump all the job information to the fd.
-     */
-    void dumpAllJobs(int fd, const Vector<String16>& args);
-
-private:
-    friend class MediaTranscodingService;
-    friend class TranscodingJobSchedulerTest;
-
-    using JobKeyType = std::pair<ClientIdType, JobIdType>;
-    using JobQueueType = std::list<JobKeyType>;
-
-    struct Job {
-        JobKeyType key;
-        uid_t uid;
-        enum State {
-            NOT_STARTED,
-            RUNNING,
-            PAUSED,
-        } state;
-        int32_t lastProgress;
-        TranscodingRequest request;
-        std::weak_ptr<ITranscodingClientCallback> callback;
-    };
-
-    // TODO(chz): call transcoder without global lock.
-    // Use mLock for all entrypoints for now.
-    mutable std::mutex mLock;
-
-    std::map<JobKeyType, Job> mJobMap;
-
-    // uid->JobQueue map (uid == -1: offline queue)
-    std::map<uid_t, JobQueueType> mJobQueues;
-
-    // uids, with the head being the most-recently-top app, 2nd item is the
-    // previous top app, etc.
-    std::list<uid_t> mUidSortedList;
-    std::list<uid_t>::iterator mOfflineUidIterator;
-
-    std::shared_ptr<TranscoderInterface> mTranscoder;
-    std::shared_ptr<UidPolicyInterface> mUidPolicy;
-    std::shared_ptr<ResourcePolicyInterface> mResourcePolicy;
-
-    Job* mCurrentJob;
-    bool mResourceLost;
-
-    // Only allow MediaTranscodingService and unit tests to instantiate.
-    TranscodingJobScheduler(const std::shared_ptr<TranscoderInterface>& transcoder,
-                            const std::shared_ptr<UidPolicyInterface>& uidPolicy,
-                            const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
-
-    Job* getTopJob_l();
-    void updateCurrentJob_l();
-    void removeJob_l(const JobKeyType& jobKey);
-    void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
-    void notifyClient(ClientIdType clientId, JobIdType jobId, const char* reason,
-                      std::function<void(const JobKeyType&)> func);
-    // Internal state verifier (debug only)
-    void validateState_l();
-
-    static String8 jobToString(const JobKeyType& jobKey);
-    static const char* jobStateToString(const Job::State jobState);
-};
-
-}  // namespace android
-#endif  // ANDROID_MEDIA_TRANSCODING_JOB_SCHEDULER_H
diff --git a/media/libmediatranscoding/include/media/TranscodingRequest.h b/media/libmediatranscoding/include/media/TranscodingRequest.h
index a6cfed2..aae621f 100644
--- a/media/libmediatranscoding/include/media/TranscodingRequest.h
+++ b/media/libmediatranscoding/include/media/TranscodingRequest.h
@@ -43,7 +43,7 @@
         requestedVideoTrackFormat = parcel.requestedVideoTrackFormat;
         priority = parcel.priority;
         requestProgressUpdate = parcel.requestProgressUpdate;
-        requestJobEventUpdate = parcel.requestJobEventUpdate;
+        requestSessionEventUpdate = parcel.requestSessionEventUpdate;
         isForTesting = parcel.isForTesting;
         testConfig = parcel.testConfig;
     }
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/libmediatranscoding/include/media/TranscodingSessionController.h
new file mode 100644
index 0000000..9ab3518
--- /dev/null
+++ b/media/libmediatranscoding/include/media/TranscodingSessionController.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H
+#define ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H
+
+#include <aidl/android/media/TranscodingSessionPriority.h>
+#include <media/ControllerClientInterface.h>
+#include <media/ResourcePolicyInterface.h>
+#include <media/TranscoderInterface.h>
+#include <media/TranscodingRequest.h>
+#include <media/UidPolicyInterface.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <list>
+#include <map>
+#include <mutex>
+
+namespace android {
+using ::aidl::android::media::TranscodingResultParcel;
+using ::aidl::android::media::TranscodingSessionPriority;
+
+class TranscodingSessionController : public UidPolicyCallbackInterface,
+                                     public ControllerClientInterface,
+                                     public TranscoderCallbackInterface,
+                                     public ResourcePolicyCallbackInterface {
+public:
+    virtual ~TranscodingSessionController();
+
+    // ControllerClientInterface
+    bool submit(ClientIdType clientId, SessionIdType sessionId, uid_t uid,
+                const TranscodingRequestParcel& request,
+                const std::weak_ptr<ITranscodingClientCallback>& clientCallback) override;
+    bool cancel(ClientIdType clientId, SessionIdType sessionId) override;
+    bool getSession(ClientIdType clientId, SessionIdType sessionId,
+                    TranscodingRequestParcel* request) override;
+    // ~ControllerClientInterface
+
+    // TranscoderCallbackInterface
+    void onStarted(ClientIdType clientId, SessionIdType sessionId) override;
+    void onPaused(ClientIdType clientId, SessionIdType sessionId) override;
+    void onResumed(ClientIdType clientId, SessionIdType sessionId) override;
+    void onFinish(ClientIdType clientId, SessionIdType sessionId) override;
+    void onError(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) override;
+    void onProgressUpdate(ClientIdType clientId, SessionIdType sessionId,
+                          int32_t progress) override;
+    void onResourceLost() override;
+    // ~TranscoderCallbackInterface
+
+    // UidPolicyCallbackInterface
+    void onTopUidsChanged(const std::unordered_set<uid_t>& uids) override;
+    // ~UidPolicyCallbackInterface
+
+    // ResourcePolicyCallbackInterface
+    void onResourceAvailable() override;
+    // ~ResourcePolicyCallbackInterface
+
+    /**
+     * Dump all the session information to the fd.
+     */
+    void dumpAllSessions(int fd, const Vector<String16>& args);
+
+private:
+    friend class MediaTranscodingService;
+    friend class TranscodingSessionControllerTest;
+
+    using SessionKeyType = std::pair<ClientIdType, SessionIdType>;
+    using SessionQueueType = std::list<SessionKeyType>;
+
+    struct Session {
+        SessionKeyType key;
+        uid_t uid;
+        enum State {
+            NOT_STARTED,
+            RUNNING,
+            PAUSED,
+        } state;
+        int32_t lastProgress;
+        TranscodingRequest request;
+        std::weak_ptr<ITranscodingClientCallback> callback;
+    };
+
+    // TODO(chz): call transcoder without global lock.
+    // Use mLock for all entrypoints for now.
+    mutable std::mutex mLock;
+
+    std::map<SessionKeyType, Session> mSessionMap;
+
+    // uid->SessionQueue map (uid == -1: offline queue)
+    std::map<uid_t, SessionQueueType> mSessionQueues;
+
+    // uids, with the head being the most-recently-top app, 2nd item is the
+    // previous top app, etc.
+    std::list<uid_t> mUidSortedList;
+    std::list<uid_t>::iterator mOfflineUidIterator;
+
+    std::shared_ptr<TranscoderInterface> mTranscoder;
+    std::shared_ptr<UidPolicyInterface> mUidPolicy;
+    std::shared_ptr<ResourcePolicyInterface> mResourcePolicy;
+
+    Session* mCurrentSession;
+    bool mResourceLost;
+
+    // Only allow MediaTranscodingService and unit tests to instantiate.
+    TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
+                                 const std::shared_ptr<UidPolicyInterface>& uidPolicy,
+                                 const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
+
+    Session* getTopSession_l();
+    void updateCurrentSession_l();
+    void removeSession_l(const SessionKeyType& sessionKey);
+    void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
+    void notifyClient(ClientIdType clientId, SessionIdType sessionId, const char* reason,
+                      std::function<void(const SessionKeyType&)> func);
+    // Internal state verifier (debug only)
+    void validateState_l();
+
+    static String8 sessionToString(const SessionKeyType& sessionKey);
+    static const char* sessionStateToString(const Session::State sessionState);
+};
+
+}  // namespace android
+#endif  // ANDROID_MEDIA_TRANSCODING_SESSION_CONTROLLER_H
diff --git a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
index 42052cb..946770c 100644
--- a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
+++ b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
@@ -35,7 +35,7 @@
 
 class ActivityManager;
 // Observer for UID lifecycle and provide information about the uid's app
-// priority used by the job scheduler.
+// priority used by the session controller.
 class TranscodingUidPolicy : public UidPolicyInterface {
 public:
     explicit TranscodingUidPolicy();
@@ -50,6 +50,7 @@
     // ~UidPolicyInterface
 
     static bool getNamesForUids(const std::vector<int32_t>& uids, std::vector<std::string>* names);
+    static status_t getUidForPackage(String16 packageName, /*inout*/ uid_t& uid);
 
 private:
     void onUidStateChanged(uid_t uid, int32_t procState);
diff --git a/media/libmediatranscoding/include/media/UidPolicyInterface.h b/media/libmediatranscoding/include/media/UidPolicyInterface.h
index f88c1ed..05d8db0 100644
--- a/media/libmediatranscoding/include/media/UidPolicyInterface.h
+++ b/media/libmediatranscoding/include/media/UidPolicyInterface.h
@@ -23,7 +23,7 @@
 
 class UidPolicyCallbackInterface;
 
-// Interface for the scheduler to query a uid's info.
+// Interface for the controller to query a uid's info.
 class UidPolicyInterface {
 public:
     // Instruct the uid policy to start monitoring a uid.
@@ -41,7 +41,7 @@
     virtual ~UidPolicyInterface() = default;
 };
 
-// Interface for notifying the scheduler of a change in uid states.
+// Interface for notifying the controller of a change in uid states.
 class UidPolicyCallbackInterface {
 public:
     // Called when the set of uids that's top priority among the uids of interest
diff --git a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
index 2e49f32..a35ca53 100644
--- a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
+++ b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
@@ -223,19 +223,19 @@
 }
 
 // Test the heap property and make sure it is the same as std::priority_queue.
-TEST(AdjustableMaxPriorityQueueTest, TranscodingJobTest) {
-    // Test data structure that mimics the Transcoding job.
-    struct TranscodingJob {
+TEST(AdjustableMaxPriorityQueueTest, TranscodingSessionTest) {
+    // Test data structure that mimics the Transcoding session.
+    struct TranscodingSession {
         int32_t priority;
         int64_t createTimeUs;
     };
 
-    // The job is arranging according to priority with highest priority comes first.
-    // For the job with the same priority, the job with early createTime will come first.
-    class TranscodingJobComp {
+    // The session is arranging according to priority with highest priority comes first.
+    // For the session with the same priority, the session with early createTime will come first.
+    class TranscodingSessionComp {
     public:
-        bool operator()(const std::unique_ptr<TranscodingJob>& lhs,
-                        const std::unique_ptr<TranscodingJob>& rhs) const {
+        bool operator()(const std::unique_ptr<TranscodingSession>& lhs,
+                        const std::unique_ptr<TranscodingSession>& rhs) const {
             if (lhs->priority != rhs->priority) {
                 return lhs->priority < rhs->priority;
             }
@@ -244,46 +244,47 @@
     };
 
     // Map to save each value's position in the heap.
-    std::unordered_map<int, TranscodingJob*> jobIdToJobMap;
+    std::unordered_map<int, TranscodingSession*> sessionIdToSessionMap;
 
-    TranscodingJob testJobs[] = {
-            {1 /*priority*/, 66 /*createTimeUs*/},  // First job,
-            {2 /*priority*/, 67 /*createTimeUs*/},  // Second job,
-            {2 /*priority*/, 66 /*createTimeUs*/},  // Third job,
-            {3 /*priority*/, 68 /*createTimeUs*/},  // Fourth job.
+    TranscodingSession testSessions[] = {
+            {1 /*priority*/, 66 /*createTimeUs*/},  // First session,
+            {2 /*priority*/, 67 /*createTimeUs*/},  // Second session,
+            {2 /*priority*/, 66 /*createTimeUs*/},  // Third session,
+            {3 /*priority*/, 68 /*createTimeUs*/},  // Fourth session.
     };
 
-    AdjustableMaxPriorityQueue<std::unique_ptr<TranscodingJob>, TranscodingJobComp> jobQueue;
+    AdjustableMaxPriorityQueue<std::unique_ptr<TranscodingSession>, TranscodingSessionComp>
+            sessionQueue;
 
-    // Pushes all the jobs into the heap.
-    for (int jobId = 0; jobId < 4; ++jobId) {
-        auto newJob = std::make_unique<TranscodingJob>(testJobs[jobId]);
-        jobIdToJobMap[jobId] = newJob.get();
-        EXPECT_TRUE(jobQueue.push(std::move(newJob)));
+    // Pushes all the sessions into the heap.
+    for (int sessionId = 0; sessionId < 4; ++sessionId) {
+        auto newSession = std::make_unique<TranscodingSession>(testSessions[sessionId]);
+        sessionIdToSessionMap[sessionId] = newSession.get();
+        EXPECT_TRUE(sessionQueue.push(std::move(newSession)));
     }
 
-    // Check the job queue size.
-    EXPECT_EQ(4, jobQueue.size());
+    // Check the session queue size.
+    EXPECT_EQ(4, sessionQueue.size());
 
-    // Check the top and it should be Forth job: (3, 68)
-    const std::unique_ptr<TranscodingJob>& topJob = jobQueue.top();
-    EXPECT_EQ(3, topJob->priority);
-    EXPECT_EQ(68, topJob->createTimeUs);
+    // Check the top and it should be Forth session: (3, 68)
+    const std::unique_ptr<TranscodingSession>& topSession = sessionQueue.top();
+    EXPECT_EQ(3, topSession->priority);
+    EXPECT_EQ(68, topSession->createTimeUs);
 
     // Consume the top.
-    std::unique_ptr<TranscodingJob> consumeJob = jobQueue.consume_top();
+    std::unique_ptr<TranscodingSession> consumeSession = sessionQueue.consume_top();
 
-    // Check the top and it should be Third Job (2, 66)
-    const std::unique_ptr<TranscodingJob>& topJob2 = jobQueue.top();
-    EXPECT_EQ(2, topJob2->priority);
-    EXPECT_EQ(66, topJob2->createTimeUs);
+    // Check the top and it should be Third Session (2, 66)
+    const std::unique_ptr<TranscodingSession>& topSession2 = sessionQueue.top();
+    EXPECT_EQ(2, topSession2->priority);
+    EXPECT_EQ(66, topSession2->createTimeUs);
 
-    // Change the Second job's priority to 4 from (2, 67) -> (4, 67). It should becomes top of the
-    // queue.
-    jobIdToJobMap[1]->priority = 4;
-    jobQueue.rebuild();
-    const std::unique_ptr<TranscodingJob>& topJob3 = jobQueue.top();
-    EXPECT_EQ(4, topJob3->priority);
-    EXPECT_EQ(67, topJob3->createTimeUs);
+    // Change the Second session's priority to 4 from (2, 67) -> (4, 67). It should becomes
+    // top of the queue.
+    sessionIdToSessionMap[1]->priority = 4;
+    sessionQueue.rebuild();
+    const std::unique_ptr<TranscodingSession>& topSession3 = sessionQueue.top();
+    EXPECT_EQ(4, topSession3->priority);
+    EXPECT_EQ(67, topSession3->createTimeUs);
 }
 }  // namespace android
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index b54022a..7b15b1b 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -38,13 +38,13 @@
 }
 
 //
-// TranscodingJobScheduler unit test
+// TranscodingSessionController unit test
 //
 cc_test {
-    name: "TranscodingJobScheduler_tests",
+    name: "TranscodingSessionController_tests",
     defaults: ["libmediatranscoding_test_defaults"],
 
-    srcs: ["TranscodingJobScheduler_tests.cpp"],
+    srcs: ["TranscodingSessionController_tests.cpp"],
 }
 
 //
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
index c2ca9b4..1a50923 100644
--- a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
+++ b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
@@ -25,7 +25,7 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <gtest/gtest.h>
-#include <media/SchedulerClientInterface.h>
+#include <media/ControllerClientInterface.h>
 #include <media/TranscodingClientManager.h>
 #include <media/TranscodingRequest.h>
 #include <utils/Log.h>
@@ -38,10 +38,10 @@
 using ::aidl::android::media::BnTranscodingClientCallback;
 using ::aidl::android::media::IMediaTranscodingService;
 using ::aidl::android::media::TranscodingErrorCode;
-using ::aidl::android::media::TranscodingJobParcel;
-using ::aidl::android::media::TranscodingJobPriority;
 using ::aidl::android::media::TranscodingRequestParcel;
 using ::aidl::android::media::TranscodingResultParcel;
+using ::aidl::android::media::TranscodingSessionParcel;
+using ::aidl::android::media::TranscodingSessionPriority;
 
 constexpr pid_t kInvalidClientPid = -5;
 constexpr pid_t kInvalidClientUid = -10;
@@ -51,7 +51,7 @@
 constexpr const char* kClientName = "TestClientName";
 constexpr const char* kClientPackage = "TestClientPackage";
 
-#define JOB(n) (n)
+#define SESSION(n) (n)
 
 struct TestClientCallback : public BnTranscodingClientCallback {
     TestClientCallback() { ALOGI("TestClientCallback Created"); }
@@ -63,30 +63,32 @@
         return Status::ok();
     }
 
-    Status onTranscodingStarted(int32_t /*in_jobId*/) override { return Status::ok(); }
+    Status onTranscodingStarted(int32_t /*in_sessionId*/) override { return Status::ok(); }
 
-    Status onTranscodingPaused(int32_t /*in_jobId*/) override { return Status::ok(); }
+    Status onTranscodingPaused(int32_t /*in_sessionId*/) override { return Status::ok(); }
 
-    Status onTranscodingResumed(int32_t /*in_jobId*/) override { return Status::ok(); }
+    Status onTranscodingResumed(int32_t /*in_sessionId*/) override { return Status::ok(); }
 
-    Status onTranscodingFinished(int32_t in_jobId,
+    Status onTranscodingFinished(int32_t in_sessionId,
                                  const TranscodingResultParcel& in_result) override {
-        EXPECT_EQ(in_jobId, in_result.jobId);
-        mEventQueue.push_back(Finished(in_jobId));
+        EXPECT_EQ(in_sessionId, in_result.sessionId);
+        mEventQueue.push_back(Finished(in_sessionId));
         return Status::ok();
     }
 
-    Status onTranscodingFailed(int32_t in_jobId, TranscodingErrorCode /*in_errorCode */) override {
-        mEventQueue.push_back(Failed(in_jobId));
+    Status onTranscodingFailed(int32_t in_sessionId,
+                               TranscodingErrorCode /*in_errorCode */) override {
+        mEventQueue.push_back(Failed(in_sessionId));
         return Status::ok();
     }
 
-    Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
-                                      int32_t /* in_newAwaitNumber */) override {
+    Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
+                                          int32_t /* in_oldAwaitNumber */,
+                                          int32_t /* in_newAwaitNumber */) override {
         return Status::ok();
     }
 
-    Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
+    Status onProgressUpdate(int32_t /* in_sessionId */, int32_t /* in_progress */) override {
         return Status::ok();
     }
 
@@ -96,12 +98,12 @@
             Finished,
             Failed,
         } type;
-        JobIdType jobId;
+        SessionIdType sessionId;
     };
 
     static constexpr Event NoEvent = {Event::NoEvent, 0};
 #define DECLARE_EVENT(action) \
-    static Event action(JobIdType jobId) { return {Event::action, jobId}; }
+    static Event action(SessionIdType sessionId) { return {Event::action, sessionId}; }
 
     DECLARE_EVENT(Finished);
     DECLARE_EVENT(Failed);
@@ -125,102 +127,102 @@
 };
 
 bool operator==(const TestClientCallback::Event& lhs, const TestClientCallback::Event& rhs) {
-    return lhs.type == rhs.type && lhs.jobId == rhs.jobId;
+    return lhs.type == rhs.type && lhs.sessionId == rhs.sessionId;
 }
 
-struct TestScheduler : public SchedulerClientInterface {
-    TestScheduler() { ALOGI("TestScheduler Created"); }
+struct TestController : public ControllerClientInterface {
+    TestController() { ALOGI("TestController Created"); }
 
-    virtual ~TestScheduler() { ALOGI("TestScheduler Destroyed"); }
+    virtual ~TestController() { ALOGI("TestController Destroyed"); }
 
-    bool submit(ClientIdType clientId, JobIdType jobId, uid_t /*uid*/,
+    bool submit(ClientIdType clientId, SessionIdType sessionId, uid_t /*uid*/,
                 const TranscodingRequestParcel& request,
                 const std::weak_ptr<ITranscodingClientCallback>& clientCallback) override {
-        JobKeyType jobKey = std::make_pair(clientId, jobId);
-        if (mJobs.count(jobKey) > 0) {
+        SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+        if (mSessions.count(sessionKey) > 0) {
             return false;
         }
 
         // This is the secret name we'll check, to test error propagation from
-        // the scheduler back to client.
+        // the controller back to client.
         if (request.sourceFilePath == "bad_source_file") {
             return false;
         }
 
-        mJobs[jobKey].request = request;
-        mJobs[jobKey].callback = clientCallback;
+        mSessions[sessionKey].request = request;
+        mSessions[sessionKey].callback = clientCallback;
 
-        mLastJob = jobKey;
+        mLastSession = sessionKey;
         return true;
     }
 
-    bool cancel(ClientIdType clientId, JobIdType jobId) override {
-        JobKeyType jobKey = std::make_pair(clientId, jobId);
+    bool cancel(ClientIdType clientId, SessionIdType sessionId) override {
+        SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
 
-        if (mJobs.count(jobKey) == 0) {
+        if (mSessions.count(sessionKey) == 0) {
             return false;
         }
-        mJobs.erase(jobKey);
+        mSessions.erase(sessionKey);
         return true;
     }
 
-    bool getJob(ClientIdType clientId, JobIdType jobId,
-                TranscodingRequestParcel* request) override {
-        JobKeyType jobKey = std::make_pair(clientId, jobId);
-        if (mJobs.count(jobKey) == 0) {
+    bool getSession(ClientIdType clientId, SessionIdType sessionId,
+                    TranscodingRequestParcel* request) override {
+        SessionKeyType sessionKey = std::make_pair(clientId, sessionId);
+        if (mSessions.count(sessionKey) == 0) {
             return false;
         }
 
-        *(TranscodingRequest*)request = mJobs[jobKey].request;
+        *(TranscodingRequest*)request = mSessions[sessionKey].request;
         return true;
     }
 
-    void finishLastJob() {
-        auto it = mJobs.find(mLastJob);
-        if (it == mJobs.end()) {
+    void finishLastSession() {
+        auto it = mSessions.find(mLastSession);
+        if (it == mSessions.end()) {
             return;
         }
         {
             auto clientCallback = it->second.callback.lock();
             if (clientCallback != nullptr) {
                 clientCallback->onTranscodingFinished(
-                        mLastJob.second,
-                        TranscodingResultParcel({mLastJob.second, 0, std::nullopt}));
+                        mLastSession.second,
+                        TranscodingResultParcel({mLastSession.second, 0, std::nullopt}));
             }
         }
-        mJobs.erase(it);
+        mSessions.erase(it);
     }
 
-    void abortLastJob() {
-        auto it = mJobs.find(mLastJob);
-        if (it == mJobs.end()) {
+    void abortLastSession() {
+        auto it = mSessions.find(mLastSession);
+        if (it == mSessions.end()) {
             return;
         }
         {
             auto clientCallback = it->second.callback.lock();
             if (clientCallback != nullptr) {
-                clientCallback->onTranscodingFailed(mLastJob.second,
+                clientCallback->onTranscodingFailed(mLastSession.second,
                                                     TranscodingErrorCode::kUnknown);
             }
         }
-        mJobs.erase(it);
+        mSessions.erase(it);
     }
 
-    struct Job {
+    struct Session {
         TranscodingRequest request;
         std::weak_ptr<ITranscodingClientCallback> callback;
     };
 
-    typedef std::pair<ClientIdType, JobIdType> JobKeyType;
-    std::map<JobKeyType, Job> mJobs;
-    JobKeyType mLastJob;
+    typedef std::pair<ClientIdType, SessionIdType> SessionKeyType;
+    std::map<SessionKeyType, Session> mSessions;
+    SessionKeyType mLastSession;
 };
 
 class TranscodingClientManagerTest : public ::testing::Test {
 public:
     TranscodingClientManagerTest()
-          : mScheduler(new TestScheduler()),
-            mClientManager(new TranscodingClientManager(mScheduler)) {
+          : mController(new TestController()),
+            mClientManager(new TranscodingClientManager(mController)) {
         ALOGD("TranscodingClientManagerTest created");
     }
 
@@ -260,7 +262,7 @@
         EXPECT_EQ(mClientManager->getNumOfClients(), 0);
     }
 
-    std::shared_ptr<TestScheduler> mScheduler;
+    std::shared_ptr<TestController> mController;
     std::shared_ptr<TranscodingClientManager> mClientManager;
     std::shared_ptr<ITranscodingClient> mClient1;
     std::shared_ptr<ITranscodingClient> mClient2;
@@ -349,36 +351,36 @@
     unregisterMultipleClients();
 }
 
-TEST_F(TranscodingClientManagerTest, TestSubmitCancelGetJobs) {
+TEST_F(TranscodingClientManagerTest, TestSubmitCancelGetSessions) {
     addMultipleClients();
 
-    // Test jobId assignment.
+    // Test sessionId assignment.
     TranscodingRequestParcel request;
     request.sourceFilePath = "test_source_file_0";
     request.destinationFilePath = "test_desintaion_file_0";
-    TranscodingJobParcel job;
+    TranscodingSessionParcel session;
     bool result;
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(0));
+    EXPECT_EQ(session.sessionId, SESSION(0));
 
     request.sourceFilePath = "test_source_file_1";
     request.destinationFilePath = "test_desintaion_file_1";
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(1));
+    EXPECT_EQ(session.sessionId, SESSION(1));
 
     request.sourceFilePath = "test_source_file_2";
     request.destinationFilePath = "test_desintaion_file_2";
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(2));
+    EXPECT_EQ(session.sessionId, SESSION(2));
 
     // Test submit bad request (no valid sourceFilePath) fails.
     TranscodingRequestParcel badRequest;
     badRequest.sourceFilePath = "bad_source_file";
     badRequest.destinationFilePath = "bad_destination_file";
-    EXPECT_TRUE(mClient1->submitRequest(badRequest, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(badRequest, &session, &result).isOk());
     EXPECT_FALSE(result);
 
     // Test submit with bad pid/uid.
@@ -386,49 +388,49 @@
     badRequest.destinationFilePath = "test_desintaion_file_3";
     badRequest.clientPid = kInvalidClientPid;
     badRequest.clientUid = kInvalidClientUid;
-    EXPECT_TRUE(mClient1->submitRequest(badRequest, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(badRequest, &session, &result).isOk());
     EXPECT_FALSE(result);
 
-    // Test get jobs by id.
-    EXPECT_TRUE(mClient1->getJobWithId(JOB(2), &job, &result).isOk());
-    EXPECT_EQ(job.jobId, JOB(2));
-    EXPECT_EQ(job.request.sourceFilePath, "test_source_file_2");
+    // Test get sessions by id.
+    EXPECT_TRUE(mClient1->getSessionWithId(SESSION(2), &session, &result).isOk());
+    EXPECT_EQ(session.sessionId, SESSION(2));
+    EXPECT_EQ(session.request.sourceFilePath, "test_source_file_2");
     EXPECT_TRUE(result);
 
-    // Test get jobs by invalid id fails.
-    EXPECT_TRUE(mClient1->getJobWithId(JOB(100), &job, &result).isOk());
+    // Test get sessions by invalid id fails.
+    EXPECT_TRUE(mClient1->getSessionWithId(SESSION(100), &session, &result).isOk());
     EXPECT_FALSE(result);
 
-    // Test cancel non-existent job fail.
-    EXPECT_TRUE(mClient2->cancelJob(JOB(100), &result).isOk());
+    // Test cancel non-existent session fail.
+    EXPECT_TRUE(mClient2->cancelSession(SESSION(100), &result).isOk());
     EXPECT_FALSE(result);
 
-    // Test cancel valid jobId in arbitrary order.
-    EXPECT_TRUE(mClient1->cancelJob(JOB(2), &result).isOk());
+    // Test cancel valid sessionId in arbitrary order.
+    EXPECT_TRUE(mClient1->cancelSession(SESSION(2), &result).isOk());
     EXPECT_TRUE(result);
 
-    EXPECT_TRUE(mClient1->cancelJob(JOB(0), &result).isOk());
+    EXPECT_TRUE(mClient1->cancelSession(SESSION(0), &result).isOk());
     EXPECT_TRUE(result);
 
-    EXPECT_TRUE(mClient1->cancelJob(JOB(1), &result).isOk());
+    EXPECT_TRUE(mClient1->cancelSession(SESSION(1), &result).isOk());
     EXPECT_TRUE(result);
 
-    // Test cancel job again fails.
-    EXPECT_TRUE(mClient1->cancelJob(JOB(1), &result).isOk());
+    // Test cancel session again fails.
+    EXPECT_TRUE(mClient1->cancelSession(SESSION(1), &result).isOk());
     EXPECT_FALSE(result);
 
-    // Test get job after cancel fails.
-    EXPECT_TRUE(mClient1->getJobWithId(JOB(2), &job, &result).isOk());
+    // Test get session after cancel fails.
+    EXPECT_TRUE(mClient1->getSessionWithId(SESSION(2), &session, &result).isOk());
     EXPECT_FALSE(result);
 
-    // Test jobId independence for each client.
-    EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
+    // Test sessionId independence for each client.
+    EXPECT_TRUE(mClient2->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(0));
+    EXPECT_EQ(session.sessionId, SESSION(0));
 
-    EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient2->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(1));
+    EXPECT_EQ(session.sessionId, SESSION(1));
 
     unregisterMultipleClients();
 }
@@ -439,32 +441,32 @@
     TranscodingRequestParcel request;
     request.sourceFilePath = "test_source_file_name";
     request.destinationFilePath = "test_destination_file_name";
-    TranscodingJobParcel job;
+    TranscodingSessionParcel session;
     bool result;
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(0));
+    EXPECT_EQ(session.sessionId, SESSION(0));
 
-    mScheduler->finishLastJob();
-    EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Finished(job.jobId));
+    mController->finishLastSession();
+    EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Finished(session.sessionId));
 
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(1));
+    EXPECT_EQ(session.sessionId, SESSION(1));
 
-    mScheduler->abortLastJob();
-    EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Failed(job.jobId));
+    mController->abortLastSession();
+    EXPECT_EQ(mClientCallback1->popEvent(), TestClientCallback::Failed(session.sessionId));
 
-    EXPECT_TRUE(mClient1->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient1->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(2));
+    EXPECT_EQ(session.sessionId, SESSION(2));
 
-    EXPECT_TRUE(mClient2->submitRequest(request, &job, &result).isOk());
+    EXPECT_TRUE(mClient2->submitRequest(request, &session, &result).isOk());
     EXPECT_TRUE(result);
-    EXPECT_EQ(job.jobId, JOB(0));
+    EXPECT_EQ(session.sessionId, SESSION(0));
 
-    mScheduler->finishLastJob();
-    EXPECT_EQ(mClientCallback2->popEvent(), TestClientCallback::Finished(job.jobId));
+    mController->finishLastSession();
+    EXPECT_EQ(mClientCallback2->popEvent(), TestClientCallback::Finished(session.sessionId));
 
     unregisterMultipleClients();
 }
@@ -479,20 +481,20 @@
 
     // Submit 2 requests, 1 offline and 1 realtime.
     TranscodingRequestParcel request;
-    TranscodingJobParcel job;
+    TranscodingSessionParcel session;
     bool result;
 
     request.sourceFilePath = "test_source_file_0";
     request.destinationFilePath = "test_destination_file_0";
-    request.priority = TranscodingJobPriority::kUnspecified;
-    EXPECT_TRUE(client->submitRequest(request, &job, &result).isOk() && result);
-    EXPECT_EQ(job.jobId, JOB(0));
+    request.priority = TranscodingSessionPriority::kUnspecified;
+    EXPECT_TRUE(client->submitRequest(request, &session, &result).isOk() && result);
+    EXPECT_EQ(session.sessionId, SESSION(0));
 
     request.sourceFilePath = "test_source_file_1";
     request.destinationFilePath = "test_destination_file_1";
-    request.priority = TranscodingJobPriority::kNormal;
-    EXPECT_TRUE(client->submitRequest(request, &job, &result).isOk() && result);
-    EXPECT_EQ(job.jobId, JOB(1));
+    request.priority = TranscodingSessionPriority::kNormal;
+    EXPECT_TRUE(client->submitRequest(request, &session, &result).isOk() && result);
+    EXPECT_EQ(session.sessionId, SESSION(1));
 
     // Unregister client, should succeed.
     Status status = client->unregister();
@@ -501,36 +503,36 @@
     // Test submit new request after unregister, should fail with ERROR_DISCONNECTED.
     request.sourceFilePath = "test_source_file_2";
     request.destinationFilePath = "test_destination_file_2";
-    request.priority = TranscodingJobPriority::kNormal;
-    status = client->submitRequest(request, &job, &result);
+    request.priority = TranscodingSessionPriority::kNormal;
+    status = client->submitRequest(request, &session, &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    // Test cancel jobs after unregister, should fail with ERROR_DISCONNECTED
-    // regardless of realtime or offline job, or whether the jobId is valid.
-    status = client->cancelJob(JOB(0), &result);
+    // Test cancel sessions after unregister, should fail with ERROR_DISCONNECTED
+    // regardless of realtime or offline session, or whether the sessionId is valid.
+    status = client->cancelSession(SESSION(0), &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    status = client->cancelJob(JOB(1), &result);
+    status = client->cancelSession(SESSION(1), &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    status = client->cancelJob(JOB(2), &result);
+    status = client->cancelSession(SESSION(2), &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    // Test get jobs, should fail with ERROR_DISCONNECTED regardless of realtime
-    // or offline job, or whether the jobId is valid.
-    status = client->getJobWithId(JOB(0), &job, &result);
+    // Test get sessions, should fail with ERROR_DISCONNECTED regardless of realtime
+    // or offline session, or whether the sessionId is valid.
+    status = client->getSessionWithId(SESSION(0), &session, &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    status = client->getJobWithId(JOB(1), &job, &result);
+    status = client->getSessionWithId(SESSION(1), &session, &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    status = client->getJobWithId(JOB(2), &job, &result);
+    status = client->getSessionWithId(SESSION(2), &session, &result);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 }
diff --git a/media/libmediatranscoding/tests/TranscodingJobScheduler_tests.cpp b/media/libmediatranscoding/tests/TranscodingJobScheduler_tests.cpp
deleted file mode 100644
index 9b9df87..0000000
--- a/media/libmediatranscoding/tests/TranscodingJobScheduler_tests.cpp
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * 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.
- */
-
-// Unit Test for TranscodingJobScheduler
-
-// #define LOG_NDEBUG 0
-#define LOG_TAG "TranscodingJobSchedulerTest"
-
-#include <aidl/android/media/BnTranscodingClientCallback.h>
-#include <aidl/android/media/IMediaTranscodingService.h>
-#include <aidl/android/media/ITranscodingClient.h>
-#include <aidl/android/media/ITranscodingClientCallback.h>
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-#include <gtest/gtest.h>
-#include <media/TranscodingClientManager.h>
-#include <media/TranscodingJobScheduler.h>
-#include <utils/Log.h>
-
-#include <unordered_set>
-
-namespace android {
-
-using Status = ::ndk::ScopedAStatus;
-using aidl::android::media::BnTranscodingClientCallback;
-using aidl::android::media::IMediaTranscodingService;
-using aidl::android::media::ITranscodingClient;
-using aidl::android::media::TranscodingRequestParcel;
-
-constexpr ClientIdType kClientId = 1000;
-constexpr JobIdType kClientJobId = 0;
-constexpr uid_t kClientUid = 5000;
-constexpr uid_t kInvalidUid = (uid_t)-1;
-
-#define CLIENT(n) (kClientId + (n))
-#define JOB(n) (kClientJobId + (n))
-#define UID(n) (kClientUid + (n))
-
-class TestUidPolicy : public UidPolicyInterface {
-public:
-    TestUidPolicy() = default;
-    virtual ~TestUidPolicy() = default;
-
-    // UidPolicyInterface
-    void registerMonitorUid(uid_t /*uid*/) override {}
-    void unregisterMonitorUid(uid_t /*uid*/) override {}
-    bool isUidOnTop(uid_t uid) override { return mTopUids.count(uid) > 0; }
-    std::unordered_set<uid_t> getTopUids() const override { return mTopUids; }
-    void setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) override {
-        mUidPolicyCallback = cb;
-    }
-    void setTop(uid_t uid) {
-        std::unordered_set<uid_t> uids = {uid};
-        setTop(uids);
-    }
-    void setTop(const std::unordered_set<uid_t>& uids) {
-        mTopUids = uids;
-        auto uidPolicyCb = mUidPolicyCallback.lock();
-        if (uidPolicyCb != nullptr) {
-            uidPolicyCb->onTopUidsChanged(mTopUids);
-        }
-    }
-
-    std::unordered_set<uid_t> mTopUids;
-    std::weak_ptr<UidPolicyCallbackInterface> mUidPolicyCallback;
-};
-
-class TestTranscoder : public TranscoderInterface {
-public:
-    TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
-    virtual ~TestTranscoder() {}
-
-    // TranscoderInterface
-    void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) override {}
-
-    void start(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& /*request*/,
-               const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
-        mEventQueue.push_back(Start(clientId, jobId));
-    }
-    void pause(ClientIdType clientId, JobIdType jobId) override {
-        mEventQueue.push_back(Pause(clientId, jobId));
-    }
-    void resume(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& /*request*/,
-                const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
-        mEventQueue.push_back(Resume(clientId, jobId));
-    }
-    void stop(ClientIdType clientId, JobIdType jobId) override {
-        mEventQueue.push_back(Stop(clientId, jobId));
-    }
-
-    void onFinished(ClientIdType clientId, JobIdType jobId) {
-        mEventQueue.push_back(Finished(clientId, jobId));
-    }
-
-    void onFailed(ClientIdType clientId, JobIdType jobId, TranscodingErrorCode err) {
-        mLastError = err;
-        mEventQueue.push_back(Failed(clientId, jobId));
-    }
-
-    TranscodingErrorCode getLastError() {
-        TranscodingErrorCode result = mLastError;
-        mLastError = TranscodingErrorCode::kUnknown;
-        return result;
-    }
-
-    struct Event {
-        enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
-        ClientIdType clientId;
-        JobIdType jobId;
-    };
-
-    static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
-
-#define DECLARE_EVENT(action)                                     \
-    static Event action(ClientIdType clientId, JobIdType jobId) { \
-        return {Event::action, clientId, jobId};                  \
-    }
-
-    DECLARE_EVENT(Start);
-    DECLARE_EVENT(Pause);
-    DECLARE_EVENT(Resume);
-    DECLARE_EVENT(Stop);
-    DECLARE_EVENT(Finished);
-    DECLARE_EVENT(Failed);
-
-    const Event& popEvent() {
-        if (mEventQueue.empty()) {
-            mPoppedEvent = NoEvent;
-        } else {
-            mPoppedEvent = *mEventQueue.begin();
-            mEventQueue.pop_front();
-        }
-        return mPoppedEvent;
-    }
-
-private:
-    Event mPoppedEvent;
-    std::list<Event> mEventQueue;
-    TranscodingErrorCode mLastError;
-};
-
-bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
-    return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.jobId == rhs.jobId;
-}
-
-struct TestClientCallback : public BnTranscodingClientCallback {
-    TestClientCallback(TestTranscoder* owner, int64_t clientId)
-          : mOwner(owner), mClientId(clientId) {
-        ALOGD("TestClient Created");
-    }
-
-    Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
-                              ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
-        return Status::ok();
-    }
-
-    Status onTranscodingStarted(int32_t /*in_jobId*/) override { return Status::ok(); }
-
-    Status onTranscodingPaused(int32_t /*in_jobId*/) override { return Status::ok(); }
-
-    Status onTranscodingResumed(int32_t /*in_jobId*/) override { return Status::ok(); }
-
-    Status onTranscodingFinished(int32_t in_jobId,
-                                 const TranscodingResultParcel& in_result) override {
-        EXPECT_EQ(in_jobId, in_result.jobId);
-        ALOGD("TestClientCallback: received onTranscodingFinished");
-        mOwner->onFinished(mClientId, in_jobId);
-        return Status::ok();
-    }
-
-    Status onTranscodingFailed(int32_t in_jobId, TranscodingErrorCode in_errorCode) override {
-        mOwner->onFailed(mClientId, in_jobId, in_errorCode);
-        return Status::ok();
-    }
-
-    Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
-                                      int32_t /* in_newAwaitNumber */) override {
-        return Status::ok();
-    }
-
-    Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
-        return Status::ok();
-    }
-
-    virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
-
-private:
-    TestTranscoder* mOwner;
-    int64_t mClientId;
-    TestClientCallback(const TestClientCallback&) = delete;
-    TestClientCallback& operator=(const TestClientCallback&) = delete;
-};
-
-class TranscodingJobSchedulerTest : public ::testing::Test {
-public:
-    TranscodingJobSchedulerTest() { ALOGI("TranscodingJobSchedulerTest created"); }
-
-    void SetUp() override {
-        ALOGI("TranscodingJobSchedulerTest set up");
-        mTranscoder.reset(new TestTranscoder());
-        mUidPolicy.reset(new TestUidPolicy());
-        mScheduler.reset(
-                new TranscodingJobScheduler(mTranscoder, mUidPolicy, nullptr /*resourcePolicy*/));
-        mUidPolicy->setCallback(mScheduler);
-
-        // Set priority only, ignore other fields for now.
-        mOfflineRequest.priority = TranscodingJobPriority::kUnspecified;
-        mRealtimeRequest.priority = TranscodingJobPriority::kHigh;
-        mClientCallback0 =
-                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
-        mClientCallback1 =
-                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
-        mClientCallback2 =
-                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
-        mClientCallback3 =
-                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
-    }
-
-    void TearDown() override { ALOGI("TranscodingJobSchedulerTest tear down"); }
-
-    ~TranscodingJobSchedulerTest() { ALOGD("TranscodingJobSchedulerTest destroyed"); }
-
-    std::shared_ptr<TestTranscoder> mTranscoder;
-    std::shared_ptr<TestUidPolicy> mUidPolicy;
-    std::shared_ptr<TranscodingJobScheduler> mScheduler;
-    TranscodingRequestParcel mOfflineRequest;
-    TranscodingRequestParcel mRealtimeRequest;
-    std::shared_ptr<TestClientCallback> mClientCallback0;
-    std::shared_ptr<TestClientCallback> mClientCallback1;
-    std::shared_ptr<TestClientCallback> mClientCallback2;
-    std::shared_ptr<TestClientCallback> mClientCallback3;
-};
-
-TEST_F(TranscodingJobSchedulerTest, TestSubmitJob) {
-    ALOGD("TestSubmitJob");
-
-    // Start with UID(1) on top.
-    mUidPolicy->setTop(UID(1));
-
-    // Submit offline job to CLIENT(0) in UID(0).
-    // Should start immediately (because this is the only job).
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
-
-    // Submit real-time job to CLIENT(0).
-    // Should pause offline job and start new job,  even if UID(0) is not on top.
-    mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
-
-    // Submit real-time job to CLIENT(0), should be queued after the previous job.
-    mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit real-time job to CLIENT(1) in same uid, should be queued after the previous job.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(0), mRealtimeRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit real-time job to CLIENT(2) in UID(1).
-    // Should pause previous job and start new job, because UID(1) is (has been) top.
-    mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
-
-    // Submit offline job, shouldn't generate any event.
-    mScheduler->submit(CLIENT(2), JOB(1), UID(1), mOfflineRequest, mClientCallback2);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Bring UID(0) to top.
-    mUidPolicy->setTop(UID(0));
-    // Should pause current job, and resume last job in UID(0).
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(1)));
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestCancelJob) {
-    ALOGD("TestCancelJob");
-
-    // Submit real-time job JOB(0), should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit real-time job JOB(1), should not start.
-    mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit offline job JOB(2), should not start.
-    mScheduler->submit(CLIENT(0), JOB(2), UID(0), mOfflineRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Cancel queued real-time job.
-    // Cancel real-time job JOB(1), should be cancelled.
-    EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(1)));
-
-    // Cancel queued offline job.
-    // Cancel offline job JOB(2), should be cancelled.
-    EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(2)));
-
-    // Submit offline job JOB(3), shouldn't cause any event.
-    mScheduler->submit(CLIENT(0), JOB(3), UID(0), mOfflineRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Cancel running real-time job JOB(0).
-    // - Should be stopped first then cancelled.
-    // - Should also start offline job JOB(2) because real-time queue is empty.
-    EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(3)));
-
-    // Submit real-time job JOB(4), offline JOB(3) should pause and JOB(4) should start.
-    mScheduler->submit(CLIENT(0), JOB(4), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(3)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(4)));
-
-    // Cancel paused JOB(3). JOB(3) should be stopped.
-    EXPECT_TRUE(mScheduler->cancel(CLIENT(0), JOB(3)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), JOB(3)));
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestFinishJob) {
-    ALOGD("TestFinishJob");
-
-    // Start with unspecified top UID.
-    // Finish without any jobs submitted, should be ignored.
-    mScheduler->onFinish(CLIENT(0), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit offline job JOB(0), should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit real-time job JOB(1), should pause offline job and start immediately.
-    mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
-
-    // Submit real-time job JOB(2), should not start.
-    mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Finish when the job never started, should be ignored.
-    mScheduler->onFinish(CLIENT(0), JOB(2));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // UID(1) moves to top.
-    mUidPolicy->setTop(UID(1));
-    // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
-
-    // Simulate Finish that arrived late, after pause issued by scheduler.
-    // Should still be propagated to client, but shouldn't trigger any new start.
-    mScheduler->onFinish(CLIENT(0), JOB(1));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(1)));
-
-    // Finish running real-time job, should start next real-time job in queue.
-    mScheduler->onFinish(CLIENT(1), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
-
-    // Finish running real-time job, should resume next job (offline job) in queue.
-    mScheduler->onFinish(CLIENT(0), JOB(2));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(2)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
-
-    // Finish running offline job.
-    mScheduler->onFinish(CLIENT(0), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
-
-    // Duplicate finish for last job, should be ignored.
-    mScheduler->onFinish(CLIENT(0), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestFailJob) {
-    ALOGD("TestFailJob");
-
-    // Start with unspecified top UID.
-    // Fail without any jobs submitted, should be ignored.
-    mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit offline job JOB(0), should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mOfflineRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit real-time job JOB(1), should pause offline job and start immediately.
-    mScheduler->submit(CLIENT(0), JOB(1), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(1)));
-
-    // Submit real-time job JOB(2), should not start.
-    mScheduler->submit(CLIENT(0), JOB(2), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Fail when the job never started, should be ignored.
-    mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // UID(1) moves to top.
-    mUidPolicy->setTop(UID(1));
-    // Submit real-time job to CLIENT(1) in UID(1), should pause previous job and start new job.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(1), mRealtimeRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(1)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
-
-    // Simulate Fail that arrived late, after pause issued by scheduler.
-    // Should still be propagated to client, but shouldn't trigger any new start.
-    mScheduler->onError(CLIENT(0), JOB(1), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(1)));
-
-    // Fail running real-time job, should start next real-time job in queue.
-    mScheduler->onError(CLIENT(1), JOB(0), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(2)));
-
-    // Fail running real-time job, should resume next job (offline job) in queue.
-    mScheduler->onError(CLIENT(0), JOB(2), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(2)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
-
-    // Fail running offline job, and test error code propagation.
-    mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kInvalidOperation);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
-
-    // Duplicate fail for last job, should be ignored.
-    mScheduler->onError(CLIENT(0), JOB(0), TranscodingErrorCode::kUnknown);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestTopUidChanged) {
-    ALOGD("TestTopUidChanged");
-
-    // Start with unspecified top UID.
-    // Submit real-time job to CLIENT(0), job should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit offline job to CLIENT(0), should not start.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Move UID(1) to top.
-    mUidPolicy->setTop(UID(1));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit real-time job to CLIENT(2) in different uid UID(1).
-    // Should pause previous job and start new job.
-    mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
-
-    // Bring UID(0) back to top.
-    mUidPolicy->setTop(UID(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
-
-    // Bring invalid uid to top.
-    mUidPolicy->setTop(kInvalidUid);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Finish job, next real-time job should resume.
-    mScheduler->onFinish(CLIENT(0), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
-
-    // Finish job, offline job should start.
-    mScheduler->onFinish(CLIENT(2), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestTopUidSetChanged) {
-    ALOGD("TestTopUidChanged_MultipleUids");
-
-    // Start with unspecified top UID.
-    // Submit real-time job to CLIENT(0), job should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit offline job to CLIENT(0), should not start.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Set UID(0), UID(1) to top set.
-    // UID(0) should continue to run.
-    mUidPolicy->setTop({UID(0), UID(1)});
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit real-time job to CLIENT(2) in different uid UID(1).
-    // UID(0) should pause and UID(1) should start.
-    mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
-
-    // Remove UID(0) from top set, and only leave UID(1) in the set.
-    // UID(1) should continue to run.
-    mUidPolicy->setTop(UID(1));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Set UID(0), UID(2) to top set.
-    // UID(1) should continue to run.
-    mUidPolicy->setTop({UID(1), UID(2)});
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Bring UID(0) back to top.
-    mUidPolicy->setTop(UID(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
-
-    // Bring invalid uid to top.
-    mUidPolicy->setTop(kInvalidUid);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Finish job, next real-time job from UID(1) should resume, even if UID(1) no longer top.
-    mScheduler->onFinish(CLIENT(0), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
-
-    // Finish job, offline job should start.
-    mScheduler->onFinish(CLIENT(2), JOB(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), JOB(0)));
-}
-
-TEST_F(TranscodingJobSchedulerTest, TestResourceLost) {
-    ALOGD("TestResourceLost");
-
-    // Start with unspecified top UID.
-    // Submit real-time job to CLIENT(0), job should start immediately.
-    mScheduler->submit(CLIENT(0), JOB(0), UID(0), mRealtimeRequest, mClientCallback0);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), JOB(0)));
-
-    // Submit offline job to CLIENT(0), should not start.
-    mScheduler->submit(CLIENT(1), JOB(0), UID(0), mOfflineRequest, mClientCallback1);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Move UID(1) to top.
-    mUidPolicy->setTop(UID(1));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Submit real-time job to CLIENT(2) in different uid UID(1).
-    // Should pause previous job and start new job.
-    mScheduler->submit(CLIENT(2), JOB(0), UID(1), mRealtimeRequest, mClientCallback2);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), JOB(0)));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), JOB(0)));
-
-    // Test 1: No queue change during resource loss.
-    // Signal resource lost.
-    mScheduler->onResourceLost();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Signal resource available, CLIENT(2) should resume.
-    mScheduler->onResourceAvailable();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), JOB(0)));
-
-    // Test 2: Change of queue order during resource loss.
-    // Signal resource lost.
-    mScheduler->onResourceLost();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Move UID(0) back to top, should have no resume due to no resource.
-    mUidPolicy->setTop(UID(0));
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Signal resource available, CLIENT(0) should resume.
-    mScheduler->onResourceAvailable();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), JOB(0)));
-
-    // Test 3: Adding new queue during resource loss.
-    // Signal resource lost.
-    mScheduler->onResourceLost();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Move UID(2) to top.
-    mUidPolicy->setTop(UID(2));
-
-    // Submit real-time job to CLIENT(3) in UID(2), job shouldn't start due to no resource.
-    mScheduler->submit(CLIENT(3), JOB(0), UID(2), mRealtimeRequest, mClientCallback3);
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
-
-    // Signal resource available, CLIENT(3)'s job should start.
-    mScheduler->onResourceAvailable();
-    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), JOB(0)));
-}
-
-}  // namespace android
diff --git a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp b/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
new file mode 100644
index 0000000..4809d7a
--- /dev/null
+++ b/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
@@ -0,0 +1,611 @@
+/*
+ * 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.
+ */
+
+// Unit Test for TranscodingSessionController
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "TranscodingSessionControllerTest"
+
+#include <aidl/android/media/BnTranscodingClientCallback.h>
+#include <aidl/android/media/IMediaTranscodingService.h>
+#include <aidl/android/media/ITranscodingClient.h>
+#include <aidl/android/media/ITranscodingClientCallback.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <media/TranscodingClientManager.h>
+#include <media/TranscodingSessionController.h>
+#include <utils/Log.h>
+
+#include <unordered_set>
+
+namespace android {
+
+using Status = ::ndk::ScopedAStatus;
+using aidl::android::media::BnTranscodingClientCallback;
+using aidl::android::media::IMediaTranscodingService;
+using aidl::android::media::ITranscodingClient;
+using aidl::android::media::TranscodingRequestParcel;
+
+constexpr ClientIdType kClientId = 1000;
+constexpr SessionIdType kClientSessionId = 0;
+constexpr uid_t kClientUid = 5000;
+constexpr uid_t kInvalidUid = (uid_t)-1;
+
+#define CLIENT(n) (kClientId + (n))
+#define SESSION(n) (kClientSessionId + (n))
+#define UID(n) (kClientUid + (n))
+
+class TestUidPolicy : public UidPolicyInterface {
+public:
+    TestUidPolicy() = default;
+    virtual ~TestUidPolicy() = default;
+
+    // UidPolicyInterface
+    void registerMonitorUid(uid_t /*uid*/) override {}
+    void unregisterMonitorUid(uid_t /*uid*/) override {}
+    bool isUidOnTop(uid_t uid) override { return mTopUids.count(uid) > 0; }
+    std::unordered_set<uid_t> getTopUids() const override { return mTopUids; }
+    void setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) override {
+        mUidPolicyCallback = cb;
+    }
+    void setTop(uid_t uid) {
+        std::unordered_set<uid_t> uids = {uid};
+        setTop(uids);
+    }
+    void setTop(const std::unordered_set<uid_t>& uids) {
+        mTopUids = uids;
+        auto uidPolicyCb = mUidPolicyCallback.lock();
+        if (uidPolicyCb != nullptr) {
+            uidPolicyCb->onTopUidsChanged(mTopUids);
+        }
+    }
+
+    std::unordered_set<uid_t> mTopUids;
+    std::weak_ptr<UidPolicyCallbackInterface> mUidPolicyCallback;
+};
+
+class TestTranscoder : public TranscoderInterface {
+public:
+    TestTranscoder() : mLastError(TranscodingErrorCode::kUnknown) {}
+    virtual ~TestTranscoder() {}
+
+    // TranscoderInterface
+    void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& /*cb*/) override {}
+
+    void start(ClientIdType clientId, SessionIdType sessionId,
+               const TranscodingRequestParcel& /*request*/,
+               const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
+        mEventQueue.push_back(Start(clientId, sessionId));
+    }
+    void pause(ClientIdType clientId, SessionIdType sessionId) override {
+        mEventQueue.push_back(Pause(clientId, sessionId));
+    }
+    void resume(ClientIdType clientId, SessionIdType sessionId,
+                const TranscodingRequestParcel& /*request*/,
+                const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) override {
+        mEventQueue.push_back(Resume(clientId, sessionId));
+    }
+    void stop(ClientIdType clientId, SessionIdType sessionId) override {
+        mEventQueue.push_back(Stop(clientId, sessionId));
+    }
+
+    void onFinished(ClientIdType clientId, SessionIdType sessionId) {
+        mEventQueue.push_back(Finished(clientId, sessionId));
+    }
+
+    void onFailed(ClientIdType clientId, SessionIdType sessionId, TranscodingErrorCode err) {
+        mLastError = err;
+        mEventQueue.push_back(Failed(clientId, sessionId));
+    }
+
+    TranscodingErrorCode getLastError() {
+        TranscodingErrorCode result = mLastError;
+        mLastError = TranscodingErrorCode::kUnknown;
+        return result;
+    }
+
+    struct Event {
+        enum { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
+        ClientIdType clientId;
+        SessionIdType sessionId;
+    };
+
+    static constexpr Event NoEvent = {Event::NoEvent, 0, 0};
+
+#define DECLARE_EVENT(action)                                             \
+    static Event action(ClientIdType clientId, SessionIdType sessionId) { \
+        return {Event::action, clientId, sessionId};                      \
+    }
+
+    DECLARE_EVENT(Start);
+    DECLARE_EVENT(Pause);
+    DECLARE_EVENT(Resume);
+    DECLARE_EVENT(Stop);
+    DECLARE_EVENT(Finished);
+    DECLARE_EVENT(Failed);
+
+    const Event& popEvent() {
+        if (mEventQueue.empty()) {
+            mPoppedEvent = NoEvent;
+        } else {
+            mPoppedEvent = *mEventQueue.begin();
+            mEventQueue.pop_front();
+        }
+        return mPoppedEvent;
+    }
+
+private:
+    Event mPoppedEvent;
+    std::list<Event> mEventQueue;
+    TranscodingErrorCode mLastError;
+};
+
+bool operator==(const TestTranscoder::Event& lhs, const TestTranscoder::Event& rhs) {
+    return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.sessionId == rhs.sessionId;
+}
+
+struct TestClientCallback : public BnTranscodingClientCallback {
+    TestClientCallback(TestTranscoder* owner, int64_t clientId)
+          : mOwner(owner), mClientId(clientId) {
+        ALOGD("TestClient Created");
+    }
+
+    Status openFileDescriptor(const std::string& /*in_fileUri*/, const std::string& /*in_mode*/,
+                              ::ndk::ScopedFileDescriptor* /*_aidl_return*/) override {
+        return Status::ok();
+    }
+
+    Status onTranscodingStarted(int32_t /*in_sessionId*/) override { return Status::ok(); }
+
+    Status onTranscodingPaused(int32_t /*in_sessionId*/) override { return Status::ok(); }
+
+    Status onTranscodingResumed(int32_t /*in_sessionId*/) override { return Status::ok(); }
+
+    Status onTranscodingFinished(int32_t in_sessionId,
+                                 const TranscodingResultParcel& in_result) override {
+        EXPECT_EQ(in_sessionId, in_result.sessionId);
+        ALOGD("TestClientCallback: received onTranscodingFinished");
+        mOwner->onFinished(mClientId, in_sessionId);
+        return Status::ok();
+    }
+
+    Status onTranscodingFailed(int32_t in_sessionId, TranscodingErrorCode in_errorCode) override {
+        mOwner->onFailed(mClientId, in_sessionId, in_errorCode);
+        return Status::ok();
+    }
+
+    Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
+                                          int32_t /* in_oldAwaitNumber */,
+                                          int32_t /* in_newAwaitNumber */) override {
+        return Status::ok();
+    }
+
+    Status onProgressUpdate(int32_t /* in_sessionId */, int32_t /* in_progress */) override {
+        return Status::ok();
+    }
+
+    virtual ~TestClientCallback() { ALOGI("TestClient destroyed"); };
+
+private:
+    TestTranscoder* mOwner;
+    int64_t mClientId;
+    TestClientCallback(const TestClientCallback&) = delete;
+    TestClientCallback& operator=(const TestClientCallback&) = delete;
+};
+
+class TranscodingSessionControllerTest : public ::testing::Test {
+public:
+    TranscodingSessionControllerTest() { ALOGI("TranscodingSessionControllerTest created"); }
+
+    void SetUp() override {
+        ALOGI("TranscodingSessionControllerTest set up");
+        mTranscoder.reset(new TestTranscoder());
+        mUidPolicy.reset(new TestUidPolicy());
+        mController.reset(new TranscodingSessionController(mTranscoder, mUidPolicy,
+                                                           nullptr /*resourcePolicy*/));
+        mUidPolicy->setCallback(mController);
+
+        // Set priority only, ignore other fields for now.
+        mOfflineRequest.priority = TranscodingSessionPriority::kUnspecified;
+        mRealtimeRequest.priority = TranscodingSessionPriority::kHigh;
+        mClientCallback0 =
+                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(0));
+        mClientCallback1 =
+                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(1));
+        mClientCallback2 =
+                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(2));
+        mClientCallback3 =
+                ::ndk::SharedRefBase::make<TestClientCallback>(mTranscoder.get(), CLIENT(3));
+    }
+
+    void TearDown() override { ALOGI("TranscodingSessionControllerTest tear down"); }
+
+    ~TranscodingSessionControllerTest() { ALOGD("TranscodingSessionControllerTest destroyed"); }
+
+    std::shared_ptr<TestTranscoder> mTranscoder;
+    std::shared_ptr<TestUidPolicy> mUidPolicy;
+    std::shared_ptr<TranscodingSessionController> mController;
+    TranscodingRequestParcel mOfflineRequest;
+    TranscodingRequestParcel mRealtimeRequest;
+    std::shared_ptr<TestClientCallback> mClientCallback0;
+    std::shared_ptr<TestClientCallback> mClientCallback1;
+    std::shared_ptr<TestClientCallback> mClientCallback2;
+    std::shared_ptr<TestClientCallback> mClientCallback3;
+};
+
+TEST_F(TranscodingSessionControllerTest, TestSubmitSession) {
+    ALOGD("TestSubmitSession");
+
+    // Start with UID(1) on top.
+    mUidPolicy->setTop(UID(1));
+
+    // Submit offline session to CLIENT(0) in UID(0).
+    // Should start immediately (because this is the only session).
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), 0));
+
+    // Submit real-time session to CLIENT(0).
+    // Should pause offline session and start new session,  even if UID(0) is not on top.
+    mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
+
+    // Submit real-time session to CLIENT(0), should be queued after the previous session.
+    mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit real-time session to CLIENT(1) in same uid, should be queued after the previous
+    // session.
+    mController->submit(CLIENT(1), SESSION(0), UID(0), mRealtimeRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit real-time session to CLIENT(2) in UID(1).
+    // Should pause previous session and start new session, because UID(1) is (has been) top.
+    mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+    // Submit offline session, shouldn't generate any event.
+    mController->submit(CLIENT(2), SESSION(1), UID(1), mOfflineRequest, mClientCallback2);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Bring UID(0) to top.
+    mUidPolicy->setTop(UID(0));
+    // Should pause current session, and resume last session in UID(0).
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(1)));
+}
+
+TEST_F(TranscodingSessionControllerTest, TestCancelSession) {
+    ALOGD("TestCancelSession");
+
+    // Submit real-time session SESSION(0), should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit real-time session SESSION(1), should not start.
+    mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit offline session SESSION(2), should not start.
+    mController->submit(CLIENT(0), SESSION(2), UID(0), mOfflineRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Cancel queued real-time session.
+    // Cancel real-time session SESSION(1), should be cancelled.
+    EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(1)));
+
+    // Cancel queued offline session.
+    // Cancel offline session SESSION(2), should be cancelled.
+    EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(2)));
+
+    // Submit offline session SESSION(3), shouldn't cause any event.
+    mController->submit(CLIENT(0), SESSION(3), UID(0), mOfflineRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Cancel running real-time session SESSION(0).
+    // - Should be stopped first then cancelled.
+    // - Should also start offline session SESSION(2) because real-time queue is empty.
+    EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(3)));
+
+    // Submit real-time session SESSION(4), offline SESSION(3) should pause and SESSION(4)
+    // should start.
+    mController->submit(CLIENT(0), SESSION(4), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(3)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(4)));
+
+    // Cancel paused SESSION(3). SESSION(3) should be stopped.
+    EXPECT_TRUE(mController->cancel(CLIENT(0), SESSION(3)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Stop(CLIENT(0), SESSION(3)));
+}
+
+TEST_F(TranscodingSessionControllerTest, TestFinishSession) {
+    ALOGD("TestFinishSession");
+
+    // Start with unspecified top UID.
+    // Finish without any sessions submitted, should be ignored.
+    mController->onFinish(CLIENT(0), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit offline session SESSION(0), should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit real-time session SESSION(1), should pause offline session and start immediately.
+    mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
+
+    // Submit real-time session SESSION(2), should not start.
+    mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Finish when the session never started, should be ignored.
+    mController->onFinish(CLIENT(0), SESSION(2));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // UID(1) moves to top.
+    mUidPolicy->setTop(UID(1));
+    // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
+    // new session.
+    mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
+
+    // Simulate Finish that arrived late, after pause issued by controller.
+    // Should still be propagated to client, but shouldn't trigger any new start.
+    mController->onFinish(CLIENT(0), SESSION(1));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(1)));
+
+    // Finish running real-time session, should start next real-time session in queue.
+    mController->onFinish(CLIENT(1), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(1), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
+
+    // Finish running real-time session, should resume next session (offline session) in queue.
+    mController->onFinish(CLIENT(0), SESSION(2));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(2)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+    // Finish running offline session.
+    mController->onFinish(CLIENT(0), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
+
+    // Duplicate finish for last session, should be ignored.
+    mController->onFinish(CLIENT(0), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+}
+
+TEST_F(TranscodingSessionControllerTest, TestFailSession) {
+    ALOGD("TestFailSession");
+
+    // Start with unspecified top UID.
+    // Fail without any sessions submitted, should be ignored.
+    mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit offline session SESSION(0), should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mOfflineRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit real-time session SESSION(1), should pause offline session and start immediately.
+    mController->submit(CLIENT(0), SESSION(1), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(1)));
+
+    // Submit real-time session SESSION(2), should not start.
+    mController->submit(CLIENT(0), SESSION(2), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Fail when the session never started, should be ignored.
+    mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // UID(1) moves to top.
+    mUidPolicy->setTop(UID(1));
+    // Submit real-time session to CLIENT(1) in UID(1), should pause previous session and start
+    // new session.
+    mController->submit(CLIENT(1), SESSION(0), UID(1), mRealtimeRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(1)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
+
+    // Simulate Fail that arrived late, after pause issued by controller.
+    // Should still be propagated to client, but shouldn't trigger any new start.
+    mController->onError(CLIENT(0), SESSION(1), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(1)));
+
+    // Fail running real-time session, should start next real-time session in queue.
+    mController->onError(CLIENT(1), SESSION(0), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(1), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(2)));
+
+    // Fail running real-time session, should resume next session (offline session) in queue.
+    mController->onError(CLIENT(0), SESSION(2), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(2)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+    // Fail running offline session, and test error code propagation.
+    mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kInvalidOperation);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Failed(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->getLastError(), TranscodingErrorCode::kInvalidOperation);
+
+    // Duplicate fail for last session, should be ignored.
+    mController->onError(CLIENT(0), SESSION(0), TranscodingErrorCode::kUnknown);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+}
+
+TEST_F(TranscodingSessionControllerTest, TestTopUidChanged) {
+    ALOGD("TestTopUidChanged");
+
+    // Start with unspecified top UID.
+    // Submit real-time session to CLIENT(0), session should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit offline session to CLIENT(0), should not start.
+    mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Move UID(1) to top.
+    mUidPolicy->setTop(UID(1));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit real-time session to CLIENT(2) in different uid UID(1).
+    // Should pause previous session and start new session.
+    mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+    // Bring UID(0) back to top.
+    mUidPolicy->setTop(UID(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+    // Bring invalid uid to top.
+    mUidPolicy->setTop(kInvalidUid);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Finish session, next real-time session should resume.
+    mController->onFinish(CLIENT(0), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+    // Finish session, offline session should start.
+    mController->onFinish(CLIENT(2), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
+}
+
+TEST_F(TranscodingSessionControllerTest, TestTopUidSetChanged) {
+    ALOGD("TestTopUidChanged_MultipleUids");
+
+    // Start with unspecified top UID.
+    // Submit real-time session to CLIENT(0), session should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit offline session to CLIENT(0), should not start.
+    mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Set UID(0), UID(1) to top set.
+    // UID(0) should continue to run.
+    mUidPolicy->setTop({UID(0), UID(1)});
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit real-time session to CLIENT(2) in different uid UID(1).
+    // UID(0) should pause and UID(1) should start.
+    mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+    // Remove UID(0) from top set, and only leave UID(1) in the set.
+    // UID(1) should continue to run.
+    mUidPolicy->setTop(UID(1));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Set UID(0), UID(2) to top set.
+    // UID(1) should continue to run.
+    mUidPolicy->setTop({UID(1), UID(2)});
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Bring UID(0) back to top.
+    mUidPolicy->setTop(UID(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(2), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+    // Bring invalid uid to top.
+    mUidPolicy->setTop(kInvalidUid);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Finish session, next real-time session from UID(1) should resume, even if UID(1)
+    // no longer top.
+    mController->onFinish(CLIENT(0), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+    // Finish session, offline session should start.
+    mController->onFinish(CLIENT(2), SESSION(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Finished(CLIENT(2), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(1), SESSION(0)));
+}
+
+TEST_F(TranscodingSessionControllerTest, TestResourceLost) {
+    ALOGD("TestResourceLost");
+
+    // Start with unspecified top UID.
+    // Submit real-time session to CLIENT(0), session should start immediately.
+    mController->submit(CLIENT(0), SESSION(0), UID(0), mRealtimeRequest, mClientCallback0);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(0), SESSION(0)));
+
+    // Submit offline session to CLIENT(0), should not start.
+    mController->submit(CLIENT(1), SESSION(0), UID(0), mOfflineRequest, mClientCallback1);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Move UID(1) to top.
+    mUidPolicy->setTop(UID(1));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Submit real-time session to CLIENT(2) in different uid UID(1).
+    // Should pause previous session and start new session.
+    mController->submit(CLIENT(2), SESSION(0), UID(1), mRealtimeRequest, mClientCallback2);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Pause(CLIENT(0), SESSION(0)));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(2), SESSION(0)));
+
+    // Test 1: No queue change during resource loss.
+    // Signal resource lost.
+    mController->onResourceLost();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Signal resource available, CLIENT(2) should resume.
+    mController->onResourceAvailable();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(2), SESSION(0)));
+
+    // Test 2: Change of queue order during resource loss.
+    // Signal resource lost.
+    mController->onResourceLost();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Move UID(0) back to top, should have no resume due to no resource.
+    mUidPolicy->setTop(UID(0));
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Signal resource available, CLIENT(0) should resume.
+    mController->onResourceAvailable();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Resume(CLIENT(0), SESSION(0)));
+
+    // Test 3: Adding new queue during resource loss.
+    // Signal resource lost.
+    mController->onResourceLost();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Move UID(2) to top.
+    mUidPolicy->setTop(UID(2));
+
+    // Submit real-time session to CLIENT(3) in UID(2), session shouldn't start due to no resource.
+    mController->submit(CLIENT(3), SESSION(0), UID(2), mRealtimeRequest, mClientCallback3);
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::NoEvent);
+
+    // Signal resource available, CLIENT(3)'s session should start.
+    mController->onResourceAvailable();
+    EXPECT_EQ(mTranscoder->popEvent(), TestTranscoder::Start(CLIENT(3), SESSION(0)));
+}
+
+}  // namespace android
diff --git a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
index ff6df2c..5db9258 100644
--- a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
+++ b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -29,6 +29,6 @@
 #adb shell /data/nativetest64/AdjustableMaxPriorityQueue_tests/AdjustableMaxPriorityQueue_tests
 adb shell /data/nativetest/AdjustableMaxPriorityQueue_tests/AdjustableMaxPriorityQueue_tests
 
-echo "testing TranscodingJobScheduler"
-#adb shell /data/nativetest64/TranscodingJobScheduler_tests/TranscodingJobScheduler_tests
-adb shell /data/nativetest/TranscodingJobScheduler_tests/TranscodingJobScheduler_tests
+echo "testing TranscodingSessionController"
+#adb shell /data/nativetest64/TranscodingSessionController_tests/TranscodingSessionController_tests
+adb shell /data/nativetest/TranscodingSessionController_tests/TranscodingSessionController_tests
diff --git a/media/libmediatranscoding/transcoder/NdkCommon.cpp b/media/libmediatranscoding/transcoder/NdkCommon.cpp
index e58330f..a7b79dc 100644
--- a/media/libmediatranscoding/transcoder/NdkCommon.cpp
+++ b/media/libmediatranscoding/transcoder/NdkCommon.cpp
@@ -73,4 +73,18 @@
         }
     }
 }
+
+#define DEFINE_SET_DEFAULT_FORMAT_VALUE_FUNC(_type, _typeName)                                  \
+    bool SetDefaultFormatValue##_typeName(const char* key, AMediaFormat* format, _type value) { \
+        _type tmp;                                                                              \
+        if (!AMediaFormat_get##_typeName(format, key, &tmp)) {                                  \
+            AMediaFormat_set##_typeName(format, key, value);                                    \
+            return true;                                                                        \
+        }                                                                                       \
+        return false;                                                                           \
+    }
+
+DEFINE_SET_DEFAULT_FORMAT_VALUE_FUNC(float, Float);
+DEFINE_SET_DEFAULT_FORMAT_VALUE_FUNC(int32_t, Int32);
+
 }  // namespace AMediaFormatUtils
\ No newline at end of file
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 0713eb8..4cf54f1 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -22,6 +22,8 @@
 #include <media/VideoTrackTranscoder.h>
 #include <utils/AndroidThreads.h>
 
+using namespace AMediaFormatUtils;
+
 namespace android {
 
 // Check that the codec sample flags have the expected NDK meaning.
@@ -36,6 +38,12 @@
 static constexpr int32_t kColorFormatSurface = 0x7f000789;
 // Default key frame interval in seconds.
 static constexpr float kDefaultKeyFrameIntervalSeconds = 1.0f;
+// Default codec operating rate.
+static constexpr int32_t kDefaultCodecOperatingRate = 240;
+// Default codec priority.
+static constexpr int32_t kDefaultCodecPriority = 1;
+// Default bitrate, in case source estimation fails.
+static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
 
 template <typename T>
 void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
@@ -176,8 +184,6 @@
 // Creates and configures the codecs.
 media_status_t VideoTrackTranscoder::configureDestinationFormat(
         const std::shared_ptr<AMediaFormat>& destinationFormat) {
-    static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
-
     media_status_t status = AMEDIA_OK;
 
     if (destinationFormat == nullptr) {
@@ -203,11 +209,12 @@
         AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, bitrate);
     }
 
-    float tmp;
-    if (!AMediaFormat_getFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, &tmp)) {
-        AMediaFormat_setFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL,
-                              kDefaultKeyFrameIntervalSeconds);
-    }
+    SetDefaultFormatValueFloat(AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, encoderFormat,
+                               kDefaultKeyFrameIntervalSeconds);
+    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat,
+                               kDefaultCodecOperatingRate);
+    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+
     AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
 
     // Always encode without rotation. The rotation degree will be transferred directly to
@@ -271,13 +278,13 @@
     AMediaFormat_setInt32(decoderFormat.get(), TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP, 0);
 
     // Copy over configurations that apply to both encoder and decoder.
-    static const AMediaFormatUtils::EntryCopier kEncoderEntriesToCopy[] = {
+    static const EntryCopier kEncoderEntriesToCopy[] = {
             ENTRY_COPIER2(AMEDIAFORMAT_KEY_OPERATING_RATE, Float, Int32),
             ENTRY_COPIER(AMEDIAFORMAT_KEY_PRIORITY, Int32),
     };
     const size_t entryCount = sizeof(kEncoderEntriesToCopy) / sizeof(kEncoderEntriesToCopy[0]);
-    AMediaFormatUtils::CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(),
-                                         kEncoderEntriesToCopy, entryCount);
+    CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy,
+                      entryCount);
 
     status = AMediaCodec_configure(mDecoder, decoderFormat.get(), mSurface, NULL /* crypto */,
                                    0 /* flags */);
@@ -480,7 +487,7 @@
     androidSetThreadPriority(0 /* tid (0 = current) */, ANDROID_PRIORITY_VIDEO);
 
     // Push start decoder and encoder as two messages, so that these are subject to the
-    // stop request as well. If the job is cancelled (or paused) immediately after start,
+    // stop request as well. If the session is cancelled (or paused) immediately after start,
     // we don't need to waste time start then stop the codecs.
     mCodecMessageQueue.push([this] {
         media_status_t status = AMediaCodec_start(mDecoder);
diff --git a/media/libmediatranscoding/transcoder/benchmark/Android.bp b/media/libmediatranscoding/transcoder/benchmark/Android.bp
index c9a7b57..ce34702 100644
--- a/media/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -1,6 +1,6 @@
 cc_defaults {
     name: "benchmarkdefaults",
-    shared_libs: ["libmediatranscoder", "libmediandk", "libbase"],
+    shared_libs: ["libmediatranscoder", "libmediandk", "libbase", "libbinder_ndk"],
     static_libs: ["libgoogle-benchmark"],
 }
 
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
index e15186c..aee0ed6 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
@@ -33,6 +33,7 @@
 #define LOG_TAG "MediaTrackTranscoderBenchmark"
 
 #include <android-base/logging.h>
+#include <android/binder_process.h>
 #include <benchmark/benchmark.h>
 #include <fcntl.h>
 #include <media/MediaSampleReader.h>
@@ -191,7 +192,7 @@
         auto& p = mSamples[mCurrentSampleIndex % mSamples.size()];
 
         if (bufferSize < p.second.size) return AMEDIA_ERROR_INVALID_PARAMETER;
-        memcpy(buffer, p.first.get(), bufferSize);
+        memcpy(buffer, p.first.get(), p.second.size);
 
         advanceTrack(trackIndex);
         return AMEDIA_OK;
@@ -277,12 +278,19 @@
 }
 
 /**
+ * Callback to edit track format for transcoding.
+ * @param dstFormat The default track format for the track type.
+ */
+using TrackFormatEditCallback = std::function<void(AMediaFormat* dstFormat)>;
+
+/**
  * Configures a MediaTrackTranscoder with the provided MediaSampleReader, reading from the first
  * track that matches the specified media type.
  */
 static bool ConfigureSampleReader(const std::shared_ptr<MediaTrackTranscoder>& transcoder,
                                   const std::shared_ptr<MediaSampleReader>& sampleReader,
-                                  MediaType mediaType) {
+                                  MediaType mediaType,
+                                  const TrackFormatEditCallback& formatEditor) {
     int srcTrackIndex = -1;
     std::shared_ptr<AMediaFormat> srcTrackFormat = nullptr;
 
@@ -313,6 +321,9 @@
     }
 
     auto destinationFormat = GetDefaultTrackFormat(mediaType, srcTrackFormat.get());
+    if (formatEditor != nullptr) {
+        formatEditor(destinationFormat.get());
+    }
     status = transcoder->configure(sampleReader, srcTrackIndex, destinationFormat);
     if (status != AMEDIA_OK) {
         LOG(ERROR) << "transcoder configure returned " << status;
@@ -323,7 +334,11 @@
 }
 
 static void BenchmarkTranscoder(benchmark::State& state, const std::string& srcFileName,
-                                bool mockReader, MediaType mediaType) {
+                                bool mockReader, MediaType mediaType,
+                                const TrackFormatEditCallback& formatEditor = nullptr) {
+    static pthread_once_t once = PTHREAD_ONCE_INIT;
+    pthread_once(&once, ABinderProcess_startThreadPool);
+
     for (auto _ : state) {
         std::shared_ptr<TrackTranscoderCallbacks> callbacks =
                 std::make_shared<TrackTranscoderCallbacks>();
@@ -341,7 +356,7 @@
             return;
         }
 
-        if (!ConfigureSampleReader(transcoder, sampleReader, mediaType)) {
+        if (!ConfigureSampleReader(transcoder, sampleReader, mediaType, formatEditor)) {
             state.SkipWithError("Unable to configure the transcoder");
             return;
         }
@@ -367,33 +382,65 @@
     }
 }
 
+static void BenchmarkTranscoderWithOperatingRate(benchmark::State& state,
+                                                 const std::string& srcFile, bool mockReader,
+                                                 MediaType mediaType) {
+    TrackFormatEditCallback editor;
+    const int32_t operatingRate = state.range(0);
+    const int32_t priority = state.range(1);
+
+    if (operatingRate >= 0 && priority >= 0) {
+        editor = [operatingRate, priority](AMediaFormat* format) {
+            AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_OPERATING_RATE, operatingRate);
+            AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PRIORITY, priority);
+        };
+    }
+    BenchmarkTranscoder(state, srcFile, mockReader, mediaType, editor);
+}
+
+//-------------------------------- AVC to AVC Benchmarks -------------------------------------------
+
+static void BM_VideoTranscode_AVC2AVC(benchmark::State& state) {
+    const char* srcFile = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4";
+    BenchmarkTranscoderWithOperatingRate(state, srcFile, false /* mockReader */, kVideo);
+}
+
+static void BM_VideoTranscode_AVC2AVC_NoExtractor(benchmark::State& state) {
+    const char* srcFile = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4";
+    BenchmarkTranscoderWithOperatingRate(state, srcFile, true /* mockReader */, kVideo);
+}
+
+//-------------------------------- HEVC to AVC Benchmarks ------------------------------------------
+
+static void BM_VideoTranscode_HEVC2AVC(benchmark::State& state) {
+    const char* srcFile = "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4";
+    BenchmarkTranscoderWithOperatingRate(state, srcFile, false /* mockReader */, kVideo);
+}
+
+static void BM_VideoTranscode_HEVC2AVC_NoExtractor(benchmark::State& state) {
+    const char* srcFile = "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4";
+    BenchmarkTranscoderWithOperatingRate(state, srcFile, true /* mockReader */, kVideo);
+}
+
+//-------------------------------- Benchmark Registration ------------------------------------------
+
 // Benchmark registration wrapper for transcoding.
 #define TRANSCODER_BENCHMARK(func) \
     BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
 
-static void BM_VideoTranscode_AVC2AVC_NoMuxer(benchmark::State& state) {
-    const char* srcFile = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4";
-    BenchmarkTranscoder(state, srcFile, false /* mockReader */, kVideo);
-}
+// Benchmark registration for testing different operating rate and priority combinations.
+#define TRANSCODER_OPERATING_RATE_BENCHMARK(func)  \
+    TRANSCODER_BENCHMARK(func)                     \
+            ->Args({-1, -1}) /* <-- Use default */ \
+            ->Args({240, 0})                       \
+            ->Args({INT32_MAX, 0})                 \
+            ->Args({240, 1})                       \
+            ->Args({INT32_MAX, 1})
 
-static void BM_VideoTranscode_AVC2AVC_NoMuxer_NoExtractor(benchmark::State& state) {
-    const char* srcFile = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4";
-    BenchmarkTranscoder(state, srcFile, true /* mockReader */, kVideo);
-}
+TRANSCODER_OPERATING_RATE_BENCHMARK(BM_VideoTranscode_AVC2AVC);
+TRANSCODER_OPERATING_RATE_BENCHMARK(BM_VideoTranscode_AVC2AVC_NoExtractor);
 
-static void BM_VideoTranscode_HEVC2AVC_NoMuxer(benchmark::State& state) {
-    const char* srcFile = "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4";
-    BenchmarkTranscoder(state, srcFile, false /* mockReader */, kVideo);
-}
-
-static void BM_VideoTranscode_HEVC2AVC_NoMuxer_NoExtractor(benchmark::State& state) {
-    const char* srcFile = "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4";
-    BenchmarkTranscoder(state, srcFile, true /* mockReader */, kVideo);
-}
-
-TRANSCODER_BENCHMARK(BM_VideoTranscode_AVC2AVC_NoMuxer);
-TRANSCODER_BENCHMARK(BM_VideoTranscode_AVC2AVC_NoMuxer_NoExtractor);
-TRANSCODER_BENCHMARK(BM_VideoTranscode_HEVC2AVC_NoMuxer);
-TRANSCODER_BENCHMARK(BM_VideoTranscode_HEVC2AVC_NoMuxer_NoExtractor);
+TRANSCODER_OPERATING_RATE_BENCHMARK(BM_VideoTranscode_HEVC2AVC);
+TRANSCODER_OPERATING_RATE_BENCHMARK(BM_VideoTranscode_HEVC2AVC_NoExtractor);
 
 BENCHMARK_MAIN();
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index f190453..f985a28 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -191,14 +191,24 @@
     if (dstFd > 0) close(dstFd);
 }
 
+/**
+ * Callback to edit track format for transcoding.
+ * @param dstFormat The default track format for the track type.
+ */
+using TrackFormatEditCallback = std::function<void(AMediaFormat* dstFormat)>;
+
 static void TranscodeMediaFile(benchmark::State& state, const std::string& srcFileName,
                                const std::string& dstFileName, bool includeAudio,
-                               bool transcodeVideo) {
+                               bool transcodeVideo,
+                               const TrackFormatEditCallback& videoFormatEditor = nullptr) {
     TranscodeMediaFile(state, srcFileName, dstFileName,
                        [=](const char* mime, AMediaFormat** dstFormatOut) -> bool {
                            *dstFormatOut = nullptr;
                            if (strncmp(mime, "video/", 6) == 0 && transcodeVideo) {
                                *dstFormatOut = CreateDefaultVideoFormat();
+                               if (videoFormatEditor != nullptr) {
+                                   videoFormatEditor(*dstFormatOut);
+                               }
                            } else if (strncmp(mime, "audio/", 6) == 0 && !includeAudio) {
                                return false;
                            }
@@ -206,9 +216,12 @@
                        });
 }
 
-// Benchmark registration wrapper for transcoding.
-#define TRANSCODER_BENCHMARK(func) \
-    BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
+static void SetMaxOperatingRate(AMediaFormat* format) {
+    AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_OPERATING_RATE, INT32_MAX);
+    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PRIORITY, 1);
+}
+
+//-------------------------------- AVC to AVC Benchmarks -------------------------------------------
 
 static void BM_TranscodeAvc2AvcAudioVideo2AudioVideo(benchmark::State& state) {
     TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
@@ -216,12 +229,6 @@
                        true /* includeAudio */, true /* transcodeVideo */);
 }
 
-static void BM_TranscodeAvc2AvcAudioVideo2Video(benchmark::State& state) {
-    TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
-                       "video_1920x1080_3648frame_h264_22Mbps_30fps_aac_transcoded_V.mp4",
-                       false /* includeAudio */, true /* transcodeVideo */);
-}
-
 static void BM_TranscodeAvc2AvcVideo2Video(benchmark::State& state) {
     TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps.mp4",
                        "video_1920x1080_3648frame_h264_22Mbps_30fps_transcoded_V.mp4",
@@ -231,35 +238,43 @@
 static void BM_TranscodeAvc2AvcAV2AVMaxOperatingRate(benchmark::State& state) {
     TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
                        "video_1920x1080_3648frame_h264_22Mbps_30fps_aac_transcoded_AV.mp4",
-                       [](const char* mime, AMediaFormat** dstFormatOut) -> bool {
-                           AMediaFormat* dstFormat = nullptr;
-                           if (strncmp(mime, "video/", 6) == 0) {
-                               dstFormat = CreateDefaultVideoFormat();
-                               AMediaFormat_setFloat(dstFormat, AMEDIAFORMAT_KEY_OPERATING_RATE,
-                                                     INT32_MAX);
-                               AMediaFormat_setInt32(dstFormat, AMEDIAFORMAT_KEY_PRIORITY, 1);
-                           }
-                           *dstFormatOut = dstFormat;
-                           return true;
-                       });
+                       true /* includeAudio */, true /* transcodeVideo */, SetMaxOperatingRate);
 }
 
 static void BM_TranscodeAvc2AvcV2VMaxOperatingRate(benchmark::State& state) {
     TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps.mp4",
                        "video_1920x1080_3648frame_h264_22Mbps_30fps_transcoded_V.mp4",
-                       [](const char* mime, AMediaFormat** dstFormatOut) -> bool {
-                           if (strncmp(mime, "video/", 6) == 0) {
-                               AMediaFormat* dstFormat = CreateDefaultVideoFormat();
-                               AMediaFormat_setFloat(dstFormat, AMEDIAFORMAT_KEY_OPERATING_RATE,
-                                                     INT32_MAX);
-                               AMediaFormat_setInt32(dstFormat, AMEDIAFORMAT_KEY_PRIORITY, 1);
-                               *dstFormatOut = dstFormat;
-                               return true;
-                           }
-                           return false;
-                       });
+                       false /* includeAudio */, true /* transcodeVideo */, SetMaxOperatingRate);
 }
 
+//-------------------------------- HEVC to AVC Benchmarks ------------------------------------------
+
+static void BM_TranscodeHevc2AvcAudioVideo2AudioVideo(benchmark::State& state) {
+    TranscodeMediaFile(state, "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4",
+                       "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac_transcoded_AV.mp4",
+                       true /* includeAudio */, true /* transcodeVideo */);
+}
+
+static void BM_TranscodeHevc2AvcVideo2Video(benchmark::State& state) {
+    TranscodeMediaFile(state, "video_1920x1080_3863frame_hevc_4Mbps_30fps.mp4",
+                       "video_1920x1080_3863frame_hevc_4Mbps_30fps_transcoded_V.mp4",
+                       false /* includeAudio */, true /* transcodeVideo */);
+}
+
+static void BM_TranscodeHevc2AvcAV2AVMaxOperatingRate(benchmark::State& state) {
+    TranscodeMediaFile(state, "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac.mp4",
+                       "video_1920x1080_3863frame_hevc_4Mbps_30fps_aac_transcoded_AV.mp4",
+                       true /* includeAudio */, true /* transcodeVideo */, SetMaxOperatingRate);
+}
+
+static void BM_TranscodeHevc2AvcV2VMaxOperatingRate(benchmark::State& state) {
+    TranscodeMediaFile(state, "video_1920x1080_3863frame_hevc_4Mbps_30fps.mp4",
+                       "video_1920x1080_3863frame_hevc_4Mbps_30fps_transcoded_V.mp4",
+                       false /* includeAudio */, true /* transcodeVideo */, SetMaxOperatingRate);
+}
+
+//-------------------------------- Passthrough Benchmarks ------------------------------------------
+
 static void BM_TranscodeAudioVideoPassthrough(benchmark::State& state) {
     TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
                        "video_1920x1080_3648frame_h264_22Mbps_30fps_aac_passthrough_AV.mp4",
@@ -271,11 +286,22 @@
                        false /* includeAudio */, false /* transcodeVideo */);
 }
 
+//-------------------------------- Benchmark Registration ------------------------------------------
+
+// Benchmark registration wrapper for transcoding.
+#define TRANSCODER_BENCHMARK(func) \
+    BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
+
 TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcAudioVideo2AudioVideo);
-TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcAudioVideo2Video);
 TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcVideo2Video);
 TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcAV2AVMaxOperatingRate);
 TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcV2VMaxOperatingRate);
+
+TRANSCODER_BENCHMARK(BM_TranscodeHevc2AvcAudioVideo2AudioVideo);
+TRANSCODER_BENCHMARK(BM_TranscodeHevc2AvcVideo2Video);
+TRANSCODER_BENCHMARK(BM_TranscodeHevc2AvcAV2AVMaxOperatingRate);
+TRANSCODER_BENCHMARK(BM_TranscodeHevc2AvcV2VMaxOperatingRate);
+
 TRANSCODER_BENCHMARK(BM_TranscodeAudioVideoPassthrough);
 TRANSCODER_BENCHMARK(BM_TranscodeVideoPassthrough);
 
diff --git a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
index 5e24049..1a72be3 100644
--- a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
+++ b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
@@ -78,5 +78,8 @@
 void CopyFormatEntries(AMediaFormat* from, AMediaFormat* to, const EntryCopier* entries,
                        size_t entryCount);
 
+bool SetDefaultFormatValueFloat(const char* key, AMediaFormat* format, float value);
+bool SetDefaultFormatValueInt32(const char* key, AMediaFormat* format, int32_t value);
+
 }  // namespace AMediaFormatUtils
 #endif  // ANDROID_MEDIA_TRANSCODING_NDK_COMMON_H
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 8fd9dfc..b9f9173 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -8311,17 +8311,38 @@
             FALLTHROUGH_INTENDED;
         }
         case kWhatResume:
-        case kWhatSetParameters:
         {
-            if (msg->what() == kWhatResume) {
-                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
-            }
+            ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
 
             mCodec->deferMessage(msg);
             handled = true;
             break;
         }
 
+        case kWhatSetParameters:
+        {
+            sp<AMessage> params;
+            CHECK(msg->findMessage("params", &params));
+
+            sp<ABuffer> hdr10PlusInfo;
+            if (params->findBuffer("hdr10-plus-info", &hdr10PlusInfo)) {
+                if (hdr10PlusInfo != nullptr && hdr10PlusInfo->size() > 0) {
+                    (void)mCodec->setHdr10PlusInfo(hdr10PlusInfo);
+                }
+                params->removeEntryAt(params->findEntryByName("hdr10-plus-info"));
+
+                if (params->countEntries() == 0) {
+                    msg->removeEntryAt(msg->findEntryByName("params"));
+                }
+            }
+
+            if (msg->countEntries() > 0) {
+                mCodec->deferMessage(msg);
+            }
+            handled = true;
+            break;
+        }
+
         case kWhatForceStateTransition:
         {
             int32_t generation = 0;
@@ -8432,6 +8453,15 @@
             return false;
         }
 
+        case OMX_EventConfigUpdate:
+        {
+            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
+
+            mCodec->onConfigUpdate((OMX_INDEXTYPE)data2);
+
+            return true;
+        }
+
         default:
             return BaseState::onOMXEvent(event, data1, data2);
     }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 19eb46f..1a4f3d3 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -318,7 +318,7 @@
 
 class MediaCodec::ReleaseSurface {
 public:
-    ReleaseSurface() {
+    explicit ReleaseSurface(uint64_t usage) {
         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
         mSurface = new Surface(mProducer, false /* controlledByApp */);
         struct ConsumerListener : public BnConsumerListener {
@@ -329,6 +329,7 @@
         sp<ConsumerListener> listener{new ConsumerListener};
         mConsumer->consumerConnect(listener, false);
         mConsumer->setConsumerName(String8{"MediaCodec.release"});
+        mConsumer->setConsumerUsageBits(usage);
     }
 
     const sp<Surface> &getSurface() {
@@ -2137,6 +2138,8 @@
                     }
 
                     bool sendErrorResponse = true;
+                    std::string origin{"kWhatError:"};
+                    origin += stateString(mState);
 
                     switch (mState) {
                         case INITIALIZING:
@@ -2188,14 +2191,14 @@
                                 // be a shutdown complete notification after
                                 // all.
 
-                                // note that we're directly going from
+                                // note that we may be directly going from
                                 // STOPPING->UNINITIALIZED, instead of the
                                 // usual STOPPING->INITIALIZED state.
                                 setState(UNINITIALIZED);
                                 if (mState == RELEASING) {
                                     mComponentName.clear();
                                 }
-                                postPendingRepliesAndDeferredMessages();
+                                postPendingRepliesAndDeferredMessages(origin + ":dead");
                                 sendErrorResponse = false;
                             }
                             break;
@@ -2286,7 +2289,7 @@
                             // released by ResourceManager.
                             finalErr = DEAD_OBJECT;
                         }
-                        postPendingRepliesAndDeferredMessages(finalErr);
+                        postPendingRepliesAndDeferredMessages(origin, finalErr);
                     }
                     break;
                 }
@@ -2334,7 +2337,7 @@
                                 MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
                     }
 
-                    postPendingRepliesAndDeferredMessages();
+                    postPendingRepliesAndDeferredMessages("kWhatComponentAllocated");
                     break;
                 }
 
@@ -2373,7 +2376,7 @@
                         mFlags |= kFlagUsesSoftwareRenderer;
                     }
                     setState(CONFIGURED);
-                    postPendingRepliesAndDeferredMessages();
+                    postPendingRepliesAndDeferredMessages("kWhatComponentConfigured");
 
                     // augment our media metrics info, now that we know more things
                     // such as what the codec extracted from any CSD passed in.
@@ -2442,7 +2445,7 @@
                     } else {
                         response->setInt32("err", err);
                     }
-                    postPendingRepliesAndDeferredMessages(response);
+                    postPendingRepliesAndDeferredMessages("kWhatInputSurfaceCreated", response);
                     break;
                 }
 
@@ -2464,7 +2467,7 @@
                     } else {
                         response->setInt32("err", err);
                     }
-                    postPendingRepliesAndDeferredMessages(response);
+                    postPendingRepliesAndDeferredMessages("kWhatInputSurfaceAccepted", response);
                     break;
                 }
 
@@ -2482,7 +2485,7 @@
                     if (msg->findInt32("err", &err)) {
                         response->setInt32("err", err);
                     }
-                    postPendingRepliesAndDeferredMessages(response);
+                    postPendingRepliesAndDeferredMessages("kWhatSignaledInputEOS", response);
                     break;
                 }
 
@@ -2502,7 +2505,7 @@
                                 MediaResource::GraphicMemoryResource(getGraphicBufferSize()));
                     }
                     setState(STARTED);
-                    postPendingRepliesAndDeferredMessages();
+                    postPendingRepliesAndDeferredMessages("kWhatStartCompleted");
                     break;
                 }
 
@@ -2639,7 +2642,13 @@
                         break;
                     }
                     setState(INITIALIZED);
-                    postPendingRepliesAndDeferredMessages();
+                    if (mReplyID) {
+                        postPendingRepliesAndDeferredMessages("kWhatStopCompleted");
+                    } else {
+                        ALOGW("kWhatStopCompleted: presumably an error occurred earlier, "
+                              "but the operation completed anyway. (last reply origin=%s)",
+                              mLastReplyOrigin.c_str());
+                    }
                     break;
                 }
 
@@ -2664,7 +2673,7 @@
                     mReleaseSurface.reset();
 
                     if (mReplyID != nullptr) {
-                        postPendingRepliesAndDeferredMessages();
+                        postPendingRepliesAndDeferredMessages("kWhatReleaseCompleted");
                     }
                     if (mAsyncReleaseCompleteNotification != nullptr) {
                         flushMediametrics();
@@ -2689,7 +2698,7 @@
                         mCodec->signalResume();
                     }
 
-                    postPendingRepliesAndDeferredMessages();
+                    postPendingRepliesAndDeferredMessages("kWhatFlushCompleted");
                     break;
                 }
 
@@ -3080,7 +3089,8 @@
             if (mState == FLUSHING || mState == STOPPING
                     || mState == CONFIGURING || mState == STARTING) {
                 // mReply is always set if in these states.
-                postPendingRepliesAndDeferredMessages();
+                postPendingRepliesAndDeferredMessages(
+                        std::string("kWhatRelease:") + stateString(mState));
             }
 
             if (mFlags & kFlagSawMediaServerDie) {
@@ -3108,7 +3118,11 @@
             if (asyncNotify != nullptr) {
                 if (mSurface != NULL) {
                     if (!mReleaseSurface) {
-                        mReleaseSurface.reset(new ReleaseSurface);
+                        uint64_t usage = 0;
+                        if (mSurface->getConsumerUsage(&usage) != OK) {
+                            usage = 0;
+                        }
+                        mReleaseSurface.reset(new ReleaseSurface(usage));
                     }
                     if (mSurface != mReleaseSurface->getSurface()) {
                         status_t err = connectToSurface(mReleaseSurface->getSurface());
@@ -3129,7 +3143,7 @@
                 // State transition replies are handled above, so this reply
                 // would not be related to state transition. As we are
                 // shutting down the component, just fail the operation.
-                postPendingRepliesAndDeferredMessages(UNKNOWN_ERROR);
+                postPendingRepliesAndDeferredMessages("kWhatRelease:reply", UNKNOWN_ERROR);
             }
             mReplyID = replyID;
             setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
@@ -3145,7 +3159,7 @@
 
             if (asyncNotify != nullptr) {
                 mResourceManagerProxy->markClientForPendingRemoval();
-                postPendingRepliesAndDeferredMessages();
+                postPendingRepliesAndDeferredMessages("kWhatRelease:async");
                 asyncNotifyPost.clear();
                 mAsyncReleaseCompleteNotification = asyncNotify;
             }
@@ -4332,16 +4346,23 @@
     return OK;
 }
 
-void MediaCodec::postPendingRepliesAndDeferredMessages(status_t err /* = OK */) {
+void MediaCodec::postPendingRepliesAndDeferredMessages(
+        std::string origin, status_t err /* = OK */) {
     sp<AMessage> response{new AMessage};
     if (err != OK) {
         response->setInt32("err", err);
     }
-    postPendingRepliesAndDeferredMessages(response);
+    postPendingRepliesAndDeferredMessages(origin, response);
 }
 
-void MediaCodec::postPendingRepliesAndDeferredMessages(const sp<AMessage> &response) {
-    CHECK(mReplyID);
+void MediaCodec::postPendingRepliesAndDeferredMessages(
+        std::string origin, const sp<AMessage> &response) {
+    LOG_ALWAYS_FATAL_IF(
+            !mReplyID,
+            "postPendingRepliesAndDeferredMessages: mReplyID == null, from %s following %s",
+            origin.c_str(),
+            mLastReplyOrigin.c_str());
+    mLastReplyOrigin = origin;
     response->postReply(mReplyID);
     mReplyID.clear();
     ALOGV_IF(!mDeferredMessages.empty(),
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 050d7c2..6245014 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -312,6 +312,27 @@
         (*format)->setBuffer("pssh", buf);
     }
 
+    // Copy over the slow-motion related metadata
+    const void *slomoMarkers;
+    size_t slomoMarkersSize;
+    if (meta->findData(kKeySlowMotionMarkers, &type, &slomoMarkers, &slomoMarkersSize)
+            && slomoMarkersSize > 0) {
+        sp<ABuffer> buf = new ABuffer(slomoMarkersSize);
+        memcpy(buf->data(), slomoMarkers, slomoMarkersSize);
+        (*format)->setBuffer("slow-motion-markers", buf);
+    }
+
+    int32_t temporalLayerCount;
+    if (meta->findInt32(kKeyTemporalLayerCount, &temporalLayerCount)
+            && temporalLayerCount > 0) {
+        (*format)->setInt32("temporal-layer-count", temporalLayerCount);
+    }
+
+    float captureFps;
+    if (meta->findFloat(kKeyCaptureFramerate, &captureFps) && captureFps > 0.0f) {
+        (*format)->setFloat("capture-rate", captureFps);
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 6446857..3d152bc 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -2143,8 +2143,10 @@
     }
     info->sample_rate = srate;
 
-    int32_t cmask = 0;
-    if (!meta->findInt32(kKeyChannelMask, &cmask) || cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
+    int32_t rawChannelMask;
+    audio_channel_mask_t cmask = meta->findInt32(kKeyChannelMask, &rawChannelMask) ?
+            static_cast<audio_channel_mask_t>(rawChannelMask) : CHANNEL_MASK_USE_CHANNEL_ORDER;
+    if (cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
         ALOGV("track of type '%s' does not publish channel mask", mime);
 
         // Try a channel count instead
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index 73a1d4b..ff9a720 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -81,6 +81,13 @@
     //},
 
     shared_libs: ["libstagefright_amrnb_common"],
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp b/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
index e1af6d4..d960322 100644
--- a/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
+++ b/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
@@ -273,9 +273,10 @@
 
         L_tmp1 >>= 11;      /* -4 : sig_lo[i] << 4 */
 
-        L_tmp1 += (int32)exc[(i<<1)] << a0;
+        int64 sig_tmp;
+        sig_tmp = (int64)L_tmp1 + (int32)(exc[(i<<1)] << a0);
+        L_tmp1 = (int32)(sig_tmp - (L_tmp2 << 1));
 
-        L_tmp1 -= (L_tmp2 << 1);
         /* sig_hi = bit16 to bit31 of synthesis */
         L_tmp1 = shl_int32(L_tmp1, 3);           /* ai in Q12 */
 
@@ -290,9 +291,8 @@
         L_tmp3 = fxp_mac_16by16(sig_lo[(i<<1)], a[1], L_tmp3);
         L_tmp3 = -L_tmp3 >> 11;
 
-        L_tmp3 += (int32)exc[(i<<1)+1] << a0;
-
-        L_tmp3 -= (L_tmp4 << 1);
+        sig_tmp = (int64)L_tmp3 + (int32)(exc[(i<<1)+1] << a0);
+        L_tmp3 = (int32)(sig_tmp - (L_tmp4 << 1));
         /* sig_hi = bit16 to bit31 of synthesis */
         L_tmp3 = shl_int32(L_tmp3, 3);           /* ai in Q12 */
         sig_hi[(i<<1)+1] = (int16)(L_tmp3 >> 16);
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index 64f302c..70c672d 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -138,6 +138,12 @@
         cfi: true,
     },
 
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
diff --git a/media/libstagefright/codecs/amrwbenc/src/preemph.c b/media/libstagefright/codecs/amrwbenc/src/preemph.c
index 70c8650..a43841a 100644
--- a/media/libstagefright/codecs/amrwbenc/src/preemph.c
+++ b/media/libstagefright/codecs/amrwbenc/src/preemph.c
@@ -24,6 +24,7 @@
 
 #include "typedef.h"
 #include "basic_op.h"
+#include <stdint.h>
 
 void Preemph(
         Word16 x[],                           /* (i/o)   : input signal overwritten by the output */
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
index fe0bdda..657b6fe 100644
--- a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
+++ b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
@@ -27,6 +27,7 @@
 #include "q_pulse.h"
 
 #define NB_POS 16                          /* pos in track, mask for sign bit */
+#define UNUSED_VAR __attribute__((unused))
 
 Word32 quant_1p_N1(                        /* (o) return N+1 bits             */
         Word16 pos,                        /* (i) position of the pulse       */
@@ -188,7 +189,7 @@
         Word16 pos[],                         /* (i) position of the pulse 1..4  */
         Word16 N)                             /* (i) number of bits for position */
 {
-    Word16 nb_pos, mask __unused, n_1, tmp;
+    Word16 nb_pos, mask UNUSED_VAR, n_1, tmp;
     Word16 posA[4], posB[4];
     Word32 i, j, k, index;
 
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/libstagefright/codecs/common/Android.bp
index 260a60a..2290722 100644
--- a/media/libstagefright/codecs/common/Android.bp
+++ b/media/libstagefright/codecs/common/Android.bp
@@ -14,4 +14,11 @@
     export_include_dirs: ["include"],
 
     cflags: ["-Werror"],
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index c64cf46..a5c7f5e 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -219,11 +219,6 @@
 
     if (info->error_protection)
     {
-        if (bitsAvailable(&pVars->inputStream, 16))
-        {
-            return SIDE_INFO_ERROR;
-        }
-
         /*
          *  Get crc content
          */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index 1a3fca5..d644207 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -73,7 +73,6 @@
 
 #include "pvmp3_get_side_info.h"
 #include "pvmp3_crc.h"
-#include "pvmp3_getbits.h"
 
 
 /*----------------------------------------------------------------------------
@@ -126,22 +125,12 @@
     {
         if (stereo == 1)
         {
-            if (!bitsAvailable(inputStream, 14))
-            {
-                return SIDE_INFO_ERROR;
-            }
-
             tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
             si->main_data_begin = (tmp << 18) >> 23;    /* 9 */
             si->private_bits    = (tmp << 27) >> 27;    /* 5 */
         }
         else
         {
-            if (!bitsAvailable(inputStream, 12))
-            {
-                return SIDE_INFO_ERROR;
-            }
-
             tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
             si->main_data_begin = (tmp << 20) >> 23;    /* 9 */
             si->private_bits    = (tmp << 29) >> 29;    /* 3 */
@@ -150,11 +139,6 @@
 
         for (ch = 0; ch < stereo; ch++)
         {
-            if (!bitsAvailable(inputStream, 4))
-            {
-                return SIDE_INFO_ERROR;
-            }
-
             tmp = getbits_crc(inputStream, 4, crc, info->error_protection);
             si->ch[ch].scfsi[0] = (tmp << 28) >> 31;    /* 1 */
             si->ch[ch].scfsi[1] = (tmp << 29) >> 31;    /* 1 */
@@ -166,11 +150,6 @@
         {
             for (ch = 0; ch < stereo; ch++)
             {
-                if (!bitsAvailable(inputStream, 34))
-                {
-                    return SIDE_INFO_ERROR;
-                }
-
                 si->ch[ch].gran[gr].part2_3_length    = getbits_crc(inputStream, 12, crc, info->error_protection);
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
@@ -181,11 +160,6 @@
 
                 if (si->ch[ch].gran[gr].window_switching_flag)
                 {
-                    if (!bitsAvailable(inputStream, 22))
-                    {
-                        return SIDE_INFO_ERROR;
-                    }
-
                     tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                     si->ch[ch].gran[gr].block_type       = (tmp << 10) >> 30;   /* 2 */;
@@ -218,11 +192,6 @@
                 }
                 else
                 {
-                    if (!bitsAvailable(inputStream, 22))
-                    {
-                        return SIDE_INFO_ERROR;
-                    }
-
                     tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                     si->ch[ch].gran[gr].table_select[0] = (tmp << 10) >> 27;   /* 5 */;
@@ -235,11 +204,6 @@
                     si->ch[ch].gran[gr].block_type      = 0;
                 }
 
-                if (!bitsAvailable(inputStream, 3))
-                {
-                    return SIDE_INFO_ERROR;
-                }
-
                 tmp = getbits_crc(inputStream, 3, crc, info->error_protection);
                 si->ch[ch].gran[gr].preflag            = (tmp << 29) >> 31;    /* 1 */
                 si->ch[ch].gran[gr].scalefac_scale     = (tmp << 30) >> 31;    /* 1 */
@@ -249,21 +213,11 @@
     }
     else /* Layer 3 LSF */
     {
-        if (!bitsAvailable(inputStream, 8 + stereo))
-        {
-            return SIDE_INFO_ERROR;
-        }
-
         si->main_data_begin = getbits_crc(inputStream,      8, crc, info->error_protection);
         si->private_bits    = getbits_crc(inputStream, stereo, crc, info->error_protection);
 
         for (ch = 0; ch < stereo; ch++)
         {
-            if (!bitsAvailable(inputStream, 39))
-            {
-                return SIDE_INFO_ERROR;
-            }
-
             tmp = getbits_crc(inputStream, 21, crc, info->error_protection);
             si->ch[ch].gran[0].part2_3_length    = (tmp << 11) >> 20;  /* 12 */
             si->ch[ch].gran[0].big_values        = (tmp << 23) >> 23;  /*  9 */
@@ -276,11 +230,6 @@
             if (si->ch[ch].gran[0].window_switching_flag)
             {
 
-                if (!bitsAvailable(inputStream, 22))
-                {
-                    return SIDE_INFO_ERROR;
-                }
-
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                 si->ch[ch].gran[0].block_type       = (tmp << 10) >> 30;   /* 2 */;
@@ -313,11 +262,6 @@
             }
             else
             {
-                if (!bitsAvailable(inputStream, 22))
-                {
-                    return SIDE_INFO_ERROR;
-                }
-
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                 si->ch[ch].gran[0].table_select[0] = (tmp << 10) >> 27;   /* 5 */;
@@ -330,11 +274,6 @@
                 si->ch[ch].gran[0].block_type      = 0;
             }
 
-            if (!bitsAvailable(inputStream, 2))
-            {
-                return SIDE_INFO_ERROR;
-            }
-
             tmp = getbits_crc(inputStream, 2, crc, info->error_protection);
             si->ch[ch].gran[0].scalefac_scale     =  tmp >> 1;  /* 1 */
             si->ch[ch].gran[0].count1table_select =  tmp & 1;  /* 1 */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
index 4d252ef..8ff7953 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
@@ -113,11 +113,10 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint32    bytesToFetch;
-    uint8     Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
-    uint8     Elem1 = 0;
-    uint8     Elem2 = 0;
-    uint8     Elem3 = 0;
+    uint8     Elem;         /* Needs to be same type as pInput->pBuffer */
+    uint8     Elem1;
+    uint8     Elem2;
+    uint8     Elem3;
     uint32   returnValue = 0;
 
     if (!neededBits)
@@ -127,25 +126,10 @@
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
-    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
-
-    switch (bytesToFetch)
-    {
-    case 4:
-        Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
-        [[fallthrough]];
-    case 3:
-        Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
-        [[fallthrough]];
-    case 2:
-        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-        [[fallthrough]];
-    case 1:
-        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-    }
+    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
+    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+    Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+    Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
 
 
     returnValue = (((uint32)(Elem)) << 24) |
@@ -153,6 +137,9 @@
                   (((uint32)(Elem2)) << 8) |
                   ((uint32)(Elem3));
 
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
     /* This line is faster than to mask off the high bits. */
     returnValue <<= bitIndex;
 
@@ -174,32 +161,22 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint32    bytesToFetch;
-    uint8    Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
-    uint8    Elem1 = 0;
+    uint8    Elem;         /* Needs to be same type as pInput->pBuffer */
+    uint8    Elem1;
     uint16   returnValue;
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
-    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
-
-    if (bytesToFetch > 1)
-    {
-        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-    }
-    else if (bytesToFetch > 0)
-    {
-        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-    }
+    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
+    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
 
 
     returnValue = (((uint16)(Elem)) << 8) |
                   ((uint16)(Elem1));
 
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
     ptBitStream->usedBits += neededBits;
     /* This line is faster than to mask off the high bits. */
     returnValue = (returnValue << (bitIndex));
@@ -220,40 +197,25 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint32    bytesToFetch;
-    uint8     Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
-    uint8     Elem1 = 0;
-    uint8     Elem2 = 0;
+    uint8     Elem;         /* Needs to be same type as pInput->pBuffer */
+    uint8     Elem1;
+    uint8     Elem2;
     uint32   returnValue;
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
-    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
-
-    if (bytesToFetch > 2)
-    {
-        Elem  = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-        Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
-    }
-    else if (bytesToFetch > 1)
-    {
-        Elem  = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-    }
-    else if (bytesToFetch > 0)
-    {
-        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
-    }
+    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
+    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+    Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
 
 
     returnValue = (((uint32)(Elem)) << 16) |
                   (((uint32)(Elem1)) << 8) |
                   ((uint32)(Elem2));
 
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
     ptBitStream->usedBits += neededBits;
     /* This line is faster than to mask off the high bits. */
     returnValue = 0xFFFFFF & (returnValue << (bitIndex));
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
index b04fe6d..b058b00 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
@@ -104,11 +104,6 @@
 ; Function Prototype declaration
 ----------------------------------------------------------------------------*/
 
-static inline bool bitsAvailable(tmp3Bits *inputStream, uint32 neededBits)
-{
-    return (inputStream->inputBufferCurrentLength << 3) >= (neededBits + inputStream->usedBits);
-}
-
 /*----------------------------------------------------------------------------
 ; END
 ----------------------------------------------------------------------------*/
diff --git a/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
index 233f9bb..29952eb 100644
--- a/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
+++ b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
         <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.1.zip?unzip=true"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true"
             value="/data/local/tmp/Mp3DecoderTestRes/" />
     </target_preparer>
 
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
index 0784c0c..91326a8 100644
--- a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
+++ b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -186,6 +186,7 @@
                          ::testing::Values(("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3"),
                                            ("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3"),
                                            ("bug_136053885.mp3"),
+                                           ("bbb_2ch_44kHz_lame_crc.mp3"),
                                            ("bbb_mp3_stereo_192kbps_48000hz.mp3")));
 
 int main(int argc, char **argv) {
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index e97f6eb..5509512 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -813,10 +813,6 @@
                 baseSize = U32_AT(&mParent.mData[mOffset + 4]);
             }
 
-            if (baseSize == 0) {
-                return;
-            }
-
             // Prevent integer overflow when adding
             if (SIZE_MAX - 10 <= baseSize) {
                 return;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index ec853e9..c246b36 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -373,6 +373,7 @@
     AString mOwnerName;
     sp<MediaCodecInfo> mCodecInfo;
     sp<AReplyToken> mReplyID;
+    std::string mLastReplyOrigin;
     std::vector<sp<AMessage>> mDeferredMessages;
     uint32_t mFlags;
     status_t mStickyError;
@@ -498,8 +499,8 @@
     bool hasPendingBuffer(int portIndex);
     bool hasPendingBuffer();
 
-    void postPendingRepliesAndDeferredMessages(status_t err = OK);
-    void postPendingRepliesAndDeferredMessages(const sp<AMessage> &response);
+    void postPendingRepliesAndDeferredMessages(std::string origin, status_t err = OK);
+    void postPendingRepliesAndDeferredMessages(std::string origin, const sp<AMessage> &response);
 
     /* called to get the last codec error when the sticky flag is set.
      * if no such codec error is found, returns UNKNOWN_ERROR.
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 801dba1..192ba77 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1430,7 +1430,13 @@
                 if (mSampleDecryptor != NULL && (nalType == 1 || nalType == 5)) {
                     uint8_t *nalData = mBuffer->data() + pos.nalOffset;
                     size_t newSize = mSampleDecryptor->processNal(nalData, pos.nalSize);
-                    // Note: the data can shrink due to unescaping
+                    // Note: the data can shrink due to unescaping, but it can never grow
+                    if (newSize > pos.nalSize) {
+                        // don't log unless verbose, since this can get called a lot if
+                        // the caller is trying to resynchronize
+                        ALOGV("expected sample size < %u, got %zu", pos.nalSize, newSize);
+                        return NULL;
+                    }
                     memcpy(accessUnit->data() + dstOffset + 4,
                             nalData,
                             newSize);
diff --git a/media/libstagefright/tests/mediacodec/Android.bp b/media/libstagefright/tests/mediacodec/Android.bp
index 006864e..0bd0639 100644
--- a/media/libstagefright/tests/mediacodec/Android.bp
+++ b/media/libstagefright/tests/mediacodec/Android.bp
@@ -23,7 +23,12 @@
         "MediaTestHelper.cpp",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
+        "libgui",
         "libmedia",
         "libmedia_codeclist",
         "libmediametrics",
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
index baa86c1..d00a50f 100644
--- a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -20,6 +20,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include <gui/Surface.h>
+#include <mediadrm/ICrypto.h>
 #include <media/stagefright/CodecBase.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecListWriter.h>
@@ -152,6 +154,37 @@
 using namespace android;
 using ::testing::_;
 
+static sp<MediaCodec> SetupMediaCodec(
+        const AString &owner,
+        const AString &codecName,
+        const AString &mediaType,
+        const sp<ALooper> &looper,
+        std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase) {
+    std::shared_ptr<MediaCodecListWriter> listWriter =
+        MediaTestHelper::CreateCodecListWriter();
+    std::unique_ptr<MediaCodecInfoWriter> infoWriter = listWriter->addMediaCodecInfo();
+    infoWriter->setName(codecName.c_str());
+    infoWriter->setOwner(owner.c_str());
+    infoWriter->addMediaType(mediaType.c_str());
+    std::vector<sp<MediaCodecInfo>> codecInfos;
+    MediaTestHelper::WriteCodecInfos(listWriter, &codecInfos);
+    std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo =
+        [codecInfos](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+            auto it = std::find_if(
+                    codecInfos.begin(), codecInfos.end(),
+                    [&name](const sp<MediaCodecInfo> &info) {
+                        return name.equalsIgnoreCase(info->getCodecName());
+                    });
+
+            *info = (it == codecInfos.end()) ? nullptr : *it;
+            return (*info) ? OK : NAME_NOT_FOUND;
+        };
+
+    looper->start();
+    return MediaTestHelper::CreateCodec(
+            codecName, looper, getCodecBase, getCodecInfo);
+}
+
 TEST(MediaCodecTest, ReclaimReleaseRace) {
     // Test scenario:
     //
@@ -202,30 +235,9 @@
             return mockCodec;
         };
 
-    std::shared_ptr<MediaCodecListWriter> listWriter =
-        MediaTestHelper::CreateCodecListWriter();
-    std::unique_ptr<MediaCodecInfoWriter> infoWriter = listWriter->addMediaCodecInfo();
-    infoWriter->setName(kCodecName.c_str());
-    infoWriter->setOwner(kCodecOwner.c_str());
-    infoWriter->addMediaType(kMediaType.c_str());
-    std::vector<sp<MediaCodecInfo>> codecInfos;
-    MediaTestHelper::WriteCodecInfos(listWriter, &codecInfos);
-    std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo =
-        [codecInfos](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
-            auto it = std::find_if(
-                    codecInfos.begin(), codecInfos.end(),
-                    [&name](const sp<MediaCodecInfo> &info) {
-                        return name.equalsIgnoreCase(info->getCodecName());
-                    });
-
-            *info = (it == codecInfos.end()) ? nullptr : *it;
-            return (*info) ? OK : NAME_NOT_FOUND;
-        };
-
     sp<ALooper> looper{new ALooper};
-    looper->start();
-    sp<MediaCodec> codec = MediaTestHelper::CreateCodec(
-            kCodecName, looper, getCodecBase, getCodecInfo);
+    sp<MediaCodec> codec = SetupMediaCodec(
+            kCodecOwner, kCodecName, kMediaType, looper, getCodecBase);
     ASSERT_NE(nullptr, codec) << "Codec must not be null";
     ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
     std::promise<void> reclaimCompleted;
@@ -266,3 +278,73 @@
         << "release timed out";
     looper->stop();
 }
+
+TEST(MediaCodecTest, ErrorWhileStopping) {
+    // Test scenario:
+    //
+    // 1) Client thread calls stop(); MediaCodec looper thread calls
+    //    initiateShutdown(); shutdown is being handled at the component thread.
+    // 2) Error occurred, but the shutdown operation is still being done.
+    // 3) MediaCodec looper thread handles the error.
+    // 4) Component thread completes shutdown and posts onStopCompleted()
+
+    static const AString kCodecName{"test.codec"};
+    static const AString kCodecOwner{"nobody"};
+    static const AString kMediaType{"video/x-test"};
+
+    std::promise<void> errorOccurred;
+    sp<MockCodec> mockCodec;
+    std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
+        [&mockCodec, &errorOccurred](const AString &, const char *) {
+            mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
+                // No mock setup, as we don't expect any buffer operations
+                // in this scenario.
+            });
+            ON_CALL(*mockCodec, initiateAllocateComponent(_))
+                .WillByDefault([mockCodec](const sp<AMessage> &) {
+                    mockCodec->callback()->onComponentAllocated(kCodecName.c_str());
+                });
+            ON_CALL(*mockCodec, initiateConfigureComponent(_))
+                .WillByDefault([mockCodec](const sp<AMessage> &msg) {
+                    mockCodec->callback()->onComponentConfigured(
+                            msg->dup(), msg->dup());
+                });
+            ON_CALL(*mockCodec, initiateStart())
+                .WillByDefault([mockCodec]() {
+                    mockCodec->callback()->onStartCompleted();
+                });
+            ON_CALL(*mockCodec, initiateShutdown(true))
+                .WillByDefault([mockCodec, &errorOccurred](bool) {
+                    mockCodec->callback()->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+                    // Mark that 1) and 2) are complete.
+                    errorOccurred.set_value();
+                });
+            ON_CALL(*mockCodec, initiateShutdown(false))
+                .WillByDefault([mockCodec](bool) {
+                    mockCodec->callback()->onReleaseCompleted();
+                });
+            return mockCodec;
+        };
+
+    sp<ALooper> looper{new ALooper};
+    sp<MediaCodec> codec = SetupMediaCodec(
+            kCodecOwner, kCodecName, kMediaType, looper, getCodecBase);
+    ASSERT_NE(nullptr, codec) << "Codec must not be null";
+    ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
+
+    std::thread([mockCodec, &errorOccurred]{
+        // Simulate component thread that handles stop()
+        errorOccurred.get_future().wait();
+        // Error occurred but shutdown request still got processed.
+        mockCodec->callback()->onStopCompleted();
+    }).detach();
+
+    codec->configure(new AMessage, nullptr, nullptr, 0);
+    codec->start();
+    codec->stop();
+    // Sleep here to give time for the MediaCodec looper thread
+    // to process the messages.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    codec->release();
+    looper->stop();
+}
diff --git a/services/OWNERS b/services/OWNERS
index 66a4bcb..f0b5e2f 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -5,3 +5,5 @@
 gkasten@google.com
 hunga@google.com
 marcone@google.com
+nchalko@google.com
+quxiangfang@google.com
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fe45221..eae9437 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -197,7 +197,12 @@
         mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
     }
 
+#if 1
+    // FIXME See bug 165702394 and bug 168511485
+    const bool doLog = false;
+#else
     const bool doLog = property_get_bool("ro.test_harness", false);
+#endif
     if (doLog) {
         mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                 MemoryHeapBase::READ_ONLY);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9885655..14a4df7 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -407,7 +407,7 @@
         case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
             // Haptic channel mask is only applicable for channel position mask.
             const uint32_t channelCount = audio_channel_count_from_out_mask(
-                    channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
+                    static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
             const uint32_t maxChannelCount = kEnableExtendedChannels
                     ? AudioMixer::MAX_NUM_CHANNELS : FCC_2;
             if (channelCount < FCC_2 // mono is not supported at this time
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index c7aba79..0ce5681 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -39,7 +39,7 @@
         , mSpdifEncoder(this, format)
         , mApplicationFormat(AUDIO_FORMAT_DEFAULT)
         , mApplicationSampleRate(0)
-        , mApplicationChannelMask(0)
+        , mApplicationChannelMask(AUDIO_CHANNEL_NONE)
 {
 }
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 077447f..46969ef 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2897,8 +2897,8 @@
         (void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
     }
 
-    mHapticChannelMask = mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
-    mChannelMask &= ~mHapticChannelMask;
+    mHapticChannelMask = static_cast<audio_channel_mask_t>(mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+    mChannelMask = static_cast<audio_channel_mask_t>(mChannelMask & ~mHapticChannelMask);
     mHapticChannelCount = audio_channel_count_from_out_mask(mHapticChannelMask);
     mChannelCount -= mHapticChannelCount;
 
@@ -4247,7 +4247,7 @@
                             "Enumerated device type(%#x) must not be used "
                             "as it does not support audio patches",
                             patch->sinks[i].ext.device.type);
-        type |= patch->sinks[i].ext.device.type;
+        type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
         deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
                 patch->sinks[i].ext.device.address));
     }
@@ -4497,8 +4497,9 @@
         // wrap the source side of the MonoPipe to make it an AudioBufferProvider
         fastTrack->mBufferProvider = new SourceAudioBufferProvider(new MonoPipeReader(monoPipe));
         fastTrack->mVolumeProvider = NULL;
-        fastTrack->mChannelMask = mChannelMask | mHapticChannelMask; // mPipeSink channel mask for
-                                                                     // audio to FastMixer
+        fastTrack->mChannelMask = static_cast<audio_channel_mask_t>(
+                mChannelMask | mHapticChannelMask); // mPipeSink channel mask for
+                                                    // audio to FastMixer
         fastTrack->mFormat = mFormat; // mPipeSink format for audio to FastMixer
         fastTrack->mHapticPlaybackEnabled = mHapticChannelMask != AUDIO_CHANNEL_NONE;
         fastTrack->mHapticIntensity = os::HapticScale::NONE;
@@ -4512,7 +4513,8 @@
         // specify sink channel mask when haptic channel mask present as it can not
         // be calculated directly from channel count
         state->mSinkChannelMask = mHapticChannelMask == AUDIO_CHANNEL_NONE
-                ? AUDIO_CHANNEL_NONE : mChannelMask | mHapticChannelMask;
+                ? AUDIO_CHANNEL_NONE
+                : static_cast<audio_channel_mask_t>(mChannelMask | mHapticChannelMask);
         state->mCommand = FastMixerState::COLD_IDLE;
         // already done in constructor initialization list
         //mFastMixerFutex = 0;
@@ -9242,7 +9244,7 @@
                                 "Enumerated device type(%#x) must not be used "
                                 "as it does not support audio patches",
                                 patch->sinks[i].ext.device.type);
-            type |= patch->sinks[i].ext.device.type;
+            type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
             sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
                     patch->sinks[i].ext.device.address));
         }
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index a896157..b450e82 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -377,7 +377,7 @@
     if (isEmpty()) {
         // Return nullptr if this collection is empty.
         return nullptr;
-    } else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
+    } else if (areAllOfSameDeviceType(types(), audio_call_is_input_device)) {
         // For input case, return the first one when there is only one device.
         return size() > 1 ? nullptr : *begin();
     } else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 883e713..889f031 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -337,7 +337,7 @@
 
     std::string mode = getXmlAttribute(cur, Attributes::mode);
     if (!mode.empty()) {
-        gain->setMode(GainModeConverter::maskFromString(mode));
+        gain->setMode(static_cast<audio_gain_mode_t>(GainModeConverter::maskFromString(mode)));
     }
 
     std::string channelsLiteral = getXmlAttribute(cur, Attributes::channelMask);
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 1821140..d39eff6 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -26,8 +26,8 @@
     {"STRATEGY_PHONE",
      {
          {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0,
-            ""}},
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
+            AUDIO_FLAG_NONE, ""}},
          },
          {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
@@ -39,10 +39,11 @@
      {
          {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
-            AUDIO_SOURCE_DEFAULT, 0, ""}}
+            AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          },
          {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}},
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT,
+            AUDIO_FLAG_NONE, ""}},
          }
      },
     },
@@ -58,7 +59,7 @@
      {
          {"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
-            AUDIO_SOURCE_DEFAULT, 0, ""}}
+            AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          }
      },
     },
@@ -66,15 +67,16 @@
      {
          {"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
           {
-              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT, 0, ""},
+              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT,
+               AUDIO_FLAG_NONE, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
-               AUDIO_SOURCE_DEFAULT, 0, ""},
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
-               AUDIO_SOURCE_DEFAULT, 0, ""},
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
-               AUDIO_SOURCE_DEFAULT, 0, ""},
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_EVENT,
-               AUDIO_SOURCE_DEFAULT, 0, ""}
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
           }
          }
      },
@@ -83,21 +85,25 @@
      {
          {"assistant", AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
-            AUDIO_SOURCE_DEFAULT, 0, ""}}
+            AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          },
          {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
           {
-              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
-              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT, 0, ""},
-              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""},
+              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+               AUDIO_FLAG_NONE, ""},
+              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT,
+               AUDIO_FLAG_NONE, ""},
+              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANT, AUDIO_SOURCE_DEFAULT,
+               AUDIO_FLAG_NONE, ""},
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
-               AUDIO_SOURCE_DEFAULT, 0, ""},
-              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
+              {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+               AUDIO_FLAG_NONE, ""}
           },
          },
          {"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
-            AUDIO_SOURCE_DEFAULT, 0, ""}}
+            AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          }
      },
     },
@@ -106,7 +112,7 @@
          {"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
-               AUDIO_SOURCE_DEFAULT, 0, ""}
+               AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
           }
          }
      },
@@ -114,7 +120,8 @@
     {"STRATEGY_CALL_ASSISTANT",
      {
          {"", AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""}}
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
+            AUDIO_FLAG_NONE, ""}}
          }
      },
     },
@@ -136,14 +143,16 @@
     {"rerouting",
      {
          {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT, 0, ""}}
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
+            AUDIO_FLAG_NONE, ""}}
          }
      },
     },
     {"patch",
      {
          {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+            AUDIO_FLAG_NONE, ""}}
          }
      },
     }
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 4842cb2..daf6418 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -228,7 +228,8 @@
             std::string flags = getXmlAttribute(cur, "value");
 
             ALOGV("%s flags %s",  __FUNCTION__, flags.c_str());
-            attributes.flags = AudioFlagConverter::maskFromString(flags, " ");
+            attributes.flags = static_cast<audio_flags_mask_t>(
+                    AudioFlagConverter::maskFromString(flags, " "));
         }
         if (!xmlStrcmp(cur->name, (const xmlChar *)("Bundle"))) {
             std::string bundleKey = getXmlAttribute(cur, "key");
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index f91f8d7..f8a6fc0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -45,7 +45,7 @@
 
 bool InputSource::sendToHW(string & /*error*/)
 {
-    uint32_t applicableInputDevice;
+    audio_devices_t applicableInputDevice;
     blackboardRead(&applicableInputDevice, sizeof(applicableInputDevice));
     return mPolicyPluginInterface->setDeviceForInputSource(mId, applicableInputDevice);
 }
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
index 244f082..6c8eb65 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.h
@@ -32,7 +32,7 @@
 
     struct Device
     {
-        uint32_t applicableDevice; /**< applicable device for this strategy. */
+        audio_devices_t applicableDevice; /**< applicable device for this strategy. */
         char deviceAddress[mMaxStringSize]; /**< device address associated with this strategy. */
     } __attribute__((packed));
 
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index aa06ae3..f4645e6 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -51,7 +51,7 @@
         mApplicableDevices = devices;
         return NO_ERROR;
     }
-    devices |= AUDIO_DEVICE_BIT_IN;
+    devices = static_cast<audio_devices_t>(devices | AUDIO_DEVICE_BIT_IN);
     if (!audio_is_input_device(devices)) {
         ALOGE("%s: trying to set an invalid device 0x%X for input source %s",
               __FUNCTION__, devices, getName().c_str());
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fc3b2a2..e4b0dd1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -904,7 +904,8 @@
     // Only honor audibility enforced when required. The client will be
     // forced to reconnect if the forced usage changes.
     if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
-        dstAttr->flags &= ~AUDIO_FLAG_AUDIBILITY_ENFORCED;
+        dstAttr->flags = static_cast<audio_flags_mask_t>(
+                dstAttr->flags & ~AUDIO_FLAG_AUDIBILITY_ENFORCED);
     }
 
     return NO_ERROR;
@@ -936,7 +937,7 @@
         return status;
     }
     if (auto it = mAllowedCapturePolicies.find(uid); it != end(mAllowedCapturePolicies)) {
-        resultAttr->flags |= it->second;
+        resultAttr->flags = static_cast<audio_flags_mask_t>(resultAttr->flags | it->second);
     }
     *stream = mEngine->getStreamTypeForAttributes(*resultAttr);
 
@@ -1254,7 +1255,8 @@
 
     // Discard haptic channel mask when forcing muting haptic channels.
     audio_channel_mask_t channelMask = forceMutingHaptic
-            ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;
+            ? static_cast<audio_channel_mask_t>(config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL)
+            : config->channel_mask;
 
     // open a direct output if required by specified parameters
     //force direct flag if offload flag is set: offloading implies a direct output stream
@@ -3233,7 +3235,7 @@
     ALOGV("%s() audioSource=%d role=%d %s", __func__, audioSource, role,
             dumpAudioDeviceTypeAddrVector(devices).c_str());
 
-    if (!areAllDevicesSupported(devices, audio_is_input_device, __func__)) {
+    if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
         return BAD_VALUE;
     }
     status_t status = mEngine->setDevicesRoleForCapturePreset(audioSource, role, devices);
@@ -3249,7 +3251,7 @@
     ALOGV("%s() audioSource=%d role=%d %s", __func__, audioSource, role,
             dumpAudioDeviceTypeAddrVector(devices).c_str());
 
-    if (!areAllDevicesSupported(devices, audio_is_input_device, __func__)) {
+    if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
         return BAD_VALUE;
     }
     status_t status = mEngine->addDevicesRoleForCapturePreset(audioSource, role, devices);
@@ -3266,7 +3268,7 @@
     ALOGV("%s() audioSource=%d role=%d devices=%s", __func__, audioSource, role,
             dumpAudioDeviceTypeAddrVector(devices).c_str());
 
-    if (!areAllDevicesSupported(devices, audio_is_input_device, __func__)) {
+    if (!areAllDevicesSupported(devices, audio_call_is_input_device, __func__)) {
         return BAD_VALUE;
     }
 
@@ -6249,9 +6251,8 @@
 
     float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
     if (outputDesc->isFixedVolume(deviceTypes) ||
-            // Force VoIP volume to max for bluetooth SCO
-
-            ((isVoiceVolSrc || isBtScoVolSrc) &&
+            // Force VoIP volume to max for bluetooth SCO device except if muted
+            (index != 0 && (isVoiceVolSrc || isBtScoVolSrc) &&
                     isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
         volumeDb = 0.0f;
     }
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 14e5236..df8e4c5 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -244,11 +244,12 @@
         uid = callingUid;
     }
     if (!mPackageManager.allowPlaybackCapture(uid)) {
-        attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
+        attr->flags = static_cast<audio_flags_mask_t>(attr->flags | AUDIO_FLAG_NO_MEDIA_PROJECTION);
     }
     if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
             && !bypassInterruptionPolicyAllowed(pid, uid)) {
-        attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
+        attr->flags = static_cast<audio_flags_mask_t>(
+                attr->flags & ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE));
     }
     AutoCallerClear acc;
     AudioPolicyInterface::output_type_t outputType;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index ed9ec8c..ca2164b 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -89,7 +89,7 @@
     void getOutputForAttr(
             audio_port_handle_t *selectedDeviceId,
             audio_format_t format,
-            int channelMask,
+            audio_channel_mask_t channelMask,
             int sampleRate,
             audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
             audio_io_handle_t *output = nullptr,
@@ -100,7 +100,7 @@
             audio_unique_id_t riid,
             audio_port_handle_t *selectedDeviceId,
             audio_format_t format,
-            int channelMask,
+            audio_channel_mask_t channelMask,
             int sampleRate,
             audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
             audio_port_handle_t *portId = nullptr);
@@ -166,7 +166,7 @@
 void AudioPolicyManagerTest::getOutputForAttr(
         audio_port_handle_t *selectedDeviceId,
         audio_format_t format,
-        int channelMask,
+        audio_channel_mask_t channelMask,
         int sampleRate,
         audio_output_flags_t flags,
         audio_io_handle_t *output,
@@ -196,7 +196,7 @@
         audio_unique_id_t riid,
         audio_port_handle_t *selectedDeviceId,
         audio_format_t format,
-        int channelMask,
+        audio_channel_mask_t channelMask,
         int sampleRate,
         audio_input_flags_t flags,
         audio_port_handle_t *portId) {
@@ -709,7 +709,8 @@
 
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
-    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, 0, ""};
+    audio_attributes_t attr = {
+        AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
     std::string tags = "addr=" + mMixAddress;
     strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
     getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
@@ -759,9 +760,9 @@
         AudioPolicyManagerTestDPPlaybackReRouting,
         testing::Values(
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""}
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
                 )
         );
 
@@ -770,47 +771,47 @@
         AudioPolicyManagerTestDPPlaybackReRouting,
         testing::Values(
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
-                                     AUDIO_USAGE_ASSISTANCE_SONIFICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VIRTUAL_SOURCE,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"}
+                    AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, "addr=remote_submix_media"}
                 )
         );
 
@@ -819,41 +820,41 @@
         AudioPolicyManagerTestDPPlaybackReRouting,
         testing::Values(
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
                                      AUDIO_USAGE_ASSISTANCE_SONIFICATION,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
-                                     AUDIO_SOURCE_DEFAULT, 0, ""}
+                                     AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
                 )
         );
 
@@ -894,7 +895,8 @@
 
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
-    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, 0, ""};
+    audio_attributes_t attr =
+            {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
     std::string tags = std::string("addr=") + mMixAddress;
     strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
     getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
@@ -943,17 +945,19 @@
         AudioPolicyManagerTestDPMixRecordInjection,
         testing::Values(
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_CAMCORDER, 0, ""},
+                                     AUDIO_SOURCE_CAMCORDER, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_CAMCORDER, 0, "addr=remote_submix_media"},
+                                     AUDIO_SOURCE_CAMCORDER, AUDIO_FLAG_NONE,
+                                     "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_MIC, 0, "addr=remote_submix_media"},
+                                     AUDIO_SOURCE_MIC, AUDIO_FLAG_NONE,
+                                     "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_MIC, 0, ""},
+                                     AUDIO_SOURCE_MIC, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_VOICE_COMMUNICATION, 0, ""},
+                                     AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_VOICE_COMMUNICATION, 0,
+                                     AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE,
                                      "addr=remote_submix_media"}
                 )
         );
@@ -964,14 +968,15 @@
         AudioPolicyManagerTestDPMixRecordInjection,
         testing::Values(
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_VOICE_RECOGNITION, 0, ""},
+                                     AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_HOTWORD, 0, ""},
+                                     AUDIO_SOURCE_HOTWORD, AUDIO_FLAG_NONE, ""},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_VOICE_RECOGNITION, 0,
+                                     AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_FLAG_NONE,
                                      "addr=remote_submix_media"},
                 (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
-                                     AUDIO_SOURCE_HOTWORD, 0, "addr=remote_submix_media"}
+                                     AUDIO_SOURCE_HOTWORD, AUDIO_FLAG_NONE,
+                                     "addr=remote_submix_media"}
                 )
         );
 
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index a4b6ce7..44fe72d 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -163,7 +163,8 @@
 Status ResourceObserverService::registerObserver(
         const std::shared_ptr<IResourceObserver>& in_observer,
         const std::vector<MediaObservableFilter>& in_filters) {
-    if (checkCallingPermission(
+    if ((getpid() != AIBinder_getCallingPid()) &&
+            checkCallingPermission(
             String16("android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER")) == false) {
         ALOGE("Permission Denial: "
                 "can't registerObserver from pid=%d, uid=%d\n",
@@ -217,7 +218,8 @@
 
 Status ResourceObserverService::unregisterObserver(
         const std::shared_ptr<IResourceObserver>& in_observer) {
-    if (checkCallingPermission(
+    if ((getpid() != AIBinder_getCallingPid()) &&
+            checkCallingPermission(
             String16("android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER")) == false) {
         ALOGE("Permission Denial: "
                 "can't unregisterObserver from pid=%d, uid=%d\n",
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 9639c55..56f327e 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -24,8 +24,8 @@
 #include <cutils/properties.h>
 #include <media/TranscoderWrapper.h>
 #include <media/TranscodingClientManager.h>
-#include <media/TranscodingJobScheduler.h>
 #include <media/TranscodingResourcePolicy.h>
+#include <media/TranscodingSessionController.h>
 #include <media/TranscodingUidPolicy.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -44,12 +44,13 @@
         const std::shared_ptr<TranscoderInterface>& transcoder)
       : mUidPolicy(new TranscodingUidPolicy()),
         mResourcePolicy(new TranscodingResourcePolicy()),
-        mJobScheduler(new TranscodingJobScheduler(transcoder, mUidPolicy, mResourcePolicy)),
-        mClientManager(new TranscodingClientManager(mJobScheduler)) {
+        mSessionController(
+                new TranscodingSessionController(transcoder, mUidPolicy, mResourcePolicy)),
+        mClientManager(new TranscodingClientManager(mSessionController)) {
     ALOGV("MediaTranscodingService is created");
-    transcoder->setCallback(mJobScheduler);
-    mUidPolicy->setCallback(mJobScheduler);
-    mResourcePolicy->setCallback(mJobScheduler);
+    transcoder->setCallback(mSessionController);
+    mUidPolicy->setCallback(mSessionController);
+    mResourcePolicy->setCallback(mSessionController);
 }
 
 MediaTranscodingService::~MediaTranscodingService() {
@@ -78,7 +79,7 @@
 
     Vector<String16> args;
     mClientManager->dumpAllClients(fd, args);
-    mJobScheduler->dumpAllJobs(fd, args);
+    mSessionController->dumpAllSessions(fd, args);
     return OK;
 }
 
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/services/mediatranscoding/MediaTranscodingService.h
index 0fe6864..428f777 100644
--- a/services/mediatranscoding/MediaTranscodingService.h
+++ b/services/mediatranscoding/MediaTranscodingService.h
@@ -26,17 +26,17 @@
 using ::aidl::android::media::BnMediaTranscodingService;
 using ::aidl::android::media::ITranscodingClient;
 using ::aidl::android::media::ITranscodingClientCallback;
-using ::aidl::android::media::TranscodingJobParcel;
 using ::aidl::android::media::TranscodingRequestParcel;
+using ::aidl::android::media::TranscodingSessionParcel;
 class TranscodingClientManager;
-class TranscodingJobScheduler;
+class TranscodingSessionController;
 class TranscoderInterface;
 class UidPolicyInterface;
 class ResourcePolicyInterface;
 
 class MediaTranscodingService : public BnMediaTranscodingService {
 public:
-    static constexpr int32_t kInvalidJobId = -1;
+    static constexpr int32_t kInvalidSessionId = -1;
     static constexpr int32_t kInvalidClientId = -1;
 
     MediaTranscodingService(const std::shared_ptr<TranscoderInterface>& transcoder);
@@ -61,7 +61,7 @@
 
     std::shared_ptr<UidPolicyInterface> mUidPolicy;
     std::shared_ptr<ResourcePolicyInterface> mResourcePolicy;
-    std::shared_ptr<TranscodingJobScheduler> mJobScheduler;
+    std::shared_ptr<TranscodingSessionController> mSessionController;
     std::shared_ptr<TranscodingClientManager> mClientManager;
 };
 
diff --git a/services/mediatranscoding/SimulatedTranscoder.cpp b/services/mediatranscoding/SimulatedTranscoder.cpp
index 97d5f5f..03ee886 100644
--- a/services/mediatranscoding/SimulatedTranscoder.cpp
+++ b/services/mediatranscoding/SimulatedTranscoder.cpp
@@ -48,58 +48,59 @@
 }
 
 void SimulatedTranscoder::start(
-        ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+        ClientIdType clientId, SessionIdType sessionId, const TranscodingRequestParcel& request,
         const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) {
     if (request.testConfig.has_value() && request.testConfig->processingTotalTimeMs > 0) {
-        mJobProcessingTimeMs = request.testConfig->processingTotalTimeMs;
+        mSessionProcessingTimeMs = request.testConfig->processingTotalTimeMs;
     }
-    ALOGV("%s: job {%d}: processingTime: %lld", __FUNCTION__, jobId,
-          (long long)mJobProcessingTimeMs);
-    queueEvent(Event::Start, clientId, jobId, [=] {
+    ALOGV("%s: session {%d}: processingTime: %lld", __FUNCTION__, sessionId,
+          (long long)mSessionProcessingTimeMs);
+    queueEvent(Event::Start, clientId, sessionId, [=] {
         auto callback = mCallback.lock();
         if (callback != nullptr) {
-            callback->onStarted(clientId, jobId);
+            callback->onStarted(clientId, sessionId);
         }
     });
 }
 
-void SimulatedTranscoder::pause(ClientIdType clientId, JobIdType jobId) {
-    queueEvent(Event::Pause, clientId, jobId, [=] {
+void SimulatedTranscoder::pause(ClientIdType clientId, SessionIdType sessionId) {
+    queueEvent(Event::Pause, clientId, sessionId, [=] {
         auto callback = mCallback.lock();
         if (callback != nullptr) {
-            callback->onPaused(clientId, jobId);
+            callback->onPaused(clientId, sessionId);
         }
     });
 }
 
 void SimulatedTranscoder::resume(
-        ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& /*request*/,
+        ClientIdType clientId, SessionIdType sessionId, const TranscodingRequestParcel& /*request*/,
         const std::shared_ptr<ITranscodingClientCallback>& /*clientCallback*/) {
-    queueEvent(Event::Resume, clientId, jobId, [=] {
+    queueEvent(Event::Resume, clientId, sessionId, [=] {
         auto callback = mCallback.lock();
         if (callback != nullptr) {
-            callback->onResumed(clientId, jobId);
+            callback->onResumed(clientId, sessionId);
         }
     });
 }
 
-void SimulatedTranscoder::stop(ClientIdType clientId, JobIdType jobId) {
-    queueEvent(Event::Stop, clientId, jobId, nullptr);
+void SimulatedTranscoder::stop(ClientIdType clientId, SessionIdType sessionId) {
+    queueEvent(Event::Stop, clientId, sessionId, nullptr);
 }
 
-void SimulatedTranscoder::queueEvent(Event::Type type, ClientIdType clientId, JobIdType jobId,
-                                     std::function<void()> runnable) {
-    ALOGV("%s: job {%lld, %d}: %s", __FUNCTION__, (long long)clientId, jobId, toString(type));
+void SimulatedTranscoder::queueEvent(Event::Type type, ClientIdType clientId,
+                                     SessionIdType sessionId, std::function<void()> runnable) {
+    ALOGV("%s: session {%lld, %d}: %s", __FUNCTION__, (long long)clientId, sessionId,
+          toString(type));
 
     auto lock = std::scoped_lock(mLock);
 
-    mQueue.push_back({type, clientId, jobId, runnable});
+    mQueue.push_back({type, clientId, sessionId, runnable});
     mCondition.notify_one();
 }
 
 void SimulatedTranscoder::threadLoop() {
     bool running = false;
-    std::chrono::microseconds remainingUs(kJobDurationUs);
+    std::chrono::microseconds remainingUs(kSessionDurationUs);
     std::chrono::system_clock::time_point lastRunningTime;
     Event lastRunningEvent;
 
@@ -113,7 +114,7 @@
                 mCondition.wait(lock);
                 continue;
             }
-            // If running, wait for the remaining life of this job. Report finish if timed out.
+            // If running, wait for the remaining life of this session. Report finish if timed out.
             std::cv_status status = mCondition.wait_for(lock, remainingUs);
             if (status == std::cv_status::timeout) {
                 running = false;
@@ -121,7 +122,7 @@
                 auto callback = mCallback.lock();
                 if (callback != nullptr) {
                     lock.unlock();
-                    callback->onFinish(lastRunningEvent.clientId, lastRunningEvent.jobId);
+                    callback->onFinish(lastRunningEvent.clientId, lastRunningEvent.sessionId);
                     lock.lock();
                 }
             } else {
@@ -139,22 +140,22 @@
             Event event = *mQueue.begin();
             mQueue.pop_front();
 
-            ALOGV("%s: job {%lld, %d}: %s", __FUNCTION__, (long long)event.clientId, event.jobId,
-                  toString(event.type));
+            ALOGV("%s: session {%lld, %d}: %s", __FUNCTION__, (long long)event.clientId,
+                  event.sessionId, toString(event.type));
 
             if (!running && (event.type == Event::Start || event.type == Event::Resume)) {
                 running = true;
                 lastRunningTime = std::chrono::system_clock::now();
                 lastRunningEvent = event;
                 if (event.type == Event::Start) {
-                    remainingUs = std::chrono::milliseconds(mJobProcessingTimeMs);
+                    remainingUs = std::chrono::milliseconds(mSessionProcessingTimeMs);
                 }
             } else if (running && (event.type == Event::Pause || event.type == Event::Stop)) {
                 running = false;
                 remainingUs -= (std::chrono::system_clock::now() - lastRunningTime);
             } else {
-                ALOGW("%s: discarding bad event: job {%lld, %d}: %s", __FUNCTION__,
-                      (long long)event.clientId, event.jobId, toString(event.type));
+                ALOGW("%s: discarding bad event: session {%lld, %d}: %s", __FUNCTION__,
+                      (long long)event.clientId, event.sessionId, toString(event.type));
                 continue;
             }
 
diff --git a/services/mediatranscoding/SimulatedTranscoder.h b/services/mediatranscoding/SimulatedTranscoder.h
index 1c359dd..ba2bba0 100644
--- a/services/mediatranscoding/SimulatedTranscoder.h
+++ b/services/mediatranscoding/SimulatedTranscoder.h
@@ -32,8 +32,8 @@
  * SimulatedTranscoder is used when useSimulatedTranscoder in TranscodingTestConfig
  * is set to true.
  *
- * SimulatedTranscoder simulates job execution by reporting finish after kJobDurationUs.
- * Job lifecycle events are reported via progress updates with special progress
+ * SimulatedTranscoder simulates session execution by reporting finish after kSessionDurationUs.
+ * Session lifecycle events are reported via progress updates with special progress
  * numbers (equal to the Event's type).
  */
 class SimulatedTranscoder : public TranscoderInterface {
@@ -41,22 +41,24 @@
     struct Event {
         enum Type { NoEvent, Start, Pause, Resume, Stop, Finished, Failed } type;
         ClientIdType clientId;
-        JobIdType jobId;
+        SessionIdType sessionId;
         std::function<void()> runnable;
     };
 
-    static constexpr int64_t kJobDurationUs = 1000000;
+    static constexpr int64_t kSessionDurationUs = 1000000;
 
     SimulatedTranscoder();
 
     // TranscoderInterface
     void setCallback(const std::shared_ptr<TranscoderCallbackInterface>& cb) override;
-    void start(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+    void start(ClientIdType clientId, SessionIdType sessionId,
+               const TranscodingRequestParcel& request,
                const std::shared_ptr<ITranscodingClientCallback>& clientCallback) override;
-    void pause(ClientIdType clientId, JobIdType jobId) override;
-    void resume(ClientIdType clientId, JobIdType jobId, const TranscodingRequestParcel& request,
+    void pause(ClientIdType clientId, SessionIdType sessionId) override;
+    void resume(ClientIdType clientId, SessionIdType sessionId,
+                const TranscodingRequestParcel& request,
                 const std::shared_ptr<ITranscodingClientCallback>& clientCallback) override;
-    void stop(ClientIdType clientId, JobIdType jobId) override;
+    void stop(ClientIdType clientId, SessionIdType sessionId) override;
     // ~TranscoderInterface
 
 private:
@@ -66,10 +68,10 @@
     std::list<Event> mQueue GUARDED_BY(mLock);
 
     // Minimum time spent on transcode the video. This is used just for testing.
-    int64_t mJobProcessingTimeMs = kJobDurationUs / 1000;
+    int64_t mSessionProcessingTimeMs = kSessionDurationUs / 1000;
 
     static const char* toString(Event::Type type);
-    void queueEvent(Event::Type type, ClientIdType clientId, JobIdType jobId,
+    void queueEvent(Event::Type type, ClientIdType clientId, SessionIdType sessionId,
                     std::function<void()> runnable);
     void threadLoop();
 };
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 6d0b99e..5f4f645 100644
--- a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -20,9 +20,9 @@
 #include <aidl/android/media/IMediaTranscodingService.h>
 #include <aidl/android/media/ITranscodingClient.h>
 #include <aidl/android/media/ITranscodingClientCallback.h>
-#include <aidl/android/media/TranscodingJobParcel.h>
-#include <aidl/android/media/TranscodingJobPriority.h>
 #include <aidl/android/media/TranscodingRequestParcel.h>
+#include <aidl/android/media/TranscodingSessionParcel.h>
+#include <aidl/android/media/TranscodingSessionPriority.h>
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -48,9 +48,9 @@
 using aidl::android::media::IMediaTranscodingService;
 using aidl::android::media::ITranscodingClient;
 using aidl::android::media::ITranscodingClientCallback;
-using aidl::android::media::TranscodingJobParcel;
-using aidl::android::media::TranscodingJobPriority;
 using aidl::android::media::TranscodingRequestParcel;
+using aidl::android::media::TranscodingSessionParcel;
+using aidl::android::media::TranscodingSessionPriority;
 using aidl::android::media::TranscodingVideoTrackFormat;
 
 constexpr int32_t kClientUseCallingPid = IMediaTranscodingService::USE_CALLING_PID;
@@ -112,12 +112,12 @@
     struct Event {
         enum { NoEvent, Start, Pause, Resume, Finished, Failed } type;
         int64_t clientId;
-        int32_t jobId;
+        int32_t sessionId;
     };
 
-#define DECLARE_EVENT(action)                              \
-    static Event action(int32_t clientId, int32_t jobId) { \
-        return {Event::action, clientId, jobId};           \
+#define DECLARE_EVENT(action)                                  \
+    static Event action(int32_t clientId, int32_t sessionId) { \
+        return {Event::action, clientId, sessionId};           \
     }
 
     DECLARE_EVENT(Start);
@@ -149,8 +149,8 @@
         default:
             return "NoEvent";
         }
-        return "job {" + std::to_string(event.clientId) + ", " + std::to_string(event.jobId) +
-               "}: " + eventStr;
+        return "session {" + std::to_string(event.clientId) + ", " +
+               std::to_string(event.sessionId) + "}: " + eventStr;
     }
 
     // Pop 1 event from front, wait for up to timeoutUs if empty.
@@ -238,7 +238,7 @@
 
 // Operators for GTest macros.
 bool operator==(const EventTracker::Event& lhs, const EventTracker::Event& rhs) {
-    return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.jobId == rhs.jobId;
+    return lhs.type == rhs.type && lhs.clientId == rhs.clientId && lhs.sessionId == rhs.sessionId;
 }
 
 std::ostream& operator<<(std::ostream& str, const EventTracker::Event& v) {
@@ -288,40 +288,41 @@
         return Status::ok();
     }
 
-    Status onTranscodingStarted(int32_t in_jobId) override {
-        append(EventTracker::Start(mClientId, in_jobId));
+    Status onTranscodingStarted(int32_t in_sessionId) override {
+        append(EventTracker::Start(mClientId, in_sessionId));
         return Status::ok();
     }
 
-    Status onTranscodingPaused(int32_t in_jobId) override {
-        append(EventTracker::Pause(mClientId, in_jobId));
+    Status onTranscodingPaused(int32_t in_sessionId) override {
+        append(EventTracker::Pause(mClientId, in_sessionId));
         return Status::ok();
     }
 
-    Status onTranscodingResumed(int32_t in_jobId) override {
-        append(EventTracker::Resume(mClientId, in_jobId));
+    Status onTranscodingResumed(int32_t in_sessionId) override {
+        append(EventTracker::Resume(mClientId, in_sessionId));
         return Status::ok();
     }
 
     Status onTranscodingFinished(
-            int32_t in_jobId,
+            int32_t in_sessionId,
             const ::aidl::android::media::TranscodingResultParcel& /* in_result */) override {
-        append(Finished(mClientId, in_jobId));
+        append(Finished(mClientId, in_sessionId));
         return Status::ok();
     }
 
-    Status onTranscodingFailed(int32_t in_jobId,
+    Status onTranscodingFailed(int32_t in_sessionId,
                                ::aidl::android::media::TranscodingErrorCode in_errorCode) override {
-        append(Failed(mClientId, in_jobId), in_errorCode);
+        append(Failed(mClientId, in_sessionId), in_errorCode);
         return Status::ok();
     }
 
-    Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
-                                      int32_t /* in_newAwaitNumber */) override {
+    Status onAwaitNumberOfSessionsChanged(int32_t /* in_sessionId */,
+                                          int32_t /* in_oldAwaitNumber */,
+                                          int32_t /* in_newAwaitNumber */) override {
         return Status::ok();
     }
 
-    Status onProgressUpdate(int32_t /* in_jobId */, int32_t in_progress) override {
+    Status onProgressUpdate(int32_t /* in_sessionId */, int32_t in_progress) override {
         updateProgress(in_progress);
         return Status::ok();
     }
@@ -354,13 +355,13 @@
     }
 
     template <bool expectation = success>
-    bool submit(int32_t jobId, const char* sourceFilePath, const char* destinationFilePath,
-                TranscodingJobPriority priority = TranscodingJobPriority::kNormal,
+    bool submit(int32_t sessionId, const char* sourceFilePath, const char* destinationFilePath,
+                TranscodingSessionPriority priority = TranscodingSessionPriority::kNormal,
                 int bitrateBps = -1, int overridePid = -1, int overrideUid = -1) {
         constexpr bool shouldSucceed = (expectation == success);
         bool result;
         TranscodingRequestParcel request;
-        TranscodingJobParcel job;
+        TranscodingSessionParcel session;
 
         request.sourceFilePath = sourceFilePath;
         request.destinationFilePath = destinationFilePath;
@@ -371,22 +372,23 @@
             request.requestedVideoTrackFormat.emplace(TranscodingVideoTrackFormat());
             request.requestedVideoTrackFormat->bitrateBps = bitrateBps;
         }
-        Status status = mClient->submitRequest(request, &job, &result);
+        Status status = mClient->submitRequest(request, &session, &result);
 
         EXPECT_TRUE(status.isOk());
         EXPECT_EQ(result, shouldSucceed);
         if (shouldSucceed) {
-            EXPECT_EQ(job.jobId, jobId);
+            EXPECT_EQ(session.sessionId, sessionId);
         }
 
-        return status.isOk() && (result == shouldSucceed) && (!shouldSucceed || job.jobId == jobId);
+        return status.isOk() && (result == shouldSucceed) &&
+               (!shouldSucceed || session.sessionId == sessionId);
     }
 
     template <bool expectation = success>
-    bool cancel(int32_t jobId) {
+    bool cancel(int32_t sessionId) {
         constexpr bool shouldSucceed = (expectation == success);
         bool result;
-        Status status = mClient->cancelJob(jobId, &result);
+        Status status = mClient->cancelSession(sessionId, &result);
 
         EXPECT_TRUE(status.isOk());
         EXPECT_EQ(result, shouldSucceed);
@@ -395,23 +397,24 @@
     }
 
     template <bool expectation = success>
-    bool getJob(int32_t jobId, const char* sourceFilePath, const char* destinationFilePath) {
+    bool getSession(int32_t sessionId, const char* sourceFilePath,
+                    const char* destinationFilePath) {
         constexpr bool shouldSucceed = (expectation == success);
         bool result;
-        TranscodingJobParcel job;
-        Status status = mClient->getJobWithId(jobId, &job, &result);
+        TranscodingSessionParcel session;
+        Status status = mClient->getSessionWithId(sessionId, &session, &result);
 
         EXPECT_TRUE(status.isOk());
         EXPECT_EQ(result, shouldSucceed);
         if (shouldSucceed) {
-            EXPECT_EQ(job.jobId, jobId);
-            EXPECT_EQ(job.request.sourceFilePath, sourceFilePath);
+            EXPECT_EQ(session.sessionId, sessionId);
+            EXPECT_EQ(session.request.sourceFilePath, sourceFilePath);
         }
 
         return status.isOk() && (result == shouldSucceed) &&
-               (!shouldSucceed ||
-                (job.jobId == jobId && job.request.sourceFilePath == sourceFilePath &&
-                 job.request.destinationFilePath == destinationFilePath));
+               (!shouldSucceed || (session.sessionId == sessionId &&
+                                   session.request.sourceFilePath == sourceFilePath &&
+                                   session.request.destinationFilePath == destinationFilePath));
     }
 
     int32_t mClientId;
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
index 381bbf5..0550d77 100644
--- a/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
+++ b/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
@@ -34,7 +34,7 @@
 namespace media {
 
 constexpr int64_t kPaddingUs = 400000;
-constexpr int64_t kJobWithPaddingUs = 10000000 + kPaddingUs;
+constexpr int64_t kSessionWithPaddingUs = 10000000 + kPaddingUs;
 constexpr int32_t kBitRate = 8 * 1000 * 1000;  // 8Mbs
 
 constexpr const char* kShortSrcPath =
@@ -59,8 +59,9 @@
     const char* dstPath = OUTPATH(TestInvalidSource);
     deleteFile(dstPath);
 
-    // Submit one job.
-    EXPECT_TRUE(mClient1->submit(0, srcPath, dstPath, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit one session.
+    EXPECT_TRUE(
+            mClient1->submit(0, srcPath, dstPath, TranscodingSessionPriority::kNormal, kBitRate));
 
     // Check expected error.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Failed(CLIENT(1), 0));
@@ -75,12 +76,12 @@
     const char* dstPath = OUTPATH(TestPassthru);
     deleteFile(dstPath);
 
-    // Submit one job.
+    // Submit one session.
     EXPECT_TRUE(mClient1->submit(0, kShortSrcPath, dstPath));
 
-    // Wait for job to finish.
+    // Wait for session to finish.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
 
     unregisterMultipleClients();
 }
@@ -91,13 +92,13 @@
     const char* dstPath = OUTPATH(TestTranscodeVideo);
     deleteFile(dstPath);
 
-    // Submit one job.
-    EXPECT_TRUE(
-            mClient1->submit(0, kShortSrcPath, dstPath, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit one session.
+    EXPECT_TRUE(mClient1->submit(0, kShortSrcPath, dstPath, TranscodingSessionPriority::kNormal,
+                                 kBitRate));
 
-    // Wait for job to finish.
+    // Wait for session to finish.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
 
     unregisterMultipleClients();
 }
@@ -108,13 +109,13 @@
     const char* dstPath = OUTPATH(TestTranscodeVideoProgress);
     deleteFile(dstPath);
 
-    // Submit one job.
-    EXPECT_TRUE(
-            mClient1->submit(0, kLongSrcPath, dstPath, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit one session.
+    EXPECT_TRUE(mClient1->submit(0, kLongSrcPath, dstPath, TranscodingSessionPriority::kNormal,
+                                 kBitRate));
 
-    // Wait for job to finish.
+    // Wait for session to finish.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
 
     // Check the progress update messages are received. For this clip (around ~15 second long),
     // expect at least 10 updates, and the last update should be 100.
@@ -133,24 +134,26 @@
 
     const char* srcPath0 = kLongSrcPath;
     const char* srcPath1 = kShortSrcPath;
-    const char* dstPath0 = OUTPATH(TestCancelImmediately_Job0);
-    const char* dstPath1 = OUTPATH(TestCancelImmediately_Job1);
+    const char* dstPath0 = OUTPATH(TestCancelImmediately_Session0);
+    const char* dstPath1 = OUTPATH(TestCancelImmediately_Session1);
 
     deleteFile(dstPath0);
     deleteFile(dstPath1);
-    // Submit one job, should start immediately.
-    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit one session, should start immediately.
+    EXPECT_TRUE(
+            mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_TRUE(mClient1->getJob(0, srcPath0, dstPath0));
+    EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0));
 
-    // Test cancel job immediately, getJob should fail after cancel.
+    // Test cancel session immediately, getSession should fail after cancel.
     EXPECT_TRUE(mClient1->cancel(0));
-    EXPECT_TRUE(mClient1->getJob<fail>(0, "", ""));
+    EXPECT_TRUE(mClient1->getSession<fail>(0, "", ""));
 
-    // Submit new job, new job should start immediately and finish.
-    EXPECT_TRUE(mClient1->submit(1, srcPath1, dstPath1, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit new session, new session should start immediately and finish.
+    EXPECT_TRUE(
+            mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
 
     unregisterMultipleClients();
 }
@@ -163,26 +166,28 @@
 
     const char* srcPath0 = kLongSrcPath;
     const char* srcPath1 = kShortSrcPath;
-    const char* dstPath0 = OUTPATH(TestCancelWhileRunning_Job0);
-    const char* dstPath1 = OUTPATH(TestCancelWhileRunning_Job1);
+    const char* dstPath0 = OUTPATH(TestCancelWhileRunning_Session0);
+    const char* dstPath1 = OUTPATH(TestCancelWhileRunning_Session1);
 
     deleteFile(dstPath0);
     deleteFile(dstPath1);
-    // Submit two jobs, job 0 should start immediately, job 1 should be queued.
-    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingJobPriority::kNormal, kBitRate));
-    EXPECT_TRUE(mClient1->submit(1, srcPath1, dstPath1, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit two sessions, session 0 should start immediately, session 1 should be queued.
+    EXPECT_TRUE(
+            mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate));
+    EXPECT_TRUE(
+            mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_TRUE(mClient1->getJob(0, srcPath0, dstPath0));
-    EXPECT_TRUE(mClient1->getJob(1, srcPath1, dstPath1));
+    EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0));
+    EXPECT_TRUE(mClient1->getSession(1, srcPath1, dstPath1));
 
-    // Job 0 (longtest) shouldn't finish in 1 seconds.
+    // Session 0 (longtest) shouldn't finish in 1 seconds.
     EXPECT_EQ(mClient1->pop(1000000), EventTracker::NoEvent);
 
-    // Now cancel job 0. Job 1 should start immediately and finish.
+    // Now cancel session 0. Session 1 should start immediately and finish.
     EXPECT_TRUE(mClient1->cancel(0));
-    EXPECT_TRUE(mClient1->getJob<fail>(0, "", ""));
+    EXPECT_TRUE(mClient1->getSession<fail>(0, "", ""));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
 
     unregisterMultipleClients();
 }
@@ -192,48 +197,49 @@
 
     const char* srcPath0 = kLongSrcPath;
     const char* srcPath1 = kShortSrcPath;
-    const char* dstPath0 = OUTPATH(TestPauseResumeSingleClient_Job0);
-    const char* dstPath1 = OUTPATH(TestPauseResumeSingleClient_Job1);
+    const char* dstPath0 = OUTPATH(TestPauseResumeSingleClient_Session0);
+    const char* dstPath1 = OUTPATH(TestPauseResumeSingleClient_Session1);
     deleteFile(dstPath0);
     deleteFile(dstPath1);
 
-    // Submit one offline job, should start immediately.
-    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingJobPriority::kUnspecified,
+    // Submit one offline session, should start immediately.
+    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kUnspecified,
                                  kBitRate));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    // Test get job after starts.
-    EXPECT_TRUE(mClient1->getJob(0, srcPath0, dstPath0));
+    // Test get session after starts.
+    EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0));
 
-    // Submit one realtime job.
-    EXPECT_TRUE(mClient1->submit(1, srcPath1, dstPath1, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit one realtime session.
+    EXPECT_TRUE(
+            mClient1->submit(1, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate));
 
-    // Offline job should pause.
+    // Offline session should pause.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 0));
-    EXPECT_TRUE(mClient1->getJob(0, srcPath0, dstPath0));
+    EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0));
 
-    // Realtime job should start immediately, and run to finish.
+    // Realtime session should start immediately, and run to finish.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
 
-    // Test get job after finish fails.
-    EXPECT_TRUE(mClient1->getJob<fail>(1, "", ""));
+    // Test get session after finish fails.
+    EXPECT_TRUE(mClient1->getSession<fail>(1, "", ""));
 
-    // Then offline job should resume.
+    // Then offline session should resume.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 0));
-    // Test get job after resume.
-    EXPECT_TRUE(mClient1->getJob(0, srcPath0, dstPath0));
+    // Test get session after resume.
+    EXPECT_TRUE(mClient1->getSession(0, srcPath0, dstPath0));
 
-    // Offline job should finish.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
-    // Test get job after finish fails.
-    EXPECT_TRUE(mClient1->getJob<fail>(0, "", ""));
+    // Offline session should finish.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    // Test get session after finish fails.
+    EXPECT_TRUE(mClient1->getSession<fail>(0, "", ""));
 
     unregisterMultipleClients();
 }
 
 /*
- * Basic test for pause/resume with two clients, with one job each.
- * Top app's job should preempt the other app's job.
+ * Basic test for pause/resume with two clients, with one session each.
+ * Top app's session should preempt the other app's session.
  */
 TEST_F(MediaTranscodingServiceRealTest, TestPauseResumeMultiClients) {
     ALOGD("TestPauseResumeMultiClients starting...");
@@ -256,33 +262,35 @@
     ALOGD("Moving app A to top...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName));
 
-    // Submit job to Client1.
-    ALOGD("Submitting job to client1 (app A) ...");
-    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit session to Client1.
+    ALOGD("Submitting session to client1 (app A) ...");
+    EXPECT_TRUE(
+            mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate));
 
-    // Client1's job should start immediately.
+    // Client1's session should start immediately.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
 
     ALOGD("Moving app B to top...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName));
 
-    // Client1's job should continue to run, since Client2 (app B) doesn't have any job.
+    // Client1's session should continue to run, since Client2 (app B) doesn't have any session.
     EXPECT_EQ(mClient1->pop(1000000), EventTracker::NoEvent);
 
-    // Submit job to Client2.
-    ALOGD("Submitting job to client2 (app B) ...");
-    EXPECT_TRUE(mClient2->submit(0, srcPath1, dstPath1, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit session to Client2.
+    ALOGD("Submitting session to client2 (app B) ...");
+    EXPECT_TRUE(
+            mClient2->submit(0, srcPath1, dstPath1, TranscodingSessionPriority::kNormal, kBitRate));
 
-    // Client1's job should pause, client2's job should start.
+    // Client1's session should pause, client2's session should start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 0));
     EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0));
 
-    // Client2's job should finish, then Client1's job should resume.
-    EXPECT_EQ(mClient2->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(2), 0));
+    // Client2's session should finish, then Client1's session should resume.
+    EXPECT_EQ(mClient2->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(2), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 0));
 
-    // Client1's job should finish.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    // Client1's session should finish.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
 
     unregisterMultipleClients();
 
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
index 31697d5..bf99efc 100644
--- a/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
+++ b/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
@@ -55,13 +55,13 @@
 /**
  * Basic testing for handling resource lost.
  *
- * This test starts a transcoding job (that's somewhat long and takes several seconds),
+ * This test starts a transcoding session (that's somewhat long and takes several seconds),
  * then launches an activity that allocates video codec instances until it hits insufficient
  * resource error. Because the activity is running in foreground,
  * ResourceManager would reclaim codecs from transcoding service which should
- * cause the job to be paused. The activity will hold the codecs for a few seconds
+ * cause the session to be paused. The activity will hold the codecs for a few seconds
  * before releasing them, and the transcoding service should be able to resume
- * and complete the job.
+ * and complete the session.
  */
 TEST_F(MediaTranscodingServiceResourceTest, TestResourceLost) {
     ALOGD("TestResourceLost starting...");
@@ -79,21 +79,22 @@
     ALOGD("Moving app A to top...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName));
 
-    // Submit job to Client1.
-    ALOGD("Submitting job to client1 (app A) ...");
-    EXPECT_TRUE(mClient1->submit(0, srcPath0, dstPath0, TranscodingJobPriority::kNormal, kBitRate));
+    // Submit session to Client1.
+    ALOGD("Submitting session to client1 (app A) ...");
+    EXPECT_TRUE(
+            mClient1->submit(0, srcPath0, dstPath0, TranscodingSessionPriority::kNormal, kBitRate));
 
-    // Client1's job should start immediately.
+    // Client1's session should start immediately.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
 
     // Launch ResourcePolicyTestActivity, which will try to allocate up to 32
     // instances, which should trigger insufficient resources on most devices.
     // (Note that it's possible that the device supports a very high number of
-    // resource instances, in which case we'll simply require that the job completes.)
+    // resource instances, in which case we'll simply require that the session completes.)
     ALOGD("Launch ResourcePolicyTestActivity...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kResourcePolicyTestActivity));
 
-    // The basic requirement is that the job should complete. Wait for finish
+    // The basic requirement is that the session should complete. Wait for finish
     // event to come and pop up all events received.
     std::list<EventTracker::Event> events;
     EXPECT_TRUE(mClient1->waitForSpecificEventAndPop(EventTracker::Finished(CLIENT(1), 0), &events,
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
index 789b493..7dfda44 100644
--- a/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
+++ b/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
@@ -23,9 +23,9 @@
 #include <aidl/android/media/IMediaTranscodingService.h>
 #include <aidl/android/media/ITranscodingClient.h>
 #include <aidl/android/media/ITranscodingClientCallback.h>
-#include <aidl/android/media/TranscodingJobParcel.h>
-#include <aidl/android/media/TranscodingJobPriority.h>
 #include <aidl/android/media/TranscodingRequestParcel.h>
+#include <aidl/android/media/TranscodingSessionParcel.h>
+#include <aidl/android/media/TranscodingSessionPriority.h>
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -44,15 +44,15 @@
 
 namespace media {
 
-// Note that -1 is valid and means using calling pid/uid for the service. But only privilege caller could
-// use them. This test is not a privilege caller.
+// Note that -1 is valid and means using calling pid/uid for the service. But only privilege caller
+// could use them. This test is not a privilege caller.
 constexpr int32_t kInvalidClientPid = -5;
 constexpr int32_t kInvalidClientUid = -10;
 constexpr const char* kInvalidClientName = "";
 constexpr const char* kInvalidClientOpPackageName = "";
 
 constexpr int64_t kPaddingUs = 1000000;
-constexpr int64_t kJobWithPaddingUs = SimulatedTranscoder::kJobDurationUs + kPaddingUs;
+constexpr int64_t kSessionWithPaddingUs = SimulatedTranscoder::kSessionDurationUs + kPaddingUs;
 
 constexpr const char* kClientOpPackageName = "TestClientPackage";
 
@@ -135,18 +135,18 @@
     unregisterMultipleClients();
 }
 
-TEST_F(MediaTranscodingServiceSimulatedTest, TestJobIdIndependence) {
+TEST_F(MediaTranscodingServiceSimulatedTest, TestSessionIdIndependence) {
     registerMultipleClients();
 
     // Submit 2 requests on client1 first.
     EXPECT_TRUE(mClient1->submit(0, "test_source_file", "test_destination_file"));
     EXPECT_TRUE(mClient1->submit(1, "test_source_file", "test_destination_file"));
 
-    // Submit 2 requests on client2, jobId should be independent for each client.
+    // Submit 2 requests on client2, sessionId should be independent for each client.
     EXPECT_TRUE(mClient2->submit(0, "test_source_file", "test_destination_file"));
     EXPECT_TRUE(mClient2->submit(1, "test_source_file", "test_destination_file"));
 
-    // Cancel all jobs.
+    // Cancel all sessions.
     EXPECT_TRUE(mClient1->cancel(0));
     EXPECT_TRUE(mClient1->cancel(1));
     EXPECT_TRUE(mClient2->cancel(0));
@@ -155,10 +155,10 @@
     unregisterMultipleClients();
 }
 
-TEST_F(MediaTranscodingServiceSimulatedTest, TestSubmitCancelJobs) {
+TEST_F(MediaTranscodingServiceSimulatedTest, TestSubmitCancelSessions) {
     registerMultipleClients();
 
-    // Test jobId assignment.
+    // Test sessionId assignment.
     EXPECT_TRUE(mClient1->submit(0, "test_source_file_0", "test_destination_file"));
     EXPECT_TRUE(mClient1->submit(1, "test_source_file_1", "test_destination_file"));
     EXPECT_TRUE(mClient1->submit(2, "test_source_file_2", "test_destination_file"));
@@ -167,33 +167,33 @@
     EXPECT_TRUE(mClient1->submit<fail>(0, "", ""));
 
     // Test submit bad request (no valid sourceFilePath) fails.
-    EXPECT_TRUE(mClient1->submit<fail>(0, "src", "dst", TranscodingJobPriority::kNormal, 1000000,
-                                       kInvalidClientPid, kInvalidClientUid));
+    EXPECT_TRUE(mClient1->submit<fail>(0, "src", "dst", TranscodingSessionPriority::kNormal,
+                                       1000000, kInvalidClientPid, kInvalidClientUid));
 
-    // Test cancel non-existent job fails.
+    // Test cancel non-existent session fails.
     EXPECT_TRUE(mClient1->cancel<fail>(100));
 
-    // Job 0 should start immediately and finish in 2 seconds, followed by Job 1 start.
+    // Session 0 should start immediately and finish in 2 seconds, followed by Session 1 start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
 
-    // Test cancel valid jobId in random order.
-    // Test cancel finished job fails.
+    // Test cancel valid sessionId in random order.
+    // Test cancel finished session fails.
     EXPECT_TRUE(mClient1->cancel(2));
     EXPECT_TRUE(mClient1->cancel<fail>(0));
     EXPECT_TRUE(mClient1->cancel(1));
 
-    // Test cancel job again fails.
+    // Test cancel session again fails.
     EXPECT_TRUE(mClient1->cancel<fail>(1));
 
     // Test no more events arriving after cancel.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::NoEvent);
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::NoEvent);
 
     unregisterMultipleClients();
 }
 
-TEST_F(MediaTranscodingServiceSimulatedTest, TestGetJobs) {
+TEST_F(MediaTranscodingServiceSimulatedTest, TestGetSessions) {
     registerMultipleClients();
 
     // Submit 3 requests.
@@ -201,69 +201,69 @@
     EXPECT_TRUE(mClient1->submit(1, "test_source_file_1", "test_destination_file_1"));
     EXPECT_TRUE(mClient1->submit(2, "test_source_file_2", "test_destination_file_2"));
 
-    // Test get jobs by id.
-    EXPECT_TRUE(mClient1->getJob(2, "test_source_file_2", "test_destination_file_2"));
-    EXPECT_TRUE(mClient1->getJob(1, "test_source_file_1", "test_destination_file_1"));
-    EXPECT_TRUE(mClient1->getJob(0, "test_source_file_0", "test_destination_file_0"));
+    // Test get sessions by id.
+    EXPECT_TRUE(mClient1->getSession(2, "test_source_file_2", "test_destination_file_2"));
+    EXPECT_TRUE(mClient1->getSession(1, "test_source_file_1", "test_destination_file_1"));
+    EXPECT_TRUE(mClient1->getSession(0, "test_source_file_0", "test_destination_file_0"));
 
-    // Test get job by invalid id fails.
-    EXPECT_TRUE(mClient1->getJob<fail>(100, "", ""));
-    EXPECT_TRUE(mClient1->getJob<fail>(-1, "", ""));
+    // Test get session by invalid id fails.
+    EXPECT_TRUE(mClient1->getSession<fail>(100, "", ""));
+    EXPECT_TRUE(mClient1->getSession<fail>(-1, "", ""));
 
-    // Test get job after cancel fails.
+    // Test get session after cancel fails.
     EXPECT_TRUE(mClient1->cancel(2));
-    EXPECT_TRUE(mClient1->getJob<fail>(2, "", ""));
+    EXPECT_TRUE(mClient1->getSession<fail>(2, "", ""));
 
-    // Job 0 should start immediately and finish in 2 seconds, followed by Job 1 start.
+    // Session 0 should start immediately and finish in 2 seconds, followed by Session 1 start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
 
-    // Test get job after finish fails.
-    EXPECT_TRUE(mClient1->getJob<fail>(0, "", ""));
+    // Test get session after finish fails.
+    EXPECT_TRUE(mClient1->getSession<fail>(0, "", ""));
 
-    // Test get the remaining job 1.
-    EXPECT_TRUE(mClient1->getJob(1, "test_source_file_1", "test_destination_file_1"));
+    // Test get the remaining session 1.
+    EXPECT_TRUE(mClient1->getSession(1, "test_source_file_1", "test_destination_file_1"));
 
-    // Cancel remaining job 1.
+    // Cancel remaining session 1.
     EXPECT_TRUE(mClient1->cancel(1));
 
     unregisterMultipleClients();
 }
 
-TEST_F(MediaTranscodingServiceSimulatedTest, TestSubmitCancelWithOfflineJobs) {
+TEST_F(MediaTranscodingServiceSimulatedTest, TestSubmitCancelWithOfflineSessions) {
     registerMultipleClients();
 
-    // Submit some offline jobs first.
+    // Submit some offline sessions first.
     EXPECT_TRUE(mClient1->submit(0, "test_source_file_0", "test_destination_file_0",
-                                 TranscodingJobPriority::kUnspecified));
+                                 TranscodingSessionPriority::kUnspecified));
     EXPECT_TRUE(mClient1->submit(1, "test_source_file_1", "test_destination_file_1",
-                                 TranscodingJobPriority::kUnspecified));
+                                 TranscodingSessionPriority::kUnspecified));
 
-    // Job 0 should start immediately.
+    // Session 0 should start immediately.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
 
-    // Submit more real-time jobs.
+    // Submit more real-time sessions.
     EXPECT_TRUE(mClient1->submit(2, "test_source_file_2", "test_destination_file_2"));
     EXPECT_TRUE(mClient1->submit(3, "test_source_file_3", "test_destination_file_3"));
 
-    // Job 0 should pause immediately and job 2 should start.
+    // Session 0 should pause immediately and session 2 should start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 2));
 
-    // Job 2 should finish in 2 seconds and job 3 should start.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 2));
+    // Session 2 should finish in 2 seconds and session 3 should start.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 2));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 3));
 
-    // Cancel job 3 now
+    // Cancel session 3 now
     EXPECT_TRUE(mClient1->cancel(3));
 
-    // Job 0 should resume and finish in 2 seconds, followed by job 1 start.
+    // Session 0 should resume and finish in 2 seconds, followed by session 1 start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 0));
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
 
-    // Cancel remaining job 1.
+    // Cancel remaining session 1.
     EXPECT_TRUE(mClient1->cancel(1));
 
     unregisterMultipleClients();
@@ -280,16 +280,16 @@
     EXPECT_TRUE(status.isOk());
 
     // Test various operations on the client, should fail with ERROR_DISCONNECTED.
-    TranscodingJobParcel job;
+    TranscodingSessionParcel session;
     bool result;
-    status = client->getJobWithId(0, &job, &result);
+    status = client->getSessionWithId(0, &session, &result);
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
-    status = client->cancelJob(0, &result);
+    status = client->cancelSession(0, &result);
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 
     TranscodingRequestParcel request;
-    status = client->submitRequest(request, &job, &result);
+    status = client->submitRequest(request, &session, &result);
     EXPECT_EQ(status.getServiceSpecificError(), IMediaTranscodingService::ERROR_DISCONNECTED);
 }
 
@@ -308,41 +308,41 @@
     EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName));
 
     // Submit 3 requests.
-    ALOGD("Submitting job to client1 (app A) ...");
+    ALOGD("Submitting session to client1 (app A) ...");
     EXPECT_TRUE(mClient1->submit(0, "test_source_file_0", "test_destination_file_0"));
     EXPECT_TRUE(mClient1->submit(1, "test_source_file_1", "test_destination_file_1"));
     EXPECT_TRUE(mClient1->submit(2, "test_source_file_2", "test_destination_file_2"));
 
-    // Job 0 should start immediately.
+    // Session 0 should start immediately.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 0));
 
     ALOGD("Moving app B to top...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageB, kTestActivityName));
 
-    // Job 0 should continue and finish in 2 seconds, then job 1 should start.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
+    // Session 0 should continue and finish in 2 seconds, then session 1 should start.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 1));
 
-    ALOGD("Submitting job to client2 (app B) ...");
+    ALOGD("Submitting session to client2 (app B) ...");
     EXPECT_TRUE(mClient2->submit(0, "test_source_file_0", "test_destination_file_0"));
 
-    // Client1's job should pause, client2's job should start.
+    // Client1's session should pause, client2's session should start.
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Pause(CLIENT(1), 1));
     EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Start(CLIENT(2), 0));
 
     ALOGD("Moving app A back to top...");
     EXPECT_TRUE(ShellHelper::Start(kClientPackageA, kTestActivityName));
 
-    // Client2's job should pause, client1's job 1 should resume.
+    // Client2's session should pause, client1's session 1 should resume.
     EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Pause(CLIENT(2), 0));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Resume(CLIENT(1), 1));
 
-    // Client2's job 1 should finish in 2 seconds, then its job 2 should start.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
+    // Client2's session 1 should finish in 2 seconds, then its session 2 should start.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 1));
     EXPECT_EQ(mClient1->pop(kPaddingUs), EventTracker::Start(CLIENT(1), 2));
 
-    // After client2's jobs finish, client1's job should resume.
-    EXPECT_EQ(mClient1->pop(kJobWithPaddingUs), EventTracker::Finished(CLIENT(1), 2));
+    // After client2's sessions finish, client1's session should resume.
+    EXPECT_EQ(mClient1->pop(kSessionWithPaddingUs), EventTracker::Finished(CLIENT(1), 2));
     EXPECT_EQ(mClient2->pop(kPaddingUs), EventTracker::Resume(CLIENT(2), 0));
 
     unregisterMultipleClients();
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index ceefe93..b139be1 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -182,11 +182,12 @@
             : AUDIO_SOURCE_DEFAULT;
     audio_flags_mask_t flags;
     if (direction == AAUDIO_DIRECTION_OUTPUT) {
-        flags = AUDIO_FLAG_LOW_LATENCY
-            | AAudioConvert_allowCapturePolicyToAudioFlagsMask(params->getAllowedCapturePolicy());
+        flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
+                | AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+                        params->getAllowedCapturePolicy()));
     } else {
-        flags = AUDIO_FLAG_LOW_LATENCY
-            | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive());
+        flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
+                | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive()));
     }
     return {
             .content_type = contentType,