Merge "Add null check for osAppId" into stage-aosp-udc-ts-dev am: 848650fd00 am: b668cff7ff am: 98843a2b8b

Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/24698008

Change-Id: Ie974d9a85fa633142080a318ecddf4a69fb84626
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1eca2a1..2e9d9ab 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -85,3 +85,4 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.1*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.cas@1.1*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/wifi/1.4/android.hardware.wifi@1.4-adapter_genc++/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/automotive/vehicle/aidl/android.hardware.automotive.vehicle-V2-ndk-source/)
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 2116e21..de7aa35 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -10,3 +10,4 @@
 aosp_hook_confirmationui = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} confirmationui
 aosp_hook_gatekeeper = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} gatekeeper
 aosp_hook_keymaster = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} keymaster
+generate_vehicle_property_enums = ${REPO_ROOT}/hardware/interfaces/automotive/vehicle/tools/generate_annotation_enums.py --android_build_top ${REPO_ROOT} --preupload_files ${PREUPLOAD_FILES} --check_only
diff --git a/apexkey/Android.bp b/apexkey/Android.bp
new file mode 100644
index 0000000..e74717a
--- /dev/null
+++ b/apexkey/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.key",
+    public_key: "com.android.hardware.avbpubkey",
+    private_key: "com.android.hardware.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.certificate",
+    certificate: "com.android.hardware",
+}
diff --git a/apexkey/com.android.hardware.avbpubkey b/apexkey/com.android.hardware.avbpubkey
new file mode 100644
index 0000000..12f0370
--- /dev/null
+++ b/apexkey/com.android.hardware.avbpubkey
Binary files differ
diff --git a/apexkey/com.android.hardware.pem b/apexkey/com.android.hardware.pem
new file mode 100644
index 0000000..4d2882b
--- /dev/null
+++ b/apexkey/com.android.hardware.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCmirL5vFcGDqg9
+JqKZwRqzPr76t8aqJSu+UOdnlmqBLmUBaeun2KwRsZiLku933m5MNv+CPnVQW7ij
+z0lv0z/qB8SXN+KAgSqRdIjL1ySQgp8ygKHu+GcvbMFj9pVuqufwSrEOY9Un1RRY
+InDDj88c/aNbCw64d1QVedgUIs5KDDLjOzkcrrbH+Th26r2YjhlRKQXCZT5jW1fY
+2gJg5LPeuM4fI63ESxFyRTY/V8E3LbAuTYKBSrHRbec22oCkL/pUilJBe2r8aNyp
+ACWEJB96uWdKmIYDCdj6r6SNzHM3S4X+l1C9/Gi9UNK8nuIAI3v2qW07S2RABAWX
+vKfE8rIKAdFmajGlHKfRe6IL9ka1/rsM1xgDr2/FgEsyRgrfJvlvvMb7ampMgTKu
+Az/hv4siSaDD2E3JrRyh3nNxTCuIABla7/jGmNz6vIdwTRJsa2RIEezkeMiUy+jp
+VyeYsWIEBmQwZ5+k6YbdrKTULaay3UJ6/YXEQY9Sbg0JL/7sjQWILwnrtab3/jsn
+iWsr59Qsaf+q3PnrWPCXT/KC8DwKi/2zSWfCX8MHreqaoozjfWXeD87lnBAhukBS
+984xWEmStJGFQG29J4sF4NmgO1I8GPqQRtoB6ghme11U2EX0vIqrDNccX12ohqgh
+CfwMXX64WV5fWscmSLZin5xK+AN+/wIDAQABAoICABLDnda1ebic/ielqrxYHYIE
+l8/31NJmzb7rrqblM6rKZ2b5YCvRJdH4iI9xRrnivdqod7FdCCq9qtgKCuQmkRT1
+Oxkumr6PzxQEZUVSQDRoAzfVdmlOY5HcVw3EQqHtb6SLRdexN9r9DwW/G6VtFpDV
+owom/Mmb6EVjLQ1XvpZpOXKQwaaRqNZvJgV//Uyq9f9G9/cnIRhguk0cgxgXrIxz
+lgW8J1/udVDCq5IHeSWWaDtPUFzw5YgLMfnkNIpLPZE45HusRCmcRwBjm9Z/m2xg
+Z1roRHEjMudL0uaHGpQoVjiRI+/D+Kkb6iKGZEBPvy/TdxMvM2RjD55BC0YNcjGv
+kXTMLwj2ke824rUPJJOYN8bJFIpOYblMcbDrxYVlDZetKOMc6EJw90xaj4za2IMS
+vWDxZx1WQPcn+B/nUvrMMOTN6MkNYKR97lmxBYP6TeCiUUytZiCF72cvvpYcdhE9
+zzOES5kVakSE8NnLTH9xAjrpAguxI9gqxeyLALhz/Rb46fgWwnhcBdqmPtez/IHb
+BgF81SSobSaBlzLcnRyrjwBRWA21DP8U/ApUkmHR/Lm1BJejzxf1hj35Hp9XUwdC
+JK7aoVnjuko/l5TPn0Bvm4pcBArG0AUL75GlRgDJTVCDZbLFR/2JZlnZ9optvN6E
+vniu3HwBRHDHn0K1DqIBAoIBAQDpdBJtyizIlZ5p6k1f0wWE/B2riPzPwv/a+ygD
+GOtzWsukyZjWHXVPjx2XY3bwlbusiqhJE1OcF+oymHTtSSv3VsqMmo2VDIj8d21T
+ycpBvV7+mcehGk6o6lGTJAiPc1wVMajmM0Co2LQb4hRvf2p8dW6+RRn5c3o288B5
+e45zpbq9+l9PMpgrmOBU3m652JmGK8JqQKeKKT96kZQVf/U3ArMif+jW2piAZnmG
+CS00el0K0RtZe/iKrFftoD27ai9GNZx/Z1p55x+9vUD15LiQ/MK0Bk/f9b24zE98
+6T07KAGPB5gXWlSs2yEk4Waufjw3JSYXs18kEoMklTA0IGGhAoIBAQC2oEwGQZI0
+oR1oL7P76FyMNjtp2T2wYnOcnGeKjp4vxZWTZNRfNUmzGqSamVE1ZPhj721sAImS
+mk1pUJbglkpP6aMDNXzA6Z50PuXfhF5+dXBrLftT1tcNo/8/ysd/iKsi1C6hWZ9L
+YYt/7uR8wazeG65jahsOKEfCrNyDBQzyoSft1qfVTvYzxUVmJRQr5S7H0c9jPTwg
+Qj+/RQsDOspsJrBC5+H0tLPkvZDdZCYvdBzVWFL7npHd0fy53TmT6kEjDwwAiE8W
+VggvzkhHOnprAiwq36nlpGo3um5Ona98dXWZ4rfELEdSUOiWCz2Gzz7IL+H8uhen
+iXQAtlAlMVyfAoIBAQDDGmlobgW9YSVyWQlvIxnCyT02pZa7P7m6VhpbdFEaJ/B3
+eLANibMH2ZCee9bkPA8LpRn9cHR4yJfGzxkxUey3mkZO+b+HqGE3tcudsdAh3tTs
+LLLk1eqVSrcAJKYu1PdJEyaXtI++TNVBVFFF2ZOyDiaOR4vsqPCjylS6cmNcDU6j
+BQLwWlVIYkxhQUACe53avumNCRm74rsVgWLkEPtrjQsOsx1xqmC3Nm0rcrHf4L+v
+kZCs2Wme42fcxQWygoydvaJb65F2vY0OcoM+vXbuXP+PmpLYljSHo+BugTLWJJog
+4fTe13RavgvWGbZJ8F/8qkRKnHLP39TQFwqhFcrhAoIBAQCZYipX+syUHVl4ftA4
+2+CW9pmR/h5cvWOCfq5L5hqf3uAQqlfgGv5qSg9DtU9KfCJOtPH/CriBA83OjRwb
+Rr7lPUJnWI4N7GjkE0u4HhHLPlGMA1OaB9AZKcsgxewmhh/OIc2EQKSUiDnE2lzX
+F0dcSH2AC8brbhNPQyX1eNF2GrpRfL77XdVUh/QQpUW61EMlGmeHXw/XvCyUNaXZ
+MZB/o0LY/q59eyO4EyrPduTHaEsrOIKByJ2UY2BSrqZEQDQzANlAvTtHdDxuAmAc
+StY0d9+mprGoKR347kDlEHUqH/EErTFQtyuzzDZ8hrZHOlrtgaHZRGbHlJ90Vasc
+gcfbAoIBAEIR0dtmd38dC7r0h0SZ7ORIvm9F8JRs+wKdWjiPfWLK3trR/jxRx6Eh
+xrrJEoRCeUmT6rc0TwUkzow5ApcEY338KmsqKVbm3iGfPpvZFEO44vBrg3280QBM
+PerIrEfidflUAE9QXNoBpvvnh2KXIOsvyN2MeY2SAyebPJQJtWzJkP35Y8fOtZkJ
+VtIhYj2wvFuobl7iuxKJG0cn4xL3OLysc03oX7Al2qA42hUCy7UMsTT6ZAPWd49+
+3gOFrqmaV3Hu5KY2HaX6Yly5ohhQWSkSL1kZMo9Uq6tTM+2HFzFU6sveFbWW/XQc
+rWnazDdd1WkHT6+nzA/NX24OzPjiUk0=
+-----END PRIVATE KEY-----
diff --git a/apexkey/com.android.hardware.pk8 b/apexkey/com.android.hardware.pk8
new file mode 100644
index 0000000..97007d2
--- /dev/null
+++ b/apexkey/com.android.hardware.pk8
Binary files differ
diff --git a/apexkey/com.android.hardware.x509.pem b/apexkey/com.android.hardware.x509.pem
new file mode 100644
index 0000000..2728a23
--- /dev/null
+++ b/apexkey/com.android.hardware.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF6TCCA9ECFDAU6pJXjblHA/w9a354h2QUOharMA0GCSqGSIb3DQEBCwUAMIGv
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTErMCkGA1UEAwwiY29t
+LmFuZHJvaWQuaGFyZHdhcmUudGhyZWFkbmV0d29yazAgFw0yMzA4MjQwNjE4MTZa
+GA80NzYxMDcyMDA2MTgxNlowga8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lk
+MRAwDgYDVQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJv
+aWQuY29tMSswKQYDVQQDDCJjb20uYW5kcm9pZC5oYXJkd2FyZS50aHJlYWRuZXR3
+b3JrMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5eMXZfeadUJiqZ0b
+kbXYSbzjd1opoeAVk/+LxGyBLLPy2z2EAeuUBx8HYEJhyPOyUrs3ohP6OvAtE8O4
+JeEbGBzqOymusKbve8ght7tDjUuTYsbBsKQWw1Gu/UUK7x3lc6zD+wDTK/5NUoTA
+I/5lI8Q4+NHCI1jb/uBRGSlzSO+k2A2oVUPdyaWWgGhLeEiXKo+Xy6XXduhFK1wc
+iSCgVyuQkZnbrJrGCGS1LD1MavsfBTthD3jfuOq+YqMjGjdi6xVPG3fZnwwdVNzW
+mSFwWwHif56ZAtxyZVtQOAksTqwAwGrUjhn70rw5eLBQjXIL1061cLrOZ4XlRSZj
+kHB8mwr6OQOw7isMORO0h+NNJ+5POa5V9rGylqk/hn1vzcTX62YUZy1N6b3rfGc2
+p9LA6STjvoXLeCFaSIc+LfTiHOamkg7LuLlsQ/AIoXeuaLyWAgg4ls2U8IG1Mdkz
+BClX5vMG/At6yZqHiCIbCU8V8VSCz7Rtuu+C/87G5Pwb/G1r4FHXr9x7d0qj4rWV
+u9MhdzvZWoTTnEzDA+DWPQM/ILkGdkSj0g4yC8GR/F5p7xWQ0vqyMyM/ii1KzWVs
+ZJFUxzpGX99C0mfjT2hezHzfEyisPec39PFbdxzC756yP1Le8I5qjMbjl+XeFjxO
+REoC0nDFgHEI7C5RunT1osKmpDUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA3HPY
++nHGFE9aFQbEsjvotuxguLMKmrgQ44yGBTr9349MPvnxGDdz1HPWs/m456k9HQxt
+1YWV+xr56NS37UDVMkqS7hzCkJe/LdMT51qvUS+hPHLzSuZNKuFAaCOb8WDa7tGQ
+MuvISlb6T7G512fUdFDRjFjnIXDLTYANzoxI3cqs2N2xQNxsL8uIJ79RWlPm2Upz
+Y5Ad55kv3EygWgirvZnSNo27E/Tt4Bo9KS0HsYXVHgWK9zHHtup1vDOntJ8bX16C
+rP7e8SELanPbUtyIUDcf14P3EFztUYBZIXO2HUSsoOTX3+Hd592h7EsnGDdlWSLU
+oreaRWCAMh4TKI/eP+1N35b8zmPMHaG+WsWjdDPrs6oNpr2MMA4U8AHGW2d6QY0N
+xZ/VhhbjbHMgmmB3Q2LXZZufbSEBawBfuFjhodfmKSgTjNCTYXtTiT/pL2w0PqEM
+v4UxrGD0uFQafFKuxQfL2LYG5tg46daRrT3BoIqLKoseTuykzW4z08NuurwsLvmy
+t7njqMxlf/tN9o+d3D3lWHQpiDJ8kC/TjgKBj7iQTCOJeShutxyR2F3R+3+kUXpP
+w7O4QfoqZDca1qtJRtew2tpmOb1hFkj/QzRi5WRx/oM/Cm0yMttYIA+4vCJeDOja
+gngrtH3jmEwMME71HDyXHlcCIIt95odXoBSBKgk=
+-----END CERTIFICATE-----
diff --git a/atrace/1.0/vts/functional/OWNERS b/atrace/OWNERS
similarity index 97%
rename from atrace/1.0/vts/functional/OWNERS
rename to atrace/OWNERS
index 31043aa..d76ffa6 100644
--- a/atrace/1.0/vts/functional/OWNERS
+++ b/atrace/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 837454
+
 wvw@google.com
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 3e06595..81c99f7 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -4,6 +4,9 @@
       "name": "VtsHalAudioCoreTargetTest"
     },
     {
+      "name": "audio_policy_config_xml_converter_tests"
+    },
+    {
       "name": "VtsHalAudioEffectFactoryTargetTest"
     },
     {
diff --git a/audio/aidl/android/hardware/audio/core/stream-in-async-sm.gv b/audio/aidl/android/hardware/audio/core/stream-in-async-sm.gv
index 818b18e..6b69845 100644
--- a/audio/aidl/android/hardware/audio/core/stream-in-async-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-in-async-sm.gv
@@ -14,8 +14,8 @@
 
 // To render: dot -Tpng stream-in-async-sm.gv -o stream-in-async-sm.png
 digraph stream_in_async_state_machine {
-    node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
-    node [shape=point width=0.5] F;
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle width=0.5] F;
     node [shape=oval width=1];
     node [fillcolor=lightgreen] STANDBY;  // buffer is empty
     node [fillcolor=tomato] CLOSED;
diff --git a/audio/aidl/android/hardware/audio/core/stream-in-sm.gv b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
index 805dc32..aa7af54 100644
--- a/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
@@ -14,8 +14,8 @@
 
 // To render: dot -Tpng stream-in-sm.gv -o stream-in-sm.png
 digraph stream_in_state_machine {
-    node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
-    node [shape=point width=0.5] F;
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle width=0.5] F;
     node [shape=oval width=1];
     node [fillcolor=lightgreen] STANDBY;  // buffer is empty
     node [fillcolor=tomato] CLOSED;
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
index 501dc01..a3f0de9 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
@@ -14,8 +14,8 @@
 
 // To render: dot -Tpng stream-out-async-sm.gv -o stream-out-async-sm.png
 digraph stream_out_async_state_machine {
-    node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
-    node [shape=point width=0.5] F;
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle width=0.5] F;
     node [shape=oval width=1];
     node [fillcolor=lightgreen] STANDBY;  // buffer is empty
     node [fillcolor=lightgreen] IDLE;     // buffer is empty
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
index 47e7fda..23fb5d9 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
@@ -14,8 +14,8 @@
 
 // To render: dot -Tpng stream-out-sm.gv -o stream-out-sm.png
 digraph stream_out_state_machine {
-    node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
-    node [shape=point width=0.5] F;
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle width=0.5] F;
     node [shape=oval width=1];
     node [fillcolor=lightgreen] STANDBY;  // buffer is empty
     node [fillcolor=lightgreen] IDLE;     // buffer is empty
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
index c88521e..ce369ba 100644
--- a/audio/aidl/android/hardware/audio/effect/state.gv
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -25,12 +25,12 @@
 
     I -> INIT[label = "IFactory.createEffect" labelfontcolor = "navy"];
     INIT -> F[label = "IFactory.destroyEffect"];
-    INIT -> IDLE[label = "open()" labelfontcolor = "lime"];
-    IDLE -> PROCESSING[label = "command(START"];
-    PROCESSING -> IDLE[label = "command(STOP)\ncommand(RESET)"];
-    IDLE -> INIT[label = "close()"];
+    INIT -> IDLE[label = "IEffect.open()" labelfontcolor = "lime"];
+    IDLE -> PROCESSING[label = "IEffect.command(START"];
+    PROCESSING -> IDLE[label = "IEffect.command(STOP)\nIEffect.command(RESET)"];
+    IDLE -> INIT[label = "IEffect.close()"];
 
-    INIT -> INIT[label = "getState\ngetDescriptor"];
-    IDLE -> IDLE[label = "getXXX\nsetParameter\ncommand(RESET)"];
-    PROCESSING -> PROCESSING[label = "getXXX\nsetParameter"];
+    INIT -> INIT[label = "IEffect.getState\nIEffect.getDescriptor"];
+    IDLE -> IDLE[label = "IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.command(RESET)"];
+    PROCESSING -> PROCESSING[label = "IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor"];
 }
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
index 0d2121c..8107655 100644
--- a/audio/aidl/common/StreamWorker.cpp
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -106,6 +106,9 @@
         std::lock_guard<std::mutex> lock(mWorkerLock);
         mWorkerState = error.empty() ? WorkerState::RUNNING : WorkerState::STOPPED;
         mError = error;
+#if defined(__ANDROID__)
+        mTid = pthread_gettid_np(pthread_self());
+#endif
     }
     mWorkerCv.notify_one();
     if (!error.empty()) return;
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
index e9c1070..efdcc81 100644
--- a/audio/aidl/common/include/StreamWorker.h
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <sys/types.h>
+
 #include <atomic>
 #include <condition_variable>
 #include <mutex>
@@ -52,6 +54,10 @@
         std::lock_guard<std::mutex> lock(mWorkerLock);
         return mError;
     }
+    pid_t getTid() {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        return mTid;
+    }
     void stop();
     // Direct use of 'join' assumes that the StreamLogic is not intended
     // to run forever, and is guaranteed to exit by itself. This normally
@@ -78,6 +84,7 @@
     std::condition_variable mWorkerCv;
     WorkerState mWorkerState GUARDED_BY(mWorkerLock) = WorkerState::INITIAL;
     std::string mError GUARDED_BY(mWorkerLock);
+    pid_t mTid GUARDED_BY(mWorkerLock) = -1;
     // The atomic lock-free variable is used to prevent priority inversions
     // that can occur when a high priority worker tries to acquire the lock
     // which has been taken by a lower priority control thread which in its turn
@@ -143,6 +150,7 @@
     void resume() { mThread.resume(); }
     bool hasError() { return mThread.hasError(); }
     std::string getError() { return mThread.getError(); }
+    pid_t getTid() { return mThread.getTid(); }
     void stop() { mThread.stop(); }
     void join() { mThread.join(); }
     bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 305c924..3b08de7 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -29,6 +29,21 @@
 #include <aidl/android/media/audio/common/AudioMode.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
 #include <aidl/android/media/audio/common/PcmType.h>
+#include <android/binder_auto_utils.h>
+
+namespace ndk {
+
+// This enables use of 'error/expected_utils' for ScopedAStatus.
+
+inline bool errorIsOk(const ScopedAStatus& s) {
+    return s.isOk();
+}
+
+inline std::string errorToString(const ScopedAStatus& s) {
+    return s.getDescription();
+}
+
+}  // namespace ndk
 
 namespace aidl::android::hardware::audio::common {
 
@@ -102,7 +117,8 @@
 constexpr bool isDefaultAudioFormat(
         const ::aidl::android::media::audio::common::AudioFormatDescription& desc) {
     return desc.type == ::aidl::android::media::audio::common::AudioFormatType::DEFAULT &&
-           desc.pcm == ::aidl::android::media::audio::common::PcmType::DEFAULT;
+           desc.pcm == ::aidl::android::media::audio::common::PcmType::DEFAULT &&
+           desc.encoding.empty();
 }
 
 constexpr bool isTelephonyDeviceType(
@@ -111,30 +127,6 @@
            device == ::aidl::android::media::audio::common::AudioDeviceType::OUT_TELEPHONY_TX;
 }
 
-constexpr bool isUsbInputDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
-    switch (type) {
-        case ::aidl::android::media::audio::common::AudioDeviceType::IN_DOCK:
-        case ::aidl::android::media::audio::common::AudioDeviceType::IN_ACCESSORY:
-        case ::aidl::android::media::audio::common::AudioDeviceType::IN_DEVICE:
-        case ::aidl::android::media::audio::common::AudioDeviceType::IN_HEADSET:
-            return true;
-        default:
-            return false;
-    }
-}
-
-constexpr bool isUsbOutputtDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
-    switch (type) {
-        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DOCK:
-        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_ACCESSORY:
-        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DEVICE:
-        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_HEADSET:
-            return true;
-        default:
-            return false;
-    }
-}
-
 constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode mode) {
     return std::find(kValidAudioModes.begin(), kValidAudioModes.end(), mode) !=
            kValidAudioModes.end();
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
index f7a30b9..2b65740 100644
--- a/audio/aidl/common/tests/streamworker_tests.cpp
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -87,6 +87,7 @@
 TEST_P(StreamWorkerInvalidTest, Uninitialized) {
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_FALSE(worker.hasError());
+    EXPECT_LE(worker.getTid(), 0);
 }
 
 TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
@@ -105,6 +106,9 @@
     EXPECT_FALSE(worker.start());
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_TRUE(worker.hasError());
+#if defined(__ANDROID__)
+    EXPECT_GT(worker.getTid(), 0);
+#endif
 }
 
 TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
@@ -136,12 +140,16 @@
 TEST_P(StreamWorkerTest, Uninitialized) {
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_FALSE(worker.hasError());
+    EXPECT_LE(worker.getTid(), 0);
 }
 
 TEST_P(StreamWorkerTest, Start) {
     ASSERT_TRUE(worker.start());
     EXPECT_TRUE(worker.waitForAtLeastOneCycle());
     EXPECT_FALSE(worker.hasError());
+#if defined(__ANDROID__)
+    EXPECT_GT(worker.getTid(), 0);
+#endif
 }
 
 TEST_P(StreamWorkerTest, StartStop) {
diff --git a/audio/aidl/default/AidlConversionXsdc.cpp b/audio/aidl/default/AidlConversionXsdc.cpp
new file mode 100644
index 0000000..c404d67
--- /dev/null
+++ b/audio/aidl/default/AidlConversionXsdc.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_AidlXsdc"
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+
+#include "core-impl/AidlConversionXsdc.h"
+
+using aidl::android::media::audio::common::AudioFormatDescription;
+
+namespace xsd = android::audio::policy::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<AudioFormatDescription> xsdc2aidl_AudioFormatDescription(const std::string& xsdc) {
+    return legacy2aidl_audio_format_t_AudioFormatDescription(::android::formatFromString(xsdc));
+}
+
+ConversionResult<SurroundSoundConfig::SurroundFormatFamily> xsdc2aidl_SurroundFormatFamily(
+        const ::xsd::SurroundFormats::Format& xsdc) {
+    SurroundSoundConfig::SurroundFormatFamily aidl;
+    aidl.primaryFormat = VALUE_OR_RETURN(xsdc2aidl_AudioFormatDescription(xsdc.getName()));
+    if (xsdc.hasSubformats()) {
+        aidl.subFormats = VALUE_OR_RETURN(convertContainer<std::vector<AudioFormatDescription>>(
+                xsdc.getSubformats(), xsdc2aidl_AudioFormatDescription));
+    }
+    return aidl;
+}
+
+ConversionResult<SurroundSoundConfig> xsdc2aidl_SurroundSoundConfig(
+        const ::xsd::SurroundSound& xsdc) {
+    SurroundSoundConfig aidl;
+    if (!xsdc.hasFormats() || !xsdc.getFirstFormats()->hasFormat()) return aidl;
+    aidl.formatFamilies = VALUE_OR_RETURN(
+            convertContainer<std::vector<SurroundSoundConfig::SurroundFormatFamily>>(
+                    xsdc.getFirstFormats()->getFormat(), xsdc2aidl_SurroundFormatFamily));
+    return aidl;
+}
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index c9edae0..bb8d76f 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -18,6 +18,7 @@
         "libbinder_ndk",
         "libcutils",
         "libfmq",
+        "libnbaio_mono",
         "libstagefright_foundation",
         "libtinyalsav2",
         "libutils",
@@ -65,20 +66,35 @@
     ],
     export_include_dirs: ["include"],
     srcs: [
+        "AidlConversionXsdc.cpp",
         "AudioPolicyConfigXmlConverter.cpp",
         "Bluetooth.cpp",
         "Config.cpp",
         "Configuration.cpp",
         "EngineConfigXmlConverter.cpp",
         "Module.cpp",
+        "ModulePrimary.cpp",
         "SoundDose.cpp",
         "Stream.cpp",
-        "StreamStub.cpp",
+        "StreamSwitcher.cpp",
         "Telephony.cpp",
+        "alsa/Mixer.cpp",
+        "alsa/ModuleAlsa.cpp",
+        "alsa/StreamAlsa.cpp",
+        "alsa/Utils.cpp",
+        "bluetooth/DevicePortProxy.cpp",
+        "bluetooth/ModuleBluetooth.cpp",
+        "bluetooth/StreamBluetooth.cpp",
+        "primary/PrimaryMixer.cpp",
+        "primary/StreamPrimary.cpp",
+        "r_submix/ModuleRemoteSubmix.cpp",
+        "r_submix/SubmixRoute.cpp",
+        "r_submix/StreamRemoteSubmix.cpp",
+        "stub/ModuleStub.cpp",
+        "stub/StreamStub.cpp",
         "usb/ModuleUsb.cpp",
         "usb/StreamUsb.cpp",
         "usb/UsbAlsaMixerControl.cpp",
-        "usb/UsbAlsaUtils.cpp",
     ],
     generated_sources: [
         "audio_policy_configuration_aidl_default",
@@ -92,6 +108,23 @@
         "audio_policy_configuration_aidl_default",
         "audio_policy_engine_configuration_aidl_default",
     ],
+    shared_libs: [
+        "android.hardware.bluetooth.audio-V3-ndk",
+        "libaudio_aidl_conversion_common_ndk",
+        "libbluetooth_audio_session_aidl",
+        "libmedia_helper",
+        "libstagefright_foundation",
+    ],
+    export_shared_lib_headers: [
+        "libaudio_aidl_conversion_common_ndk",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_NDK",
+    ],
 }
 
 cc_binary {
@@ -108,7 +141,65 @@
     static_libs: [
         "libaudioserviceexampleimpl",
     ],
+    shared_libs: [
+        "android.hardware.bluetooth.audio-V3-ndk",
+        "libaudio_aidl_conversion_common_ndk",
+        "libbluetooth_audio_session_aidl",
+        "libmedia_helper",
+        "libstagefright_foundation",
+    ],
     srcs: ["main.cpp"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_NDK",
+    ],
+}
+
+cc_test {
+    name: "audio_policy_config_xml_converter_tests",
+    vendor_available: true,
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+        "latest_android_hardware_audio_core_ndk_static",
+    ],
+    shared_libs: [
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudioaidlcommon",
+        "libaudioutils",
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libmedia_helper",
+        "libstagefright_foundation",
+        "libutils",
+        "libxml2",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libaudioaidl_headers",
+        "libxsdc-utils",
+    ],
+    generated_sources: [
+        "audio_policy_configuration_aidl_default",
+    ],
+    generated_headers: [
+        "audio_policy_configuration_aidl_default",
+    ],
+    srcs: [
+        "AudioPolicyConfigXmlConverter.cpp",
+        "tests/AudioPolicyConfigXmlConverterTest.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_NDK",
+    ],
+    test_suites: ["general-tests"],
 }
 
 cc_defaults {
diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
index 6290912..7452c8e 100644
--- a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
+++ b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
@@ -21,11 +21,17 @@
 #include <functional>
 #include <unordered_map>
 
+#define LOG_TAG "AHAL_ApmXmlConverter"
+#include <android-base/logging.h>
+
 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <media/stagefright/foundation/MediaDefs.h>
 #include <system/audio-base-utils.h>
 
+#include "core-impl/AidlConversionXsdc.h"
 #include "core-impl/AudioPolicyConfigXmlConverter.h"
 
+using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
 using aidl::android::media::audio::common::AudioHalVolumeCurve;
 using aidl::android::media::audio::common::AudioHalVolumeGroup;
@@ -68,13 +74,13 @@
                     getXsdcConfig()->getVolumes());
         }
         aidlVolumeCurve.curvePoints =
-                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                         mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
                         std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
                                   std::placeholders::_1));
     } else {
         aidlVolumeCurve.curvePoints =
-                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                         xsdcVolumeCurve.getPoint(),
                         std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
                                   std::placeholders::_1));
@@ -87,6 +93,22 @@
             convertVolumeCurveToAidl(xsdcVolumeCurve));
 }
 
+const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
+    static const SurroundSoundConfig aidlSurroundSoundConfig = [this]() {
+        if (auto xsdcConfig = getXsdcConfig(); xsdcConfig && xsdcConfig->hasSurroundSound()) {
+            auto configConv = xsdc2aidl_SurroundSoundConfig(*xsdcConfig->getFirstSurroundSound());
+            if (configConv.ok()) {
+                return configConv.value();
+            }
+            LOG(ERROR) << "There was an error converting surround formats to AIDL: "
+                       << configConv.error();
+        }
+        LOG(WARNING) << "Audio policy config does not have <surroundSound> section, using default";
+        return getDefaultSurroundSoundConfig();
+    }();
+    return aidlSurroundSoundConfig;
+}
+
 const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
     if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
         getXsdcConfig()->hasVolumes()) {
@@ -95,6 +117,47 @@
     return mAidlEngineConfig;
 }
 
+// static
+const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig() {
+    // Provide a config similar to the one used by the framework by default
+    // (see AudioPolicyConfig::setDefaultSurroundFormats).
+#define ENCODED_FORMAT(format)        \
+    AudioFormatDescription {          \
+        .encoding = ::android::format \
+    }
+#define SIMPLE_FORMAT(format)                   \
+    SurroundSoundConfig::SurroundFormatFamily { \
+        .primaryFormat = ENCODED_FORMAT(format) \
+    }
+
+    static const SurroundSoundConfig defaultConfig = {
+            .formatFamilies = {
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC3),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD),
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3_JOC),
+                    SurroundSoundConfig::SurroundFormatFamily{
+                            .primaryFormat = ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_LC),
+                            .subFormats =
+                                    {
+                                            ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1),
+                                            ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2),
+                                            ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_ELD),
+                                            ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_XHE),
+                                    }},
+                    SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC4),
+            }};
+#undef SIMPLE_FORMAT
+#undef ENCODED_FORMAT
+
+    return defaultConfig;
+}
+
 void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
     if (getXsdcConfig()->hasVolumes()) {
         for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
diff --git a/audio/aidl/default/Bluetooth.cpp b/audio/aidl/default/Bluetooth.cpp
index c32b538..072b89f 100644
--- a/audio/aidl/default/Bluetooth.cpp
+++ b/audio/aidl/default/Bluetooth.cpp
@@ -82,19 +82,18 @@
 
 ndk::ScopedAStatus BluetoothA2dp::isEnabled(bool* _aidl_return) {
     *_aidl_return = mEnabled;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothA2dp::setEnabled(bool in_enabled) {
     mEnabled = in_enabled;
     LOG(DEBUG) << __func__ << ": " << mEnabled;
+    if (mHandler) return mHandler();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothA2dp::supportsOffloadReconfiguration(bool* _aidl_return) {
-    *_aidl_return = true;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    *_aidl_return = false;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -102,24 +101,22 @@
         const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
                 __unused) {
     LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
 ndk::ScopedAStatus BluetoothLe::isEnabled(bool* _aidl_return) {
     *_aidl_return = mEnabled;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothLe::setEnabled(bool in_enabled) {
     mEnabled = in_enabled;
-    LOG(DEBUG) << __func__ << ": " << mEnabled;
+    if (mHandler) return mHandler();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothLe::supportsOffloadReconfiguration(bool* _aidl_return) {
-    *_aidl_return = true;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    *_aidl_return = false;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -127,7 +124,7 @@
         const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
                 __unused) {
     LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index 87c0ace..308200a 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -27,30 +27,41 @@
 
 namespace aidl::android::hardware::audio::core {
 ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
-    SurroundSoundConfig surroundSoundConfig;
-    // TODO: parse from XML; for now, use empty config as default
-    *_aidl_return = std::move(surroundSoundConfig);
+    static const auto& func = __func__;
+    static const SurroundSoundConfig surroundSoundConfig = [this]() {
+        SurroundSoundConfig surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
+        if (mAudioPolicyConverter.getStatus() != ::android::OK) {
+            LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
+        }
+        return surroundCfg;
+    }();
+    *_aidl_return = surroundSoundConfig;
     LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Config::getEngineConfig(AudioHalEngineConfig* _aidl_return) {
+    static const auto& func = __func__;
     static const AudioHalEngineConfig returnEngCfg = [this]() {
         AudioHalEngineConfig engConfig;
         if (mEngConfigConverter.getStatus() == ::android::OK) {
             engConfig = mEngConfigConverter.getAidlEngineConfig();
         } else {
-            LOG(INFO) << __func__ << mEngConfigConverter.getError();
+            LOG(INFO) << func << ": " << mEngConfigConverter.getError();
             if (mAudioPolicyConverter.getStatus() == ::android::OK) {
                 engConfig = mAudioPolicyConverter.getAidlEngineConfig();
             } else {
-                LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
+                LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
             }
         }
+        // Logging full contents of the config is an overkill, just provide statistics.
+        LOG(DEBUG) << func
+                   << ": number of strategies parsed: " << engConfig.productStrategies.size()
+                   << ", default strategy: " << engConfig.defaultProductStrategyId
+                   << ", number of volume groups parsed: " << engConfig.volumeGroups.size();
         return engConfig;
     }();
     *_aidl_return = returnEngCfg;
-    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
     return ndk::ScopedAStatus::ok();
 }
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index e1e1f79..9131935 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -134,7 +134,7 @@
 // Device ports:
 //  * "Speaker", OUT_SPEAKER, default
 //    - no profiles specified
-//  * "Built-in Mic", IN_MICROPHONE, default
+//  * "Built-In Mic", IN_MICROPHONE, default
 //    - no profiles specified
 //  * "Telephony Tx", OUT_TELEPHONY_TX
 //    - no profiles specified
@@ -142,63 +142,39 @@
 //    - no profiles specified
 //  * "FM Tuner", IN_FM_TUNER
 //    - no profiles specified
-//  * "USB Out", OUT_DEVICE, CONNECTION_USB
-//    - no profiles specified
-//  * "USB In", IN_DEVICE, CONNECTION_USB
-//    - no profiles specified
 //
 // Mix ports:
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//  * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
-//    - profile MP3; MONO, STEREO; 44100, 48000
-//  * "primary input", 2 max open, 2 max active streams
-//    - profile PCM 16-bit; MONO, STEREO, FRONT_BACK;
-//        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
-//        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+//  * "primary input", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; MONO, STEREO;
+//        8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_tx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_rx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "fm_tuner", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //
 // Routes:
-//  "primary out", "compressed offload" -> "Speaker"
-//  "primary out", "compressed offload" -> "USB Out"
-//  "Built-in Mic", "USB In" -> "primary input"
-//  "telephony_tx" -> "Telephony Tx"
+//  "primary out" -> "Speaker"
+//  "Built-In Mic" -> "primary input"
 //  "Telephony Rx" -> "telephony_rx"
+//  "telephony_tx" -> "Telephony Tx"
 //  "FM Tuner" -> "fm_tuner"
 //
 // Initial port configs:
-//  * "Speaker" device port: PCM 24-bit; STEREO; 48000
-//  * "Built-in Mic" device port: PCM 24-bit; MONO; 48000
-//  * "Telephony Tx" device port: PCM 24-bit; MONO; 48000
-//  * "Telephony Rx" device port: PCM 24-bit; MONO; 48000
-//  * "FM Tuner" device port: PCM 24-bit; STEREO; 48000
-//
-// Profiles for device port connected state:
-//  * USB Out":
-//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//  * USB In":
-//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//  * "Speaker" device port: PCM 16-bit; STEREO; 48000
+//  * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
+//  * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
+//  * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
+//  * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
 //
 std::unique_ptr<Configuration> getPrimaryConfiguration() {
     static const Configuration configuration = []() {
         const std::vector<AudioProfile> standardPcmAudioProfiles = {
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {8000, 11025, 16000, 32000, 44100, 48000}),
-                createProfile(PcmType::INT_24_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                               {8000, 11025, 16000, 32000, 44100, 48000})};
         Configuration c;
 
@@ -210,17 +186,17 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(speakerOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
                                  createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
         AudioPort micInDevice =
-                createPort(c.nextPortId++, "Built-in Mic", 0, true,
+                createPort(c.nextPortId++, "Built-In Mic", 0, true,
                            createDeviceExt(AudioDeviceType::IN_MICROPHONE,
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(micInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
                                  createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
 
@@ -230,7 +206,7 @@
         c.ports.push_back(telephonyTxOutDevice);
         c.initialConfigs.push_back(
                 createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
-                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
                                  false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
 
         AudioPort telephonyRxInDevice =
@@ -239,64 +215,33 @@
         c.ports.push_back(telephonyRxInDevice);
         c.initialConfigs.push_back(
                 createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
-                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
                                  true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
 
         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
         c.ports.push_back(fmTunerInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
                                  createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
 
-        AudioPort usbOutDevice =
-                createPort(c.nextPortId++, "USB Out", 0, false,
-                           createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
-                                           AudioDeviceDescription::CONNECTION_USB));
-        c.ports.push_back(usbOutDevice);
-        c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
-
-        AudioPort usbInDevice = createPort(c.nextPortId++, "USB In", 0, true,
-                                           createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
-                                                           AudioDeviceDescription::CONNECTION_USB));
-        c.ports.push_back(usbInDevice);
-        c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
-
         // Mix ports
 
         AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
                                              makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
-                                             false, createPortMixExt(1, 1));
+                                             false, createPortMixExt(0, 0));
         primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
                                       standardPcmAudioProfiles.begin(),
                                       standardPcmAudioProfiles.end());
         c.ports.push_back(primaryOutMix);
 
-        AudioPort compressedOffloadOutMix =
-                createPort(c.nextPortId++, "compressed offload",
-                           makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
-                                                    AudioOutputFlags::COMPRESS_OFFLOAD,
-                                                    AudioOutputFlags::NON_BLOCKING}),
-                           false, createPortMixExt(1, 1));
-        compressedOffloadOutMix.profiles.push_back(
-                createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {44100, 48000}));
-        c.ports.push_back(compressedOffloadOutMix);
-
         AudioPort primaryInMix =
-                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
+                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 0));
         primaryInMix.profiles.push_back(
                 createProfile(PcmType::INT_16_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
-                               AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
-        primaryInMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
-                               AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}));
         c.ports.push_back(primaryInMix);
 
         AudioPort telephonyTxOutMix =
@@ -320,11 +265,10 @@
                                      standardPcmAudioProfiles.end());
         c.ports.push_back(fmTunerInMix);
 
-        c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, speakerOutDevice));
-        c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, usbOutDevice));
-        c.routes.push_back(createRoute({micInDevice, usbInDevice}, primaryInMix));
-        c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
+        c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
+        c.routes.push_back(createRoute({micInDevice}, primaryInMix));
         c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
+        c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
         c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
@@ -345,15 +289,21 @@
 //
 // Device ports:
 //  * "Remote Submix Out", OUT_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
+//    - no profiles specified
 //  * "Remote Submix In", IN_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
+//    - no profiles specified
 //
 // Mix ports:
-//  * "r_submix output", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
-//  * "r_submix input", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
+//  * "r_submix output", unlimited max open, unlimited max active stream
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//  * "r_submix input", unlimited max open, unlimited max active stream
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //
 // Routes:
 //  "r_submix output" -> "Remote Submix Out"
@@ -362,33 +312,46 @@
 std::unique_ptr<Configuration> getRSubmixConfiguration() {
     static const Configuration configuration = []() {
         Configuration c;
+        const std::vector<AudioProfile> standardPcmAudioProfiles{
+                createProfile(PcmType::FLOAT_32_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}),
+                createProfile(PcmType::INT_32_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}),
+                createProfile(PcmType::INT_24_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}),
+                createProfile(PcmType::INT_16_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000})};
 
         // Device ports
 
-        AudioPort rsubmixOutDevice = createPort(c.nextPortId++, "Remote Submix Out", 0, false,
-                                                createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
-        rsubmixOutDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        AudioPort rsubmixOutDevice =
+                createPort(c.nextPortId++, "Remote Submix Out", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
+                                           AudioDeviceDescription::CONNECTION_VIRTUAL));
         c.ports.push_back(rsubmixOutDevice);
+        c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;
 
-        AudioPort rsubmixInDevice = createPort(c.nextPortId++, "Remote Submix In", 0, true,
-                                               createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
-        rsubmixInDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        AudioPort rsubmixInDevice =
+                createPort(c.nextPortId++, "Remote Submix In", 0, true,
+                           createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
+                                           AudioDeviceDescription::CONNECTION_VIRTUAL));
         c.ports.push_back(rsubmixInDevice);
+        c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;
 
         // Mix ports
 
         AudioPort rsubmixOutMix =
                 createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
-        rsubmixOutMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        rsubmixOutMix.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixOutMix);
 
         AudioPort rsubmixInMix =
                 createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
-        rsubmixInMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        rsubmixInMix.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixInMix);
 
         c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
@@ -402,22 +365,31 @@
 // Usb configuration:
 //
 // Device ports:
+//  * "USB Device Out", OUT_DEVICE, CONNECTION_USB
+//    - no profiles specified
 //  * "USB Headset Out", OUT_HEADSET, CONNECTION_USB
 //    - no profiles specified
+//  * "USB Device In", IN_DEVICE, CONNECTION_USB
+//    - no profiles specified
 //  * "USB Headset In", IN_HEADSET, CONNECTION_USB
 //    - no profiles specified
 //
 // Mix ports:
-//  * "usb_headset output", 1 max open, 1 max active stream
+//  * "usb_device output", 1 max open, 1 max active stream
 //    - no profiles specified
-//  * "usb_headset input", 1 max open, 1 max active stream
+//  * "usb_device input", 1 max open, 1 max active stream
 //    - no profiles specified
 //
+// Routes:
+//  * "usb_device output" -> "USB Device Out"
+//  * "usb_device output" -> "USB Headset Out"
+//  * "USB Device In", "USB Headset In" -> "usb_device input"
+//
 // Profiles for device port connected state:
-//  * USB Headset Out":
+//  * "USB Device Out", "USB Headset Out":
 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
-//  * USB Headset In":
+//  * "USB Device In", "USB Headset In":
 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
 //
@@ -436,6 +408,13 @@
 
         // Device ports
 
+        AudioPort usbOutDevice =
+                createPort(c.nextPortId++, "USB Device Out", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
+                                           AudioDeviceDescription::CONNECTION_USB));
+        c.ports.push_back(usbOutDevice);
+        c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
+
         AudioPort usbOutHeadset =
                 createPort(c.nextPortId++, "USB Headset Out", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
@@ -443,6 +422,12 @@
         c.ports.push_back(usbOutHeadset);
         c.connectedProfiles[usbOutHeadset.id] = standardPcmAudioProfiles;
 
+        AudioPort usbInDevice = createPort(c.nextPortId++, "USB Device In", 0, true,
+                                           createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
+                                                           AudioDeviceDescription::CONNECTION_USB));
+        c.ports.push_back(usbInDevice);
+        c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
+
         AudioPort usbInHeadset =
                 createPort(c.nextPortId++, "USB Headset In", 0, true,
                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
@@ -452,16 +437,211 @@
 
         // Mix ports
 
-        AudioPort usbHeadsetOutMix =
-                createPort(c.nextPortId++, "usb_headset output", 0, false, createPortMixExt(1, 1));
-        c.ports.push_back(usbHeadsetOutMix);
+        AudioPort usbDeviceOutMix =
+                createPort(c.nextPortId++, "usb_device output", 0, false, createPortMixExt(1, 1));
+        c.ports.push_back(usbDeviceOutMix);
 
-        AudioPort usbHeadsetInMix =
-                createPort(c.nextPortId++, "usb_headset input", 0, true, createPortMixExt(1, 1));
-        c.ports.push_back(usbHeadsetInMix);
+        AudioPort usbDeviceInMix =
+                createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(1, 1));
+        c.ports.push_back(usbDeviceInMix);
 
-        c.routes.push_back(createRoute({usbHeadsetOutMix}, usbOutHeadset));
-        c.routes.push_back(createRoute({usbInHeadset}, usbHeadsetInMix));
+        c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutDevice));
+        c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutHeadset));
+        c.routes.push_back(createRoute({usbInDevice, usbInHeadset}, usbDeviceInMix));
+
+        return c;
+    }();
+    return std::make_unique<Configuration>(configuration);
+}
+
+// Stub configuration:
+//
+// Device ports:
+//  * "Test Out", OUT_AFE_PROXY
+//    - no profiles specified
+//  * "Test In", IN_AFE_PROXY
+//    - no profiles specified
+//
+// Mix ports:
+//  * "test output", 1 max open, 1 max active stream
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//  * "test fast output", 1 max open, 1 max active stream
+//    - profile PCM 24-bit; STEREO; 44100, 48000
+//  * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
+//  stream
+//    - profile MP3; MONO, STEREO; 44100, 48000
+//  * "test input", 2 max open, 2 max active streams
+//    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
+//        8000, 11025, 16000, 22050, 32000, 44100, 48000
+//
+// Routes:
+//  "test output", "test fast output", "test compressed offload" -> "Test Out"
+//  "Test In" -> "test input"
+//
+// Initial port configs:
+//  * "Test Out" device port: PCM 24-bit; STEREO; 48000
+//  * "Test In" device port: PCM 24-bit; MONO; 48000
+//
+std::unique_ptr<Configuration> getStubConfiguration() {
+    static const Configuration configuration = []() {
+        Configuration c;
+
+        // Device ports
+
+        AudioPort testOutDevice = createPort(c.nextPortId++, "Test Out", 0, false,
+                                             createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0));
+        c.ports.push_back(testOutDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(testOutDevice.id, testOutDevice.id, PcmType::INT_24_BIT,
+                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
+                                 createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)));
+
+        AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
+                                            createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0));
+        c.ports.push_back(testInDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(testInDevice.id, testInDevice.id, PcmType::INT_24_BIT,
+                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
+                                 createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)));
+
+        // Mix ports
+
+        AudioPort testOutMix =
+                createPort(c.nextPortId++, "test output", 0, false, createPortMixExt(1, 1));
+        testOutMix.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}));
+        c.ports.push_back(testOutMix);
+
+        AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
+                                              makeBitPositionFlagMask({AudioOutputFlags::FAST}),
+                                              false, createPortMixExt(1, 1));
+        testFastOutMix.profiles.push_back(createProfile(
+                PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
+        c.ports.push_back(testFastOutMix);
+
+        AudioPort compressedOffloadOutMix =
+                createPort(c.nextPortId++, "test compressed offload",
+                           makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
+                                                    AudioOutputFlags::COMPRESS_OFFLOAD,
+                                                    AudioOutputFlags::NON_BLOCKING}),
+                           false, createPortMixExt(1, 1));
+        compressedOffloadOutMix.profiles.push_back(
+                createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000}));
+        c.ports.push_back(compressedOffloadOutMix);
+
+        AudioPort testInMIx =
+                createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2));
+        testInMIx.profiles.push_back(
+                createProfile(PcmType::INT_16_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
+                               AudioChannelLayout::LAYOUT_FRONT_BACK},
+                              {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
+        testInMIx.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
+                               AudioChannelLayout::LAYOUT_FRONT_BACK},
+                              {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
+        c.ports.push_back(testInMIx);
+
+        c.routes.push_back(
+                createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
+        c.routes.push_back(createRoute({testInDevice}, testInMIx));
+
+        c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
+
+        return c;
+    }();
+    return std::make_unique<Configuration>(configuration);
+}
+
+// Bluetooth configuration:
+//
+// Device ports:
+//  * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP
+//    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+//  * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP
+//    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+//  * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP
+//    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+//  * "BT Hearing Aid Out", OUT_HEARING_AID, CONNECTION_WIRELESS
+//    - no profiles specified
+//
+// Mix ports:
+//  * "a2dp output", 1 max open, 1 max active stream
+//    - no profiles specified
+//  * "hearing aid output", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; STEREO; 16000, 24000
+//
+// Routes:
+//  "a2dp output" -> "BT A2DP Out"
+//  "a2dp output" -> "BT A2DP Headphones"
+//  "a2dp output" -> "BT A2DP Speaker"
+//  "hearing aid output" -> "BT Hearing Aid Out"
+//
+std::unique_ptr<Configuration> getBluetoothConfiguration() {
+    static const Configuration configuration = []() {
+        const std::vector<AudioProfile> standardPcmAudioProfiles = {
+                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000, 88200, 96000})};
+        Configuration c;
+
+        // Device ports
+        AudioPort btOutDevice =
+                createPort(c.nextPortId++, "BT A2DP Out", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
+                                           AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(),
+                                    standardPcmAudioProfiles.end());
+        c.ports.push_back(btOutDevice);
+        c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles;
+
+        AudioPort btOutHeadphone =
+                createPort(c.nextPortId++, "BT A2DP Headphones", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0,
+                                           AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(),
+                                       standardPcmAudioProfiles.begin(),
+                                       standardPcmAudioProfiles.end());
+        c.ports.push_back(btOutHeadphone);
+        c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles;
+
+        AudioPort btOutSpeaker =
+                createPort(c.nextPortId++, "BT A2DP Speaker", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0,
+                                           AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(),
+                                     standardPcmAudioProfiles.begin(),
+                                     standardPcmAudioProfiles.end());
+        c.ports.push_back(btOutSpeaker);
+        c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles;
+
+        AudioPort btOutHearingAid =
+                createPort(c.nextPortId++, "BT Hearing Aid Out", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
+                                           AudioDeviceDescription::CONNECTION_WIRELESS));
+        c.ports.push_back(btOutHearingAid);
+        c.connectedProfiles[btOutHearingAid.id] = std::vector<AudioProfile>(
+                {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
+
+        // Mix ports
+        AudioPort btOutMix =
+                createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
+        c.ports.push_back(btOutMix);
+
+        AudioPort btHearingOutMix =
+                createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
+        btHearingOutMix.profiles.push_back(createProfile(
+                PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
+        c.ports.push_back(btHearingOutMix);
+
+        c.routes.push_back(createRoute({btOutMix}, btOutDevice));
+        c.routes.push_back(createRoute({btOutMix}, btOutHeadphone));
+        c.routes.push_back(createRoute({btOutMix}, btOutSpeaker));
+        c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid));
 
         return c;
     }();
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index 71d111b..4a12f8a 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -18,6 +18,7 @@
 #include <string>
 #define LOG_TAG "AHAL_EffectConfig"
 #include <android-base/logging.h>
+#include <system/audio_aidl_utils.h>
 #include <system/audio_effects/audio_effects_conf.h>
 #include <system/audio_effects/effect_uuid.h>
 
@@ -116,53 +117,59 @@
 
 bool EffectConfig::parseEffect(const tinyxml2::XMLElement& xml) {
     struct EffectLibraries effectLibraries;
-    std::vector<LibraryUuid> libraryUuids;
+    std::vector<Library> libraries;
     std::string name = xml.Attribute("name");
     RETURN_VALUE_IF(name == "", false, "effectsNoName");
 
     LOG(DEBUG) << __func__ << dump(xml);
-    struct LibraryUuid libraryUuid;
+    struct Library library;
     if (std::strcmp(xml.Name(), "effectProxy") == 0) {
         // proxy lib and uuid
-        RETURN_VALUE_IF(!parseLibraryUuid(xml, libraryUuid, true), false, "parseProxyLibFailed");
-        effectLibraries.proxyLibrary = libraryUuid;
+        RETURN_VALUE_IF(!parseLibrary(xml, library, true), false, "parseProxyLibFailed");
+        effectLibraries.proxyLibrary = library;
         // proxy effect libs and UUID
         auto xmlProxyLib = xml.FirstChildElement();
         RETURN_VALUE_IF(!xmlProxyLib, false, "noLibForProxy");
         while (xmlProxyLib) {
-            struct LibraryUuid tempLibraryUuid;
-            RETURN_VALUE_IF(!parseLibraryUuid(*xmlProxyLib, tempLibraryUuid), false,
+            struct Library tempLibrary;
+            RETURN_VALUE_IF(!parseLibrary(*xmlProxyLib, tempLibrary), false,
                             "parseEffectLibFailed");
-            libraryUuids.push_back(std::move(tempLibraryUuid));
+            libraries.push_back(std::move(tempLibrary));
             xmlProxyLib = xmlProxyLib->NextSiblingElement();
         }
     } else {
         // expect only one library if not proxy
-        RETURN_VALUE_IF(!parseLibraryUuid(xml, libraryUuid), false, "parseEffectLibFailed");
-        libraryUuids.push_back(std::move(libraryUuid));
+        RETURN_VALUE_IF(!parseLibrary(xml, library), false, "parseEffectLibFailed");
+        libraries.push_back(std::move(library));
     }
 
-    effectLibraries.libraries = std::move(libraryUuids);
+    effectLibraries.libraries = std::move(libraries);
     mEffectsMap[name] = std::move(effectLibraries);
     return true;
 }
 
-bool EffectConfig::parseLibraryUuid(const tinyxml2::XMLElement& xml,
-                                    struct LibraryUuid& libraryUuid, bool isProxy) {
+bool EffectConfig::parseLibrary(const tinyxml2::XMLElement& xml, struct Library& library,
+                                bool isProxy) {
     // Retrieve library name only if not effectProxy element
     if (!isProxy) {
         const char* name = xml.Attribute("library");
         RETURN_VALUE_IF(!name, false, "noLibraryAttribute");
-        libraryUuid.name = name;
+        library.name = name;
     }
 
     const char* uuidStr = xml.Attribute("uuid");
     RETURN_VALUE_IF(!uuidStr, false, "noUuidAttribute");
-    libraryUuid.uuid = stringToUuid(uuidStr);
-    RETURN_VALUE_IF((libraryUuid.uuid == getEffectUuidZero()), false, "invalidUuidAttribute");
+    library.uuid = stringToUuid(uuidStr);
+    if (const char* typeUuidStr = xml.Attribute("type")) {
+        library.type = stringToUuid(typeUuidStr);
+    }
+    RETURN_VALUE_IF((library.uuid == getEffectUuidZero()), false, "invalidUuidAttribute");
 
-    LOG(DEBUG) << __func__ << (isProxy ? " proxy " : libraryUuid.name) << " : "
-               << libraryUuid.uuid.toString();
+    LOG(DEBUG) << __func__ << (isProxy ? " proxy " : library.name) << " : uuid "
+               << ::android::audio::utils::toString(library.uuid)
+               << (library.type.has_value()
+                           ? ::android::audio::utils::toString(library.type.value())
+                           : "");
     return true;
 }
 
@@ -189,16 +196,16 @@
     // see list of audio sources in audio_source_t:
     // system/media/audio/include/system/audio_effects/audio_effects_conf.h
     static const std::map<const std::string, AudioSource> sAudioSourceTable = {
-            {MIC_SRC_TAG, AudioSource::VOICE_CALL},
-            {VOICE_UL_SRC_TAG, AudioSource::VOICE_CALL},
-            {VOICE_DL_SRC_TAG, AudioSource::VOICE_CALL},
+            {MIC_SRC_TAG, AudioSource::MIC},
+            {VOICE_UL_SRC_TAG, AudioSource::VOICE_UPLINK},
+            {VOICE_DL_SRC_TAG, AudioSource::VOICE_DOWNLINK},
             {VOICE_CALL_SRC_TAG, AudioSource::VOICE_CALL},
-            {CAMCORDER_SRC_TAG, AudioSource::VOICE_CALL},
-            {VOICE_REC_SRC_TAG, AudioSource::VOICE_CALL},
-            {VOICE_COMM_SRC_TAG, AudioSource::VOICE_CALL},
-            {REMOTE_SUBMIX_SRC_TAG, AudioSource::VOICE_CALL},
-            {UNPROCESSED_SRC_TAG, AudioSource::VOICE_CALL},
-            {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_CALL}};
+            {CAMCORDER_SRC_TAG, AudioSource::CAMCORDER},
+            {VOICE_REC_SRC_TAG, AudioSource::VOICE_RECOGNITION},
+            {VOICE_COMM_SRC_TAG, AudioSource::VOICE_COMMUNICATION},
+            {REMOTE_SUBMIX_SRC_TAG, AudioSource::REMOTE_SUBMIX},
+            {UNPROCESSED_SRC_TAG, AudioSource::UNPROCESSED},
+            {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_PERFORMANCE}};
 
     if (typeTag == Processing::Type::streamType) {
         auto typeIter = sAudioStreamTypeTable.find(type);
@@ -240,7 +247,8 @@
     return mProcessingMap;
 }
 
-bool EffectConfig::findUuid(const std::string& xmlEffectName, AudioUuid* uuid) {
+bool EffectConfig::findUuid(const std::pair<std::string, struct EffectLibraries>& effectElem,
+                            AudioUuid* uuid) {
 // Difference from EFFECT_TYPE_LIST_DEF, there could be multiple name mapping to same Effect Type
 #define EFFECT_XML_TYPE_LIST_DEF(V)                        \
     V("acoustic_echo_canceler", AcousticEchoCanceler)      \
@@ -250,6 +258,7 @@
     V("downmix", Downmix)                                  \
     V("dynamics_processing", DynamicsProcessing)           \
     V("equalizer", Equalizer)                              \
+    V("extensioneffect", Extension)                        \
     V("haptic_generator", HapticGenerator)                 \
     V("loudness_enhancer", LoudnessEnhancer)               \
     V("env_reverb", EnvReverb)                             \
@@ -266,6 +275,7 @@
 
 #define GENERATE_MAP_ENTRY_V(s, symbol) {s, &getEffectTypeUuid##symbol},
 
+    const std::string xmlEffectName = effectElem.first;
     typedef const AudioUuid& (*UuidGetter)(void);
     static const std::map<std::string, UuidGetter> uuidMap{
             // std::make_pair("s", &getEffectTypeUuidExtension)};
@@ -274,6 +284,14 @@
         *uuid = (*it->second)();
         return true;
     }
+
+    const auto& libs = effectElem.second.libraries;
+    for (const auto& lib : libs) {
+        if (lib.type.has_value()) {
+            *uuid = lib.type.value();
+            return true;
+        }
+    }
     return false;
 }
 
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index 7073a10..96f13ba 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -25,6 +25,7 @@
 
 #include <android-base/logging.h>
 #include <android/binder_ibinder_platform.h>
+#include <system/audio_aidl_utils.h>
 #include <system/audio_effects/effect_uuid.h>
 #include <system/thread_defs.h>
 
@@ -47,19 +48,19 @@
         for (const auto& it : mEffectMap) {
             if (auto spEffect = it.first.lock()) {
                 LOG(ERROR) << __func__ << " erase remaining instance UUID "
-                           << it.second.first.toString();
-                destroyEffectImpl(spEffect);
+                           << ::android::audio::utils::toString(it.second.first);
+                destroyEffectImpl_l(spEffect);
             }
         }
     }
 }
 
-ndk::ScopedAStatus Factory::getDescriptorWithUuid(const AudioUuid& uuid, Descriptor* desc) {
+ndk::ScopedAStatus Factory::getDescriptorWithUuid_l(const AudioUuid& uuid, Descriptor* desc) {
     RETURN_IF(!desc, EX_NULL_POINTER, "nullDescriptor");
 
     if (mEffectLibMap.count(uuid)) {
         auto& entry = mEffectLibMap[uuid];
-        getDlSyms(entry);
+        getDlSyms_l(entry);
         auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
         RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
                   "dlNullQueryEffectFunc");
@@ -74,6 +75,7 @@
                                          const std::optional<AudioUuid>& in_impl_uuid,
                                          const std::optional<AudioUuid>& in_proxy_uuid,
                                          std::vector<Descriptor>* _aidl_return) {
+    std::lock_guard lg(mMutex);
     // get the matching list
     std::vector<Descriptor::Identity> idList;
     std::copy_if(mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(idList),
@@ -87,7 +89,8 @@
     for (const auto& id : idList) {
         if (mEffectLibMap.count(id.uuid)) {
             Descriptor desc;
-            RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(id.uuid, &desc), "getDescriptorFailed");
+            RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid_l(id.uuid, &desc),
+                                     "getDescriptorFailed");
             // update proxy UUID with information from config xml
             desc.common.id.proxy = id.proxy;
             _aidl_return->emplace_back(std::move(desc));
@@ -98,18 +101,19 @@
 
 ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
                                             std::vector<Processing>* _aidl_return) {
+    std::lock_guard lg(mMutex);
     const auto& processings = mConfig.getProcessingMap();
     // Processing stream type
     for (const auto& procIter : processings) {
         if (!in_type.has_value() || in_type.value() == procIter.first) {
             Processing process = {.type = procIter.first /* Processing::Type */};
             for (const auto& libs : procIter.second /* std::vector<struct EffectLibraries> */) {
-                for (const auto& lib : libs.libraries /* std::vector<struct LibraryUuid> */) {
+                for (const auto& lib : libs.libraries /* std::vector<struct Library> */) {
                     Descriptor desc;
                     if (libs.proxyLibrary.has_value()) {
                         desc.common.id.proxy = libs.proxyLibrary.value().uuid;
                     }
-                    RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(lib.uuid, &desc),
+                    RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid_l(lib.uuid, &desc),
                                              "getDescriptorFailed");
                     process.ids.emplace_back(desc);
                 }
@@ -123,10 +127,11 @@
 
 ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
                                          std::shared_ptr<IEffect>* _aidl_return) {
-    LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
+    LOG(DEBUG) << __func__ << ": UUID " << ::android::audio::utils::toString(in_impl_uuid);
+    std::lock_guard lg(mMutex);
     if (mEffectLibMap.count(in_impl_uuid)) {
         auto& entry = mEffectLibMap[in_impl_uuid];
-        getDlSyms(entry);
+        getDlSyms_l(entry);
 
         auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
         RETURN_IF(!libInterface || !libInterface->createEffectFunc, EX_NULL_POINTER,
@@ -151,7 +156,7 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
+ndk::ScopedAStatus Factory::destroyEffectImpl_l(const std::shared_ptr<IEffect>& in_handle) {
     std::weak_ptr<IEffect> wpHandle(in_handle);
     // find the effect entry with key (std::weak_ptr<IEffect>)
     if (auto effectIt = mEffectMap.find(wpHandle); effectIt != mEffectMap.end()) {
@@ -163,7 +168,8 @@
                       "dlNulldestroyEffectFunc");
             RETURN_IF_BINDER_EXCEPTION(interface->destroyEffectFunc(in_handle));
         } else {
-            LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
+            LOG(ERROR) << __func__ << ": UUID " << ::android::audio::utils::toString(uuid)
+                       << " does not exist in libMap!";
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
         mEffectMap.erase(effectIt);
@@ -175,7 +181,7 @@
 }
 
 // go over the map and cleanup all expired weak_ptrs.
-void Factory::cleanupEffectMap() {
+void Factory::cleanupEffectMap_l() {
     for (auto it = mEffectMap.begin(); it != mEffectMap.end();) {
         if (nullptr == it->first.lock()) {
             it = mEffectMap.erase(it);
@@ -187,13 +193,15 @@
 
 ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_handle) {
     LOG(DEBUG) << __func__ << ": instance " << in_handle.get();
-    ndk::ScopedAStatus status = destroyEffectImpl(in_handle);
+    std::lock_guard lg(mMutex);
+    ndk::ScopedAStatus status = destroyEffectImpl_l(in_handle);
     // always do the cleanup
-    cleanupEffectMap();
+    cleanupEffectMap_l();
     return status;
 }
 
-bool Factory::openEffectLibrary(const AudioUuid& impl, const std::string& path) {
+bool Factory::openEffectLibrary(const AudioUuid& impl,
+                                const std::string& path) NO_THREAD_SAFETY_ANALYSIS {
     std::function<void(void*)> dlClose = [](void* handle) -> void {
         if (handle && dlclose(handle)) {
             LOG(ERROR) << "dlclose failed " << dlerror();
@@ -207,8 +215,8 @@
         return false;
     }
 
-    LOG(INFO) << __func__ << " dlopen lib:" << path << "\nimpl:" << impl.toString()
-              << "\nhandle:" << libHandle;
+    LOG(INFO) << __func__ << " dlopen lib:" << path
+              << "\nimpl:" << ::android::audio::utils::toString(impl) << "\nhandle:" << libHandle;
     auto interface = new effect_dl_interface_s{nullptr, nullptr, nullptr};
     mEffectLibMap.insert(
             {impl,
@@ -217,9 +225,9 @@
     return true;
 }
 
-void Factory::createIdentityWithConfig(const EffectConfig::LibraryUuid& configLib,
-                                       const AudioUuid& typeUuid,
-                                       const std::optional<AudioUuid> proxyUuid) {
+void Factory::createIdentityWithConfig(
+        const EffectConfig::Library& configLib, const AudioUuid& typeUuid,
+        const std::optional<AudioUuid> proxyUuid) NO_THREAD_SAFETY_ANALYSIS {
     static const auto& libMap = mConfig.getLibraryMap();
     const std::string& libName = configLib.name;
     if (auto path = libMap.find(libName); path != libMap.end()) {
@@ -228,8 +236,10 @@
         id.uuid = configLib.uuid;
         id.proxy = proxyUuid;
         LOG(DEBUG) << __func__ << " loading lib " << path->second << ": typeUuid "
-                   << id.type.toString() << "\nimplUuid " << id.uuid.toString() << " proxyUuid "
-                   << (proxyUuid.has_value() ? proxyUuid->toString() : "null");
+                   << ::android::audio::utils::toString(id.type) << "\nimplUuid "
+                   << ::android::audio::utils::toString(id.uuid) << " proxyUuid "
+                   << (proxyUuid.has_value() ? ::android::audio::utils::toString(proxyUuid.value())
+                                             : "null");
         if (openEffectLibrary(id.uuid, path->second)) {
             mIdentitySet.insert(std::move(id));
         }
@@ -242,8 +252,7 @@
 void Factory::loadEffectLibs() {
     const auto& configEffectsMap = mConfig.getEffectsMap();
     for (const auto& configEffects : configEffectsMap) {
-        if (AudioUuid uuid;
-            EffectConfig::findUuid(configEffects.first /* xml effect name */, &uuid)) {
+        if (AudioUuid type; EffectConfig::findUuid(configEffects /* xml effect */, &type)) {
             const auto& configLibs = configEffects.second;
             std::optional<AudioUuid> proxyUuid;
             if (configLibs.proxyLibrary.has_value()) {
@@ -251,7 +260,7 @@
                 proxyUuid = proxyLib.uuid;
             }
             for (const auto& configLib : configLibs.libraries) {
-                createIdentityWithConfig(configLib, uuid, proxyUuid);
+                createIdentityWithConfig(configLib, type, proxyUuid);
             }
         } else {
             LOG(ERROR) << __func__ << ": can not find type UUID for effect " << configEffects.first
@@ -260,7 +269,7 @@
     }
 }
 
-void Factory::getDlSyms(DlEntry& entry) {
+void Factory::getDlSyms_l(DlEntry& entry) {
     auto& dlHandle = std::get<kMapEntryHandleIndex>(entry);
     RETURN_VALUE_IF(!dlHandle, void(), "dlNullHandle");
     // Get the reference of the DL interfaces in library map tuple.
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index da1ad11..c81c731 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -76,7 +76,7 @@
 }
 
 ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
-    LOG(DEBUG) << getEffectName() << __func__ << " with: " << param.toString();
+    LOG(VERBOSE) << getEffectName() << __func__ << " with: " << param.toString();
 
     const auto tag = param.getTag();
     switch (tag) {
@@ -100,7 +100,6 @@
 }
 
 ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) {
-    LOG(DEBUG) << getEffectName() << __func__ << id.toString();
     auto tag = id.getTag();
     switch (tag) {
         case Parameter::Id::commonTag: {
@@ -117,7 +116,7 @@
             break;
         }
     }
-    LOG(DEBUG) << getEffectName() << __func__ << param->toString();
+    LOG(VERBOSE) << getEffectName() << __func__ << id.toString() << param->toString();
     return ndk::ScopedAStatus::ok();
 }
 
@@ -254,7 +253,7 @@
     for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    LOG(DEBUG) << getEffectName() << __func__ << " done processing " << samples << " samples";
+    LOG(VERBOSE) << getEffectName() << __func__ << " done processing " << samples << " samples";
     return {STATUS_OK, samples, samples};
 }
 
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
index 574dc69..cd2ba53 100644
--- a/audio/aidl/default/EffectThread.cpp
+++ b/audio/aidl/default/EffectThread.cpp
@@ -149,8 +149,8 @@
         IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
         outputMQ->write(buffer, status.fmqProduced);
         statusMQ->writeBlocking(&status, 1);
-        LOG(DEBUG) << mName << __func__ << ": done processing, effect consumed "
-                   << status.fmqConsumed << " produced " << status.fmqProduced;
+        LOG(VERBOSE) << mName << __func__ << ": done processing, effect consumed "
+                     << status.fmqConsumed << " produced " << status.fmqProduced;
     }
 }
 
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 5f17d71..96b555c 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -140,7 +140,7 @@
     aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
     if (xsdcAttributesGroup.hasAttributes_optional()) {
         aidlAttributesGroup.attributes =
-                convertCollectionToAidl<xsd::AttributesType, AudioAttributes>(
+                convertCollectionToAidlUnchecked<xsd::AttributesType, AudioAttributes>(
                         xsdcAttributesGroup.getAttributes_optional(),
                         std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
                                   std::placeholders::_1));
@@ -172,7 +172,7 @@
 
     if (xsdcProductStrategy.hasAttributesGroup()) {
         aidlProductStrategy.attributesGroups =
-                convertCollectionToAidl<xsd::AttributesGroup, AudioHalAttributesGroup>(
+                convertCollectionToAidlUnchecked<xsd::AttributesGroup, AudioHalAttributesGroup>(
                         xsdcProductStrategy.getAttributesGroup(),
                         std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
                                   std::placeholders::_1));
@@ -204,13 +204,13 @@
                     getXsdcConfig()->getVolumes());
         }
         aidlVolumeCurve.curvePoints =
-                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                         mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
                         std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
                                   std::placeholders::_1));
     } else {
         aidlVolumeCurve.curvePoints =
-                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                         xsdcVolumeCurve.getPoint(),
                         std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
                                   std::placeholders::_1));
@@ -224,10 +224,11 @@
     aidlVolumeGroup.name = xsdcVolumeGroup.getName();
     aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
     aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
-    aidlVolumeGroup.volumeCurves = convertCollectionToAidl<xsd::Volume, AudioHalVolumeCurve>(
-            xsdcVolumeGroup.getVolume(),
-            std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
-                      std::placeholders::_1));
+    aidlVolumeGroup.volumeCurves =
+            convertCollectionToAidlUnchecked<xsd::Volume, AudioHalVolumeCurve>(
+                    xsdcVolumeGroup.getVolume(),
+                    std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
+                              std::placeholders::_1));
     return aidlVolumeGroup;
 }
 
@@ -251,7 +252,7 @@
     aidlCapCriterionType.name = xsdcCriterionType.getName();
     aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
     aidlCapCriterionType.values =
-            convertWrappedCollectionToAidl<xsd::ValuesType, xsd::ValueType, std::string>(
+            convertWrappedCollectionToAidlUnchecked<xsd::ValuesType, xsd::ValueType, std::string>(
                     xsdcCriterionType.getValues(), &xsd::ValuesType::getValue,
                     std::bind(&EngineConfigXmlConverter::convertCriterionTypeValueToAidl, this,
                               std::placeholders::_1));
@@ -266,9 +267,9 @@
     initProductStrategyMap();
     if (getXsdcConfig()->hasProductStrategies()) {
         mAidlEngineConfig.productStrategies =
-                convertWrappedCollectionToAidl<xsd::ProductStrategies,
-                                               xsd::ProductStrategies::ProductStrategy,
-                                               AudioHalProductStrategy>(
+                convertWrappedCollectionToAidlUnchecked<xsd::ProductStrategies,
+                                                        xsd::ProductStrategies::ProductStrategy,
+                                                        AudioHalProductStrategy>(
                         getXsdcConfig()->getProductStrategies(),
                         &xsd::ProductStrategies::getProductStrategy,
                         std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
@@ -278,7 +279,7 @@
         }
     }
     if (getXsdcConfig()->hasVolumeGroups()) {
-        mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidl<
+        mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidlUnchecked<
                 xsd::VolumeGroupsType, xsd::VolumeGroupsType::VolumeGroup, AudioHalVolumeGroup>(
                 getXsdcConfig()->getVolumeGroups(), &xsd::VolumeGroupsType::getVolumeGroup,
                 std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
@@ -287,19 +288,17 @@
     if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
         AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
         capSpecificConfig.criteria =
-                convertWrappedCollectionToAidl<xsd::CriteriaType, xsd::CriterionType,
-                                               AudioHalCapCriterion>(
+                convertWrappedCollectionToAidlUnchecked<xsd::CriteriaType, xsd::CriterionType,
+                                                        AudioHalCapCriterion>(
                         getXsdcConfig()->getCriteria(), &xsd::CriteriaType::getCriterion,
                         std::bind(&EngineConfigXmlConverter::convertCapCriterionToAidl, this,
                                   std::placeholders::_1));
-        capSpecificConfig.criterionTypes =
-                convertWrappedCollectionToAidl<xsd::CriterionTypesType, xsd::CriterionTypeType,
-                                               AudioHalCapCriterionType>(
-                        getXsdcConfig()->getCriterion_types(),
-                        &xsd::CriterionTypesType::getCriterion_type,
-                        std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
-                                  std::placeholders::_1));
+        capSpecificConfig.criterionTypes = convertWrappedCollectionToAidlUnchecked<
+                xsd::CriterionTypesType, xsd::CriterionTypeType, AudioHalCapCriterionType>(
+                getXsdcConfig()->getCriterion_types(), &xsd::CriterionTypesType::getCriterion_type,
+                std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
+                          std::placeholders::_1));
         mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
     }
 }
-}  // namespace aidl::android::hardware::audio::core::internal
\ No newline at end of file
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 6b417a4..b7761bf 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -18,20 +18,20 @@
 #include <set>
 
 #define LOG_TAG "AHAL_Module"
-#include <android-base/logging.h>
-#include <android/binder_ibinder_platform.h>
-
 #include <Utils.h>
 #include <aidl/android/media/audio/common/AudioInputFlags.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <error/expected_utils.h>
 
-#include "core-impl/Bluetooth.h"
 #include "core-impl/Module.h"
+#include "core-impl/ModuleBluetooth.h"
+#include "core-impl/ModulePrimary.h"
+#include "core-impl/ModuleRemoteSubmix.h"
+#include "core-impl/ModuleStub.h"
 #include "core-impl/ModuleUsb.h"
 #include "core-impl/SoundDose.h"
-#include "core-impl/StreamStub.h"
-#include "core-impl/StreamUsb.h"
-#include "core-impl/Telephony.h"
 #include "core-impl/utils.h"
 
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
@@ -110,36 +110,16 @@
 // static
 std::shared_ptr<Module> Module::createInstance(Type type) {
     switch (type) {
-        case Module::Type::USB:
-            return ndk::SharedRefBase::make<ModuleUsb>(type);
         case Type::DEFAULT:
+            return ndk::SharedRefBase::make<ModulePrimary>();
         case Type::R_SUBMIX:
-        default:
-            return ndk::SharedRefBase::make<Module>(type);
-    }
-}
-
-// static
-StreamIn::CreateInstance Module::getStreamInCreator(Type type) {
-    switch (type) {
+            return ndk::SharedRefBase::make<ModuleRemoteSubmix>();
+        case Type::STUB:
+            return ndk::SharedRefBase::make<ModuleStub>();
         case Type::USB:
-            return StreamInUsb::createInstance;
-        case Type::DEFAULT:
-        case Type::R_SUBMIX:
-        default:
-            return StreamInStub::createInstance;
-    }
-}
-
-// static
-StreamOut::CreateInstance Module::getStreamOutCreator(Type type) {
-    switch (type) {
-        case Type::USB:
-            return StreamOutUsb::createInstance;
-        case Type::DEFAULT:
-        case Type::R_SUBMIX:
-        default:
-            return StreamOutStub::createInstance;
+            return ndk::SharedRefBase::make<ModuleUsb>();
+        case Type::BLUETOOTH:
+            return ndk::SharedRefBase::make<ModuleBluetooth>();
     }
 }
 
@@ -151,9 +131,15 @@
         case Module::Type::R_SUBMIX:
             os << "r_submix";
             break;
+        case Module::Type::STUB:
+            os << "stub";
+            break;
         case Module::Type::USB:
             os << "usb";
             break;
+        case Module::Type::BLUETOOTH:
+            os << "bluetooth";
+            break;
     }
     return os;
 }
@@ -187,7 +173,7 @@
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     LOG(DEBUG) << __func__ << ": frame size " << frameSize << " bytes";
-    if (frameSize > kMaximumStreamBufferSizeBytes / in_bufferSizeFrames) {
+    if (frameSize > static_cast<size_t>(kMaximumStreamBufferSizeBytes / in_bufferSizeFrames)) {
         LOG(ERROR) << __func__ << ": buffer size " << in_bufferSizeFrames
                    << " frames is too large, maximum size is "
                    << kMaximumStreamBufferSizeBytes / frameSize;
@@ -206,8 +192,9 @@
         StreamContext temp(
                 std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
                 std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
-                portConfigIt->format.value(), portConfigIt->channelMask.value(),
-                portConfigIt->sampleRate.value().value,
+                portConfigIt->portId, portConfigIt->format.value(),
+                portConfigIt->channelMask.value(), portConfigIt->sampleRate.value().value, flags,
+                portConfigIt->ext.get<AudioPortExt::mix>().handle,
                 std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
                 asyncCallback, outEventCallback, params);
         if (temp.isValid()) {
@@ -281,7 +268,7 @@
                    << " does not correspond to a mix port";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    const int32_t maxOpenStreamCount = portIt->ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
+    const size_t maxOpenStreamCount = portIt->ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
     if (maxOpenStreamCount != 0 && mStreams.count(portId) >= maxOpenStreamCount) {
         LOG(ERROR) << __func__ << ": port id " << portId
                    << " has already reached maximum allowed opened stream count: "
@@ -305,19 +292,31 @@
     return result;
 }
 
+std::unique_ptr<internal::Configuration> Module::initializeConfig() {
+    std::unique_ptr<internal::Configuration> config;
+    switch (getType()) {
+        case Type::DEFAULT:
+            config = std::move(internal::getPrimaryConfiguration());
+            break;
+        case Type::R_SUBMIX:
+            config = std::move(internal::getRSubmixConfiguration());
+            break;
+        case Type::STUB:
+            config = std::move(internal::getStubConfiguration());
+            break;
+        case Type::USB:
+            config = std::move(internal::getUsbConfiguration());
+            break;
+        case Type::BLUETOOTH:
+            config = std::move(internal::getBluetoothConfiguration());
+            break;
+    }
+    return config;
+}
+
 internal::Configuration& Module::getConfig() {
     if (!mConfig) {
-        switch (mType) {
-            case Type::DEFAULT:
-                mConfig = std::move(internal::getPrimaryConfiguration());
-                break;
-            case Type::R_SUBMIX:
-                mConfig = std::move(internal::getRSubmixConfiguration());
-                break;
-            case Type::USB:
-                mConfig = std::move(internal::getUsbConfiguration());
-                break;
-        }
+        mConfig = std::move(initializeConfig());
     }
     return *mConfig;
 }
@@ -339,30 +338,61 @@
     do_insert(patch.sinkPortConfigIds);
 }
 
-void Module::updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch) {
+ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatch,
+                                                       const AudioPatch& newPatch) {
     // Streams from the old patch need to be disconnected, streams from the new
     // patch need to be connected. If the stream belongs to both patches, no need
     // to update it.
-    std::set<int32_t> idsToDisconnect, idsToConnect;
+    auto maybeFailure = ndk::ScopedAStatus::ok();
+    std::set<int32_t> idsToDisconnect, idsToConnect, idsToDisconnectOnFailure;
     idsToDisconnect.insert(oldPatch.sourcePortConfigIds.begin(),
                            oldPatch.sourcePortConfigIds.end());
     idsToDisconnect.insert(oldPatch.sinkPortConfigIds.begin(), oldPatch.sinkPortConfigIds.end());
     idsToConnect.insert(newPatch.sourcePortConfigIds.begin(), newPatch.sourcePortConfigIds.end());
     idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end());
     std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) {
-        if (idsToConnect.count(portConfigId) == 0) {
-            LOG(DEBUG) << "The stream on port config id " << portConfigId << " is not connected";
-            mStreams.setStreamIsConnected(portConfigId, {});
+        if (idsToConnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
+            if (auto status = mStreams.setStreamConnectedDevices(portConfigId, {}); status.isOk()) {
+                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
+                           << portConfigId << " has been disconnected";
+            } else {
+                // Disconnection is tricky to roll back, just register a failure.
+                maybeFailure = std::move(status);
+            }
         }
     });
+    if (!maybeFailure.isOk()) return maybeFailure;
     std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) {
-        if (idsToDisconnect.count(portConfigId) == 0) {
+        if (idsToDisconnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
             const auto connectedDevices = findConnectedDevices(portConfigId);
-            LOG(DEBUG) << "The stream on port config id " << portConfigId
-                       << " is connected to: " << ::android::internal::ToString(connectedDevices);
-            mStreams.setStreamIsConnected(portConfigId, connectedDevices);
+            if (connectedDevices.empty()) {
+                // This is important as workers use the vector size to derive the connection status.
+                LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port "
+                              "config id "
+                           << portConfigId;
+            }
+            if (auto status = mStreams.setStreamConnectedDevices(portConfigId, connectedDevices);
+                status.isOk()) {
+                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
+                           << portConfigId << " has been connected to: "
+                           << ::android::internal::ToString(connectedDevices);
+            } else {
+                maybeFailure = std::move(status);
+                idsToDisconnectOnFailure.insert(portConfigId);
+            }
         }
     });
+    if (!maybeFailure.isOk()) {
+        LOG(WARNING) << __func__ << ": Due to a failure, disconnecting streams on port config ids "
+                     << ::android::internal::ToString(idsToDisconnectOnFailure);
+        std::for_each(idsToDisconnectOnFailure.begin(), idsToDisconnectOnFailure.end(),
+                      [&](const auto& portConfigId) {
+                          auto status = mStreams.setStreamConnectedDevices(portConfigId, {});
+                          (void)status.isOk();  // Can't do much about a failure here.
+                      });
+        return maybeFailure;
+    }
+    return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Module::setModuleDebug(
@@ -386,38 +416,26 @@
 }
 
 ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
-    if (!mTelephony) {
-        mTelephony = ndk::SharedRefBase::make<Telephony>();
-    }
-    *_aidl_return = mTelephony.getPtr();
-    LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Module::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
-    if (!mBluetooth) {
-        mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
-    }
-    *_aidl_return = mBluetooth.getPtr();
-    LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get();
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Module::getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
-    if (!mBluetoothA2dp) {
-        mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
-    }
-    *_aidl_return = mBluetoothA2dp.getPtr();
-    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Module::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
-    if (!mBluetoothLe) {
-        mBluetoothLe = ndk::SharedRefBase::make<BluetoothLe>();
-    }
-    *_aidl_return = mBluetoothLe.getPtr();
-    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
     return ndk::ScopedAStatus::ok();
 }
 
@@ -436,16 +454,15 @@
             LOG(ERROR) << __func__ << ": port id " << templateId << " is not a device port";
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
-        if (!templateIt->profiles.empty()) {
-            LOG(ERROR) << __func__ << ": port id " << templateId
-                       << " does not have dynamic profiles";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-        }
         auto& templateDevicePort = templateIt->ext.get<AudioPortExt::Tag::device>();
         if (templateDevicePort.device.type.connection.empty()) {
             LOG(ERROR) << __func__ << ": port id " << templateId << " is permanently attached";
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
+        if (mConnectedDevicePorts.find(templateId) != mConnectedDevicePorts.end()) {
+            LOG(ERROR) << __func__ << ": port id " << templateId << " is a connected device port";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
         // Postpone id allocation until we ensure that there are no client errors.
         connectedPort = *templateIt;
         connectedPort.extraAudioDescriptors = in_templateIdAndAdditionalData.extraAudioDescriptors;
@@ -468,22 +485,34 @@
         }
     }
 
-    if (!mDebug.simulateDeviceConnections) {
-        if (ndk::ScopedAStatus status = populateConnectedDevicePort(&connectedPort);
-            !status.isOk()) {
-            return status;
+    if (connectedPort.profiles.empty()) {
+        if (!mDebug.simulateDeviceConnections) {
+            RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
+        } else {
+            auto& connectedProfiles = getConfig().connectedProfiles;
+            if (auto connectedProfilesIt = connectedProfiles.find(templateId);
+                connectedProfilesIt != connectedProfiles.end()) {
+                connectedPort.profiles = connectedProfilesIt->second;
+            }
         }
-    } else {
-        auto& connectedProfiles = getConfig().connectedProfiles;
-        if (auto connectedProfilesIt = connectedProfiles.find(templateId);
-            connectedProfilesIt != connectedProfiles.end()) {
-            connectedPort.profiles = connectedProfilesIt->second;
+        if (connectedPort.profiles.empty()) {
+            LOG(ERROR) << __func__
+                       << ": profiles of a connected port still empty after connecting external "
+                          "device "
+                       << connectedPort.toString();
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
         }
     }
-    if (connectedPort.profiles.empty()) {
-        LOG(ERROR) << "Profiles of a connected port still empty after connecting external device "
-                   << connectedPort.toString();
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+
+    for (auto profile : connectedPort.profiles) {
+        if (profile.channelMasks.empty()) {
+            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no channel masks";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+        if (profile.sampleRates.empty()) {
+            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no sample rates";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
     }
 
     connectedPort.id = ++getConfig().nextPortId;
@@ -647,34 +676,26 @@
     LOG(DEBUG) << __func__ << ": port config id " << in_args.portConfigId << ", buffer size "
                << in_args.bufferSizeFrames << " frames";
     AudioPort* port = nullptr;
-    if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(findPortIdForNewStream(in_args.portConfigId, &port));
     if (port->flags.getTag() != AudioIoFlags::Tag::input) {
         LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
                    << " does not correspond to an input mix port";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     StreamContext context;
-    if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames, nullptr,
-                                          nullptr, &context);
-        !status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
+                                               nullptr, nullptr, &context));
     context.fillDescriptor(&_aidl_return->desc);
     std::shared_ptr<StreamIn> stream;
-    ndk::ScopedAStatus status = getStreamInCreator(mType)(in_args.sinkMetadata, std::move(context),
-                                                          mConfig->microphones, &stream);
-    if (!status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
+                                             mConfig->microphones, &stream));
     StreamWrapper streamWrapper(stream);
+    if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
+        RETURN_STATUS_IF_ERROR(
+                streamWrapper.setConnectedDevices(findConnectedDevices(in_args.portConfigId)));
+    }
     AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
                                    ANDROID_PRIORITY_AUDIO);
-    auto patchIt = mPatches.find(in_args.portConfigId);
-    if (patchIt != mPatches.end()) {
-        streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
-    }
     mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
     _aidl_return->stream = std::move(stream);
     return ndk::ScopedAStatus::ok();
@@ -686,9 +707,7 @@
                << (in_args.offloadInfo.has_value()) << ", buffer size " << in_args.bufferSizeFrames
                << " frames";
     AudioPort* port = nullptr;
-    if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(findPortIdForNewStream(in_args.portConfigId, &port));
     if (port->flags.getTag() != AudioIoFlags::Tag::output) {
         LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
                    << " does not correspond to an output mix port";
@@ -709,26 +728,20 @@
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     StreamContext context;
-    if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
-                                          isNonBlocking ? in_args.callback : nullptr,
-                                          in_args.eventCallback, &context);
-        !status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
+                                               isNonBlocking ? in_args.callback : nullptr,
+                                               in_args.eventCallback, &context));
     context.fillDescriptor(&_aidl_return->desc);
     std::shared_ptr<StreamOut> stream;
-    ndk::ScopedAStatus status = getStreamOutCreator(mType)(
-            in_args.sourceMetadata, std::move(context), in_args.offloadInfo, &stream);
-    if (!status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata,
+                                              in_args.offloadInfo, &stream));
     StreamWrapper streamWrapper(stream);
+    if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
+        RETURN_STATUS_IF_ERROR(
+                streamWrapper.setConnectedDevices(findConnectedDevices(in_args.portConfigId)));
+    }
     AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
                                    ANDROID_PRIORITY_AUDIO);
-    auto patchIt = mPatches.find(in_args.portConfigId);
-    if (patchIt != mPatches.end()) {
-        streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
-    }
     mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
     _aidl_return->stream = std::move(stream);
     return ndk::ScopedAStatus::ok();
@@ -796,10 +809,7 @@
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
     }
-
-    if (auto status = checkAudioPatchEndpointsMatch(sources, sinks); !status.isOk()) {
-        return status;
-    }
+    RETURN_STATUS_IF_ERROR(checkAudioPatchEndpointsMatch(sources, sinks));
 
     auto& patches = getConfig().patches;
     auto existing = patches.end();
@@ -834,13 +844,20 @@
     if (existing == patches.end()) {
         _aidl_return->id = getConfig().nextPatchId++;
         patches.push_back(*_aidl_return);
-        existing = patches.begin() + (patches.size() - 1);
     } else {
         oldPatch = *existing;
-        *existing = *_aidl_return;
     }
-    registerPatch(*existing);
-    updateStreamsConnectedState(oldPatch, *_aidl_return);
+    patchesBackup = mPatches;
+    registerPatch(*_aidl_return);
+    if (auto status = updateStreamsConnectedState(oldPatch, *_aidl_return); !status.isOk()) {
+        mPatches = std::move(*patchesBackup);
+        if (existing == patches.end()) {
+            patches.pop_back();
+        } else {
+            *existing = oldPatch;
+        }
+        return status;
+    }
 
     LOG(DEBUG) << __func__ << ": " << (oldPatch.id == 0 ? "created" : "updated") << " patch "
                << _aidl_return->toString();
@@ -992,8 +1009,12 @@
     auto& patches = getConfig().patches;
     auto patchIt = findById<AudioPatch>(patches, in_patchId);
     if (patchIt != patches.end()) {
+        auto patchesBackup = mPatches;
         cleanUpPatch(patchIt->id);
-        updateStreamsConnectedState(*patchIt, AudioPatch{});
+        if (auto status = updateStreamsConnectedState(*patchIt, AudioPatch{}); !status.isOk()) {
+            mPatches = std::move(patchesBackup);
+            return status;
+        }
         patches.erase(patchIt);
         LOG(DEBUG) << __func__ << ": erased patch " << in_patchId;
         return ndk::ScopedAStatus::ok();
@@ -1120,7 +1141,7 @@
     if (!mSoundDose) {
         mSoundDose = ndk::SharedRefBase::make<sounddose::SoundDose>();
     }
-    *_aidl_return = mSoundDose.getPtr();
+    *_aidl_return = mSoundDose.getInstance();
     LOG(DEBUG) << __func__ << ": returning instance of ISoundDose: " << _aidl_return->get();
     return ndk::ScopedAStatus::ok();
 }
@@ -1353,4 +1374,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
+Module::BtProfileHandles Module::getBtProfileManagerHandles() {
+    return std::make_tuple(std::weak_ptr<IBluetooth>(), std::weak_ptr<IBluetoothA2dp>(),
+                           std::weak_ptr<IBluetoothLe>());
+}
+
+ndk::ScopedAStatus Module::bluetoothParametersUpdated() {
+    return mStreams.bluetoothParametersUpdated();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
new file mode 100644
index 0000000..9919c7f
--- /dev/null
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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 <vector>
+
+#define LOG_TAG "AHAL_ModulePrimary"
+#include <Utils.h>
+#include <android-base/logging.h>
+
+#include "core-impl/ModulePrimary.h"
+#include "core-impl/StreamPrimary.h"
+#include "core-impl/Telephony.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
+    if (!mTelephony) {
+        mTelephony = ndk::SharedRefBase::make<Telephony>();
+    }
+    *_aidl_return = mTelephony.getInstance();
+    LOG(DEBUG) << __func__
+               << ": returning instance of ITelephony: " << _aidl_return->get()->asBinder().get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context,
+                                                    const SinkMetadata& sinkMetadata,
+                                                    const std::vector<MicrophoneInfo>& microphones,
+                                                    std::shared_ptr<StreamIn>* result) {
+    return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata,
+                                                 microphones);
+}
+
+ndk::ScopedAStatus ModulePrimary::createOutputStream(
+        StreamContext&& context, const SourceMetadata& sourceMetadata,
+        const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+    return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
+                                                  offloadInfo);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 77b0601..af89f5f 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -27,12 +27,16 @@
 using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDualMonoMode;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioLatencyMode;
 using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
 using aidl::android::media::audio::common::AudioPlaybackRate;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
@@ -47,13 +51,19 @@
         desc->reply = mReplyMQ->dupeDesc();
     }
     if (mDataMQ) {
-        const size_t frameSize = getFrameSize();
-        desc->frameSizeBytes = frameSize;
-        desc->bufferSizeFrames = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / frameSize;
+        desc->frameSizeBytes = getFrameSize();
+        desc->bufferSizeFrames = getBufferSizeInFrames();
         desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
     }
 }
 
+size_t StreamContext::getBufferSizeInFrames() const {
+    if (mDataMQ) {
+        return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize();
+    }
+    return 0;
+}
+
 size_t StreamContext::getFrameSize() const {
     return getFrameSizeInBytes(mFormat, mChannelLayout);
 }
@@ -85,17 +95,18 @@
 }
 
 std::string StreamWorkerCommonLogic::init() {
-    if (mCommandMQ == nullptr) return "Command MQ is null";
-    if (mReplyMQ == nullptr) return "Reply MQ is null";
-    if (mDataMQ == nullptr) return "Data MQ is null";
-    if (sizeof(DataBufferElement) != mDataMQ->getQuantumSize()) {
-        return "Unexpected Data MQ quantum size: " + std::to_string(mDataMQ->getQuantumSize());
+    if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
+    if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
+    StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+    if (dataMQ == nullptr) return "Data MQ is null";
+    if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
+        return "Unexpected Data MQ quantum size: " + std::to_string(dataMQ->getQuantumSize());
     }
-    mDataBufferSize = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize();
+    mDataBufferSize = dataMQ->getQuantumCount() * dataMQ->getQuantumSize();
     mDataBuffer.reset(new (std::nothrow) DataBufferElement[mDataBufferSize]);
     if (mDataBuffer == nullptr) {
         return "Failed to allocate data buffer for element count " +
-               std::to_string(mDataMQ->getQuantumCount()) +
+               std::to_string(dataMQ->getQuantumCount()) +
                ", size in bytes: " + std::to_string(mDataBufferSize);
     }
     if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
@@ -108,12 +119,14 @@
                                             bool isConnected) const {
     reply->status = STATUS_OK;
     if (isConnected) {
-        reply->observable.frames = mFrameCount;
+        reply->observable.frames = mContext->getFrameCount();
         reply->observable.timeNs = ::android::elapsedRealtimeNano();
-    } else {
-        reply->observable.frames = StreamDescriptor::Position::UNKNOWN;
-        reply->observable.timeNs = StreamDescriptor::Position::UNKNOWN;
+        if (auto status = mDriver->refinePosition(&reply->observable); status == ::android::OK) {
+            return;
+        }
     }
+    reply->observable.frames = StreamDescriptor::Position::UNKNOWN;
+    reply->observable.timeNs = StreamDescriptor::Position::UNKNOWN;
 }
 
 void StreamWorkerCommonLogic::populateReplyWrongState(
@@ -133,7 +146,7 @@
     // TODO: Add a delay for transitions of async operations when/if they added.
 
     StreamDescriptor::Command command{};
-    if (!mCommandMQ->readBlocking(&command, 1)) {
+    if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
         LOG(ERROR) << __func__ << ": reading of command from MQ failed";
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
@@ -151,7 +164,8 @@
     switch (command.getTag()) {
         case Tag::halReservedExit:
             if (const int32_t cookie = command.get<Tag::halReservedExit>();
-                cookie == mInternalCommandCookie) {
+                cookie == mContext->getInternalCommandCookie()) {
+                mDriver->shutdown();
                 setClosed();
                 // This is an internal command, no need to reply.
                 return Status::EXIT;
@@ -165,10 +179,15 @@
         case Tag::start:
             if (mState == StreamDescriptor::State::STANDBY ||
                 mState == StreamDescriptor::State::DRAINING) {
-                populateReply(&reply, mIsConnected);
-                mState = mState == StreamDescriptor::State::STANDBY
-                                 ? StreamDescriptor::State::IDLE
-                                 : StreamDescriptor::State::ACTIVE;
+                if (::android::status_t status = mDriver->start(); status == ::android::OK) {
+                    populateReply(&reply, mIsConnected);
+                    mState = mState == StreamDescriptor::State::STANDBY
+                                     ? StreamDescriptor::State::IDLE
+                                     : StreamDescriptor::State::ACTIVE;
+                } else {
+                    LOG(ERROR) << __func__ << ": start failed: " << status;
+                    mState = StreamDescriptor::State::ERROR;
+                }
             } else {
                 populateReplyWrongState(&reply, command);
             }
@@ -223,8 +242,8 @@
             break;
         case Tag::standby:
             if (mState == StreamDescriptor::State::IDLE) {
+                populateReply(&reply, mIsConnected);
                 if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
-                    populateReply(&reply, mIsConnected);
                     mState = StreamDescriptor::State::STANDBY;
                 } else {
                     LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -263,7 +282,7 @@
     }
     reply.state = mState;
     LOG(severity) << __func__ << ": writing reply " << reply.toString();
-    if (!mReplyMQ->writeBlocking(&reply, 1)) {
+    if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
         LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
@@ -272,14 +291,16 @@
 }
 
 bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply) {
-    const size_t byteCount = std::min({clientSize, mDataMQ->availableToWrite(), mDataBufferSize});
+    StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+    const size_t byteCount = std::min({clientSize, dataMQ->availableToWrite(), mDataBufferSize});
     const bool isConnected = mIsConnected;
+    const size_t frameSize = mContext->getFrameSize();
     size_t actualFrameCount = 0;
     bool fatal = false;
     int32_t latency = Module::kLatencyMs;
     if (isConnected) {
-        if (::android::status_t status = mDriver->transfer(
-                    mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
+        if (::android::status_t status = mDriver->transfer(mDataBuffer.get(), byteCount / frameSize,
+                                                           &actualFrameCount, &latency);
             status != ::android::OK) {
             fatal = true;
             LOG(ERROR) << __func__ << ": read failed: " << status;
@@ -287,17 +308,16 @@
     } else {
         usleep(3000);  // Simulate blocking transfer delay.
         for (size_t i = 0; i < byteCount; ++i) mDataBuffer[i] = 0;
-        actualFrameCount = byteCount / mFrameSize;
+        actualFrameCount = byteCount / frameSize;
     }
-    const size_t actualByteCount = actualFrameCount * mFrameSize;
-    if (bool success =
-                actualByteCount > 0 ? mDataMQ->write(&mDataBuffer[0], actualByteCount) : true;
+    const size_t actualByteCount = actualFrameCount * frameSize;
+    if (bool success = actualByteCount > 0 ? dataMQ->write(&mDataBuffer[0], actualByteCount) : true;
         success) {
         LOG(VERBOSE) << __func__ << ": writing of " << actualByteCount << " bytes into data MQ"
                      << " succeeded; connected? " << isConnected;
         // Frames are provided and counted regardless of connection status.
         reply->fmqByteCount += actualByteCount;
-        mFrameCount += actualFrameCount;
+        mContext->advanceFrameCount(actualFrameCount);
         populateReply(reply, isConnected);
     } else {
         LOG(WARNING) << __func__ << ": writing of " << actualByteCount
@@ -316,7 +336,8 @@
         if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
                     std::chrono::steady_clock::now() - mTransientStateStart);
             stateDurationMs >= mTransientStateDelayMs) {
-            if (mAsyncCallback == nullptr) {
+            std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
+            if (asyncCallback == nullptr) {
                 // In blocking mode, mState can only be DRAINING.
                 mState = StreamDescriptor::State::IDLE;
             } else {
@@ -324,13 +345,13 @@
                 // drain or transfer completion. In the stub, we switch unconditionally.
                 if (mState == StreamDescriptor::State::DRAINING) {
                     mState = StreamDescriptor::State::IDLE;
-                    ndk::ScopedAStatus status = mAsyncCallback->onDrainReady();
+                    ndk::ScopedAStatus status = asyncCallback->onDrainReady();
                     if (!status.isOk()) {
                         LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
                     }
                 } else {
                     mState = StreamDescriptor::State::ACTIVE;
-                    ndk::ScopedAStatus status = mAsyncCallback->onTransferReady();
+                    ndk::ScopedAStatus status = asyncCallback->onTransferReady();
                     if (!status.isOk()) {
                         LOG(ERROR) << __func__ << ": error from onTransferReady: " << status;
                     }
@@ -344,7 +365,7 @@
     }
 
     StreamDescriptor::Command command{};
-    if (!mCommandMQ->readBlocking(&command, 1)) {
+    if (!mContext->getCommandMQ()->readBlocking(&command, 1)) {
         LOG(ERROR) << __func__ << ": reading of command from MQ failed";
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
@@ -363,7 +384,8 @@
     switch (command.getTag()) {
         case Tag::halReservedExit:
             if (const int32_t cookie = command.get<Tag::halReservedExit>();
-                cookie == mInternalCommandCookie) {
+                cookie == mContext->getInternalCommandCookie()) {
+                mDriver->shutdown();
                 setClosed();
                 // This is an internal command, no need to reply.
                 return Status::EXIT;
@@ -375,26 +397,36 @@
             populateReply(&reply, mIsConnected);
             break;
         case Tag::start: {
-            bool commandAccepted = true;
+            std::optional<StreamDescriptor::State> nextState;
             switch (mState) {
                 case StreamDescriptor::State::STANDBY:
-                    mState = StreamDescriptor::State::IDLE;
+                    nextState = StreamDescriptor::State::IDLE;
                     break;
                 case StreamDescriptor::State::PAUSED:
-                    mState = StreamDescriptor::State::ACTIVE;
+                    nextState = StreamDescriptor::State::ACTIVE;
                     break;
                 case StreamDescriptor::State::DRAIN_PAUSED:
-                    switchToTransientState(StreamDescriptor::State::DRAINING);
+                    nextState = StreamDescriptor::State::DRAINING;
                     break;
                 case StreamDescriptor::State::TRANSFER_PAUSED:
-                    switchToTransientState(StreamDescriptor::State::TRANSFERRING);
+                    nextState = StreamDescriptor::State::TRANSFERRING;
                     break;
                 default:
                     populateReplyWrongState(&reply, command);
-                    commandAccepted = false;
             }
-            if (commandAccepted) {
-                populateReply(&reply, mIsConnected);
+            if (nextState.has_value()) {
+                if (::android::status_t status = mDriver->start(); status == ::android::OK) {
+                    populateReply(&reply, mIsConnected);
+                    if (*nextState == StreamDescriptor::State::IDLE ||
+                        *nextState == StreamDescriptor::State::ACTIVE) {
+                        mState = *nextState;
+                    } else {
+                        switchToTransientState(*nextState);
+                    }
+                } else {
+                    LOG(ERROR) << __func__ << ": start failed: " << status;
+                    mState = StreamDescriptor::State::ERROR;
+                }
             }
         } break;
         case Tag::burst:
@@ -407,10 +439,11 @@
                     if (!write(fmqByteCount, &reply)) {
                         mState = StreamDescriptor::State::ERROR;
                     }
+                    std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
                     if (mState == StreamDescriptor::State::STANDBY ||
                         mState == StreamDescriptor::State::DRAIN_PAUSED ||
                         mState == StreamDescriptor::State::PAUSED) {
-                        if (mAsyncCallback == nullptr ||
+                        if (asyncCallback == nullptr ||
                             mState != StreamDescriptor::State::DRAIN_PAUSED) {
                             mState = StreamDescriptor::State::PAUSED;
                         } else {
@@ -419,7 +452,7 @@
                     } else if (mState == StreamDescriptor::State::IDLE ||
                                mState == StreamDescriptor::State::DRAINING ||
                                mState == StreamDescriptor::State::ACTIVE) {
-                        if (mAsyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
+                        if (asyncCallback == nullptr || reply.fmqByteCount == fmqByteCount) {
                             mState = StreamDescriptor::State::ACTIVE;
                         } else {
                             switchToTransientState(StreamDescriptor::State::TRANSFERRING);
@@ -441,7 +474,8 @@
                     if (::android::status_t status = mDriver->drain(mode);
                         status == ::android::OK) {
                         populateReply(&reply, mIsConnected);
-                        if (mState == StreamDescriptor::State::ACTIVE && mForceSynchronousDrain) {
+                        if (mState == StreamDescriptor::State::ACTIVE &&
+                            mContext->getForceSynchronousDrain()) {
                             mState = StreamDescriptor::State::IDLE;
                         } else {
                             switchToTransientState(StreamDescriptor::State::DRAINING);
@@ -462,8 +496,8 @@
             break;
         case Tag::standby:
             if (mState == StreamDescriptor::State::IDLE) {
+                populateReply(&reply, mIsConnected);
                 if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
-                    populateReply(&reply, mIsConnected);
                     mState = StreamDescriptor::State::STANDBY;
                 } else {
                     LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -516,7 +550,7 @@
     }
     reply.state = mState;
     LOG(severity) << __func__ << ": writing reply " << reply.toString();
-    if (!mReplyMQ->writeBlocking(&reply, 1)) {
+    if (!mContext->getReplyMQ()->writeBlocking(&reply, 1)) {
         LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
@@ -525,38 +559,40 @@
 }
 
 bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* reply) {
-    const size_t readByteCount = mDataMQ->availableToRead();
+    StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
+    const size_t readByteCount = dataMQ->availableToRead();
+    const size_t frameSize = mContext->getFrameSize();
     bool fatal = false;
     int32_t latency = Module::kLatencyMs;
-    if (bool success = readByteCount > 0 ? mDataMQ->read(&mDataBuffer[0], readByteCount) : true) {
+    if (bool success = readByteCount > 0 ? dataMQ->read(&mDataBuffer[0], readByteCount) : true) {
         const bool isConnected = mIsConnected;
         LOG(VERBOSE) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
                      << " succeeded; connected? " << isConnected;
         // Amount of data that the HAL module is going to actually use.
         size_t byteCount = std::min({clientSize, readByteCount, mDataBufferSize});
-        if (byteCount >= mFrameSize && mForceTransientBurst) {
+        if (byteCount >= frameSize && mContext->getForceTransientBurst()) {
             // In order to prevent the state machine from going to ACTIVE state,
             // simulate partial write.
-            byteCount -= mFrameSize;
+            byteCount -= frameSize;
         }
         size_t actualFrameCount = 0;
         if (isConnected) {
             if (::android::status_t status = mDriver->transfer(
-                        mDataBuffer.get(), byteCount / mFrameSize, &actualFrameCount, &latency);
+                        mDataBuffer.get(), byteCount / frameSize, &actualFrameCount, &latency);
                 status != ::android::OK) {
                 fatal = true;
                 LOG(ERROR) << __func__ << ": write failed: " << status;
             }
         } else {
-            if (mAsyncCallback == nullptr) {
+            if (mContext->getAsyncCallback() == nullptr) {
                 usleep(3000);  // Simulate blocking transfer delay.
             }
-            actualFrameCount = byteCount / mFrameSize;
+            actualFrameCount = byteCount / frameSize;
         }
-        const size_t actualByteCount = actualFrameCount * mFrameSize;
+        const size_t actualByteCount = actualFrameCount * frameSize;
         // Frames are consumed and counted regardless of the connection status.
         reply->fmqByteCount += actualByteCount;
-        mFrameCount += actualFrameCount;
+        mContext->advanceFrameCount(actualFrameCount);
         populateReply(reply, isConnected);
     } else {
         LOG(WARNING) << __func__ << ": reading of " << readByteCount
@@ -567,8 +603,7 @@
     return !fatal;
 }
 
-template <class Metadata>
-StreamCommonImpl<Metadata>::~StreamCommonImpl() {
+StreamCommonImpl::~StreamCommonImpl() {
     if (!isClosed()) {
         LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
         stopWorker();
@@ -576,52 +611,65 @@
     }
 }
 
-template <class Metadata>
-void StreamCommonImpl<Metadata>::createStreamCommon(
+ndk::ScopedAStatus StreamCommonImpl::initInstance(
         const std::shared_ptr<StreamCommonInterface>& delegate) {
-    if (mCommon != nullptr) {
-        LOG(FATAL) << __func__ << ": attempting to create the common interface twice";
+    mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
+    if (!mWorker->start()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
-    mCommon = ndk::SharedRefBase::make<StreamCommon>(delegate);
-    mCommonBinder = mCommon->asBinder();
-    AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+    if (auto flags = getContext().getFlags();
+        (flags.getTag() == AudioIoFlags::Tag::input &&
+         isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::input>(),
+                              AudioInputFlags::FAST)) ||
+        (flags.getTag() == AudioIoFlags::Tag::output &&
+         isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+                              AudioOutputFlags::FAST))) {
+        // FAST workers should be run with a SCHED_FIFO scheduler, however the host process
+        // might be lacking the capability to request it, thus a failure to set is not an error.
+        pid_t workerTid = mWorker->getTid();
+        if (workerTid > 0) {
+            struct sched_param param;
+            param.sched_priority = 3;  // Must match SchedulingPolicyService.PRIORITY_MAX (Java).
+            if (sched_setscheduler(workerTid, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+                PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler for a fast thread";
+            }
+        } else {
+            LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
+        }
+    }
+    return ndk::ScopedAStatus::ok();
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::getStreamCommon(
+ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
         std::shared_ptr<IStreamCommon>* _aidl_return) {
-    if (mCommon == nullptr) {
+    if (!mCommon) {
         LOG(FATAL) << __func__ << ": the common interface was not created";
     }
-    *_aidl_return = mCommon;
+    *_aidl_return = mCommon.getInstance();
     LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
     return ndk::ScopedAStatus::ok();
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::updateHwAvSyncId(int32_t in_hwAvSyncId) {
+ndk::ScopedAStatus StreamCommonImpl::updateHwAvSyncId(int32_t in_hwAvSyncId) {
     LOG(DEBUG) << __func__ << ": id " << in_hwAvSyncId;
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::getVendorParameters(
+ndk::ScopedAStatus StreamCommonImpl::getVendorParameters(
         const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) {
     LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
     (void)_aidl_return;
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::setVendorParameters(
+ndk::ScopedAStatus StreamCommonImpl::setVendorParameters(
         const std::vector<VendorParameter>& in_parameters, bool in_async) {
     LOG(DEBUG) << __func__ << ": parameters count " << in_parameters.size()
                << ", async: " << in_async;
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::addEffect(
+ndk::ScopedAStatus StreamCommonImpl::addEffect(
         const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
     if (in_effect == nullptr) {
         LOG(DEBUG) << __func__ << ": null effect";
@@ -631,8 +679,7 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::removeEffect(
+ndk::ScopedAStatus StreamCommonImpl::removeEffect(
         const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect) {
     if (in_effect == nullptr) {
         LOG(DEBUG) << __func__ << ": null effect";
@@ -642,16 +689,14 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::close() {
+ndk::ScopedAStatus StreamCommonImpl::close() {
     LOG(DEBUG) << __func__;
     if (!isClosed()) {
         stopWorker();
         LOG(DEBUG) << __func__ << ": joining the worker thread...";
         mWorker->stop();
         LOG(DEBUG) << __func__ << ": worker thread joined";
-        mContext.reset();
-        mWorker->setClosed();
+        onClose(mWorker->setClosed());
         return ndk::ScopedAStatus::ok();
     } else {
         LOG(ERROR) << __func__ << ": stream was already closed";
@@ -659,8 +704,7 @@
     }
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::prepareToClose() {
+ndk::ScopedAStatus StreamCommonImpl::prepareToClose() {
     LOG(DEBUG) << __func__;
     if (!isClosed()) {
         return ndk::ScopedAStatus::ok();
@@ -669,8 +713,7 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
 }
 
-template <class Metadata>
-void StreamCommonImpl<Metadata>::stopWorker() {
+void StreamCommonImpl::stopWorker() {
     if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
         LOG(DEBUG) << __func__ << ": asking the worker to exit...";
         auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
@@ -686,10 +729,12 @@
     }
 }
 
-template <class Metadata>
-ndk::ScopedAStatus StreamCommonImpl<Metadata>::updateMetadata(const Metadata& metadata) {
+ndk::ScopedAStatus StreamCommonImpl::updateMetadataCommon(const Metadata& metadata) {
     LOG(DEBUG) << __func__;
     if (!isClosed()) {
+        if (metadata.index() != mMetadata.index()) {
+            LOG(FATAL) << __func__ << ": changing metadata variant is not allowed";
+        }
         mMetadata = metadata;
         return ndk::ScopedAStatus::ok();
     }
@@ -697,15 +742,18 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
 }
 
-// static
-ndk::ScopedAStatus StreamIn::initInstance(const std::shared_ptr<StreamIn>& stream) {
-    if (auto status = stream->init(); !status.isOk()) {
-        return status;
-    }
-    stream->createStreamCommon(stream);
+ndk::ScopedAStatus StreamCommonImpl::setConnectedDevices(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    mWorker->setIsConnected(!devices.empty());
+    mConnectedDevices = devices;
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
+    LOG(DEBUG) << __func__;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 namespace {
 static std::map<AudioDevice, std::string> transformMicrophones(
         const std::vector<MicrophoneInfo>& microphones) {
@@ -716,22 +764,22 @@
 }
 }  // namespace
 
-StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext&& context,
-                   const DriverInterface::CreateInstance& createDriver,
-                   const StreamWorkerInterface::CreateInstance& createWorker,
-                   const std::vector<MicrophoneInfo>& microphones)
-    : StreamCommonImpl<SinkMetadata>(sinkMetadata, std::move(context), createDriver, createWorker),
-      mMicrophones(transformMicrophones(microphones)) {
+StreamIn::StreamIn(StreamContext&& context, const std::vector<MicrophoneInfo>& microphones)
+    : mContextInstance(std::move(context)), mMicrophones(transformMicrophones(microphones)) {
     LOG(DEBUG) << __func__;
 }
 
+void StreamIn::defaultOnClose() {
+    mContextInstance.reset();
+}
+
 ndk::ScopedAStatus StreamIn::getActiveMicrophones(
         std::vector<MicrophoneDynamicInfo>* _aidl_return) {
     std::vector<MicrophoneDynamicInfo> result;
     std::vector<MicrophoneDynamicInfo::ChannelMapping> channelMapping{
-            getChannelCount(mContext.getChannelLayout()),
+            getChannelCount(getContext().getChannelLayout()),
             MicrophoneDynamicInfo::ChannelMapping::DIRECT};
-    for (auto it = mConnectedDevices.begin(); it != mConnectedDevices.end(); ++it) {
+    for (auto it = getConnectedDevices().begin(); it != getConnectedDevices().end(); ++it) {
         if (auto micIt = mMicrophones.find(*it); micIt != mMicrophones.end()) {
             MicrophoneDynamicInfo dynMic;
             dynMic.id = micIt->second;
@@ -777,25 +825,41 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-// static
-ndk::ScopedAStatus StreamOut::initInstance(const std::shared_ptr<StreamOut>& stream) {
-    if (auto status = stream->init(); !status.isOk()) {
-        return status;
-    }
-    stream->createStreamCommon(stream);
+StreamInHwGainHelper::StreamInHwGainHelper(const StreamContext* context)
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamInHwGainHelper::getHwGainImpl(std::vector<float>* _aidl_return) {
+    *_aidl_return = mHwGains;
+    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
 }
 
-StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext&& context,
-                     const DriverInterface::CreateInstance& createDriver,
-                     const StreamWorkerInterface::CreateInstance& createWorker,
-                     const std::optional<AudioOffloadInfo>& offloadInfo)
-    : StreamCommonImpl<SourceMetadata>(sourceMetadata, std::move(context), createDriver,
-                                       createWorker),
-      mOffloadInfo(offloadInfo) {
+ndk::ScopedAStatus StreamInHwGainHelper::setHwGainImpl(const std::vector<float>& in_channelGains) {
+    LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+    if (in_channelGains.size() != mChannelCount) {
+        LOG(ERROR) << __func__
+                   << ": channel count does not match stream channel count: " << mChannelCount;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    for (float gain : in_channelGains) {
+        if (gain < StreamIn::HW_GAIN_MIN || gain > StreamIn::HW_GAIN_MAX) {
+            LOG(ERROR) << __func__ << ": gain value out of range: " << gain;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    mHwGains = in_channelGains;
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamOut::StreamOut(StreamContext&& context, const std::optional<AudioOffloadInfo>& offloadInfo)
+    : mContextInstance(std::move(context)), mOffloadInfo(offloadInfo) {
     LOG(DEBUG) << __func__;
 }
 
+void StreamOut::defaultOnClose() {
+    mContextInstance.reset();
+}
+
 ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
         const AudioOffloadMetadata& in_offloadMetadata) {
     LOG(DEBUG) << __func__;
@@ -892,4 +956,31 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+StreamOutHwVolumeHelper::StreamOutHwVolumeHelper(const StreamContext* context)
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::getHwVolumeImpl(std::vector<float>* _aidl_return) {
+    *_aidl_return = mHwVolumes;
+    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::setHwVolumeImpl(
+        const std::vector<float>& in_channelVolumes) {
+    LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+    if (in_channelVolumes.size() != mChannelCount) {
+        LOG(ERROR) << __func__
+                   << ": channel count does not match stream channel count: " << mChannelCount;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    for (float volume : in_channelVolumes) {
+        if (volume < StreamOut::HW_VOLUME_MIN || volume > StreamOut::HW_VOLUME_MAX) {
+            LOG(ERROR) << __func__ << ": volume value out of range: " << volume;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    mHwVolumes = in_channelVolumes;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/StreamStub.cpp b/audio/aidl/default/StreamStub.cpp
deleted file mode 100644
index 2467320..0000000
--- a/audio/aidl/default/StreamStub.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2023 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 <cmath>
-
-#define LOG_TAG "AHAL_Stream"
-#include <android-base/logging.h>
-#include <audio_utils/clock.h>
-
-#include "core-impl/Module.h"
-#include "core-impl/StreamStub.h"
-
-using aidl::android::hardware::audio::common::SinkMetadata;
-using aidl::android::hardware::audio::common::SourceMetadata;
-using aidl::android::media::audio::common::AudioDevice;
-using aidl::android::media::audio::common::AudioOffloadInfo;
-using aidl::android::media::audio::common::MicrophoneInfo;
-
-namespace aidl::android::hardware::audio::core {
-
-DriverStub::DriverStub(const StreamContext& context, bool isInput)
-    : mFrameSizeBytes(context.getFrameSize()),
-      mSampleRate(context.getSampleRate()),
-      mIsAsynchronous(!!context.getAsyncCallback()),
-      mIsInput(isInput) {}
-
-::android::status_t DriverStub::init() {
-    usleep(500);
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::drain(StreamDescriptor::DrainMode) {
-    usleep(500);
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::flush() {
-    usleep(500);
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::pause() {
-    usleep(500);
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
-                                         int32_t* latencyMs) {
-    static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
-    static constexpr float kScaleFactor = .8f;
-    if (mIsAsynchronous) {
-        usleep(500);
-    } else {
-        const size_t delayUs = static_cast<size_t>(
-                std::roundf(kScaleFactor * frameCount * kMicrosPerSecond / mSampleRate));
-        usleep(delayUs);
-    }
-    if (mIsInput) {
-        uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
-        for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
-            byteBuffer[i] = std::rand() % 255;
-        }
-    }
-    *actualFrameCount = frameCount;
-    *latencyMs = Module::kLatencyMs;
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::standby() {
-    usleep(500);
-    return ::android::OK;
-}
-
-::android::status_t DriverStub::setConnectedDevices(
-        const std::vector<AudioDevice>& connectedDevices __unused) {
-    usleep(500);
-    return ::android::OK;
-}
-
-// static
-ndk::ScopedAStatus StreamInStub::createInstance(const SinkMetadata& sinkMetadata,
-                                                StreamContext&& context,
-                                                const std::vector<MicrophoneInfo>& microphones,
-                                                std::shared_ptr<StreamIn>* result) {
-    std::shared_ptr<StreamIn> stream =
-            ndk::SharedRefBase::make<StreamInStub>(sinkMetadata, std::move(context), microphones);
-    if (auto status = initInstance(stream); !status.isOk()) {
-        return status;
-    }
-    *result = std::move(stream);
-    return ndk::ScopedAStatus::ok();
-}
-
-StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context,
-                           const std::vector<MicrophoneInfo>& microphones)
-    : StreamIn(
-              sinkMetadata, std::move(context),
-              [](const StreamContext& ctx) -> DriverInterface* {
-                  return new DriverStub(ctx, true /*isInput*/);
-              },
-              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
-                  // The default worker implementation is used.
-                  return new StreamInWorker(ctx, driver);
-              },
-              microphones) {}
-
-// static
-ndk::ScopedAStatus StreamOutStub::createInstance(const SourceMetadata& sourceMetadata,
-                                                 StreamContext&& context,
-                                                 const std::optional<AudioOffloadInfo>& offloadInfo,
-                                                 std::shared_ptr<StreamOut>* result) {
-    std::shared_ptr<StreamOut> stream = ndk::SharedRefBase::make<StreamOutStub>(
-            sourceMetadata, std::move(context), offloadInfo);
-    if (auto status = initInstance(stream); !status.isOk()) {
-        return status;
-    }
-    *result = std::move(stream);
-    return ndk::ScopedAStatus::ok();
-}
-
-StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context,
-                             const std::optional<AudioOffloadInfo>& offloadInfo)
-    : StreamOut(
-              sourceMetadata, std::move(context),
-              [](const StreamContext& ctx) -> DriverInterface* {
-                  return new DriverStub(ctx, false /*isInput*/);
-              },
-              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
-                  // The default worker implementation is used.
-                  return new StreamOutWorker(ctx, driver);
-              },
-              offloadInfo) {}
-
-}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/StreamSwitcher.cpp
new file mode 100644
index 0000000..8ba15a8
--- /dev/null
+++ b/audio/aidl/default/StreamSwitcher.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2023 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 <limits>
+
+#define LOG_TAG "AHAL_StreamSwitcher"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+
+#include "core-impl/StreamStub.h"
+#include "core-impl/StreamSwitcher.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioDevice;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamSwitcher::StreamSwitcher(StreamContext* context, const Metadata& metadata)
+    : mContext(context),
+      mMetadata(metadata),
+      mStream(new InnerStreamWrapper<StreamStub>(context, mMetadata)) {}
+
+ndk::ScopedAStatus StreamSwitcher::closeCurrentStream(bool validateStreamState) {
+    if (!mStream) return ndk::ScopedAStatus::ok();
+    RETURN_STATUS_IF_ERROR(mStream->prepareToClose());
+    RETURN_STATUS_IF_ERROR(mStream->close());
+    if (validateStreamState && !isValidClosingStreamState(mStream->getStatePriorToClosing())) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    mStream.reset();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::close() {
+    if (mStream != nullptr) {
+        auto status = closeCurrentStream(false /*validateStreamState*/);
+        // The actual state is irrelevant since only StreamSwitcher cares about it.
+        onClose(StreamDescriptor::State::STANDBY);
+        return status;
+    }
+    LOG(ERROR) << __func__ << ": stream was already closed";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+}
+
+ndk::ScopedAStatus StreamSwitcher::prepareToClose() {
+    if (mStream != nullptr) {
+        return mStream->prepareToClose();
+    }
+    LOG(ERROR) << __func__ << ": stream was closed";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+}
+
+ndk::ScopedAStatus StreamSwitcher::updateHwAvSyncId(int32_t in_hwAvSyncId) {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    RETURN_STATUS_IF_ERROR(mStream->updateHwAvSyncId(in_hwAvSyncId));
+    mHwAvSyncId = in_hwAvSyncId;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::getVendorParameters(const std::vector<std::string>& in_ids,
+                                                       std::vector<VendorParameter>* _aidl_return) {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (mIsStubStream) {
+        LOG(ERROR) << __func__ << ": the stream is not connected";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    return mStream->getVendorParameters(in_ids, _aidl_return);
+}
+
+ndk::ScopedAStatus StreamSwitcher::setVendorParameters(
+        const std::vector<VendorParameter>& in_parameters, bool in_async) {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (mIsStubStream) {
+        mMissedParameters.emplace_back(in_parameters, in_async);
+        return ndk::ScopedAStatus::ok();
+    }
+    return mStream->setVendorParameters(in_parameters, in_async);
+}
+
+ndk::ScopedAStatus StreamSwitcher::addEffect(const std::shared_ptr<IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": null effect";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (!mIsStubStream) {
+        RETURN_STATUS_IF_ERROR(mStream->addEffect(in_effect));
+    }
+    mEffects.push_back(in_effect);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::removeEffect(const std::shared_ptr<IEffect>& in_effect) {
+    if (in_effect == nullptr) {
+        LOG(DEBUG) << __func__ << ": null effect";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    for (auto it = mEffects.begin(); it != mEffects.end(); ++it) {
+        if ((*it)->asBinder() == in_effect->asBinder()) {
+            mEffects.erase(it);
+            break;
+        }
+    }
+    return !mIsStubStream ? mStream->removeEffect(in_effect) : ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::getStreamCommonCommon(
+        std::shared_ptr<IStreamCommon>* _aidl_return) {
+    if (!mCommon) {
+        LOG(FATAL) << __func__ << ": the common interface was not created";
+    }
+    *_aidl_return = mCommon.getInstance();
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::updateMetadataCommon(const Metadata& metadata) {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    mMetadata = metadata;
+    return !mIsStubStream ? mStream->updateMetadataCommon(metadata) : ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::initInstance(
+        const std::shared_ptr<StreamCommonInterface>& delegate) {
+    mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
+    // The delegate is null because StreamSwitcher handles IStreamCommon methods by itself.
+    return mStream->initInstance(nullptr);
+}
+
+const StreamContext& StreamSwitcher::getContext() const {
+    return *mContext;
+}
+
+bool StreamSwitcher::isClosed() const {
+    return mStream == nullptr || mStream->isClosed();
+}
+
+const StreamCommonInterface::ConnectedDevices& StreamSwitcher::getConnectedDevices() const {
+    return mStream->getConnectedDevices();
+}
+
+ndk::ScopedAStatus StreamSwitcher::setConnectedDevices(const std::vector<AudioDevice>& devices) {
+    LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(devices);
+    if (mStream->getConnectedDevices() == devices) return ndk::ScopedAStatus::ok();
+    const DeviceSwitchBehavior behavior = switchCurrentStream(devices);
+    if (behavior == DeviceSwitchBehavior::UNSUPPORTED_DEVICES) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    } else if (behavior == DeviceSwitchBehavior::SWITCH_TO_STUB_STREAM && !devices.empty()) {
+        // This is an error in the extending class.
+        LOG(FATAL) << __func__
+                   << ": switching to stub stream with connected devices is not allowed";
+    }
+    if (behavior == USE_CURRENT_STREAM) {
+        mIsStubStream = false;
+    } else {
+        LOG(DEBUG) << __func__ << ": connected devices changed, switching stream";
+        // Two streams can't be opened for the same context, thus we always need to close
+        // the current one before creating a new one.
+        RETURN_STATUS_IF_ERROR(closeCurrentStream(true /*validateStreamState*/));
+        if (behavior == CREATE_NEW_STREAM) {
+            mStream = createNewStream(devices, mContext, mMetadata);
+            mIsStubStream = false;
+        } else {  // SWITCH_TO_STUB_STREAM
+            mStream.reset(new InnerStreamWrapper<StreamStub>(mContext, mMetadata));
+            mIsStubStream = true;
+        }
+        // The delegate is null because StreamSwitcher handles IStreamCommon methods by itself.
+        if (ndk::ScopedAStatus status = mStream->initInstance(nullptr); !status.isOk()) {
+            if (mIsStubStream) {
+                LOG(FATAL) << __func__
+                           << ": failed to initialize stub stream: " << status.getDescription();
+            }
+            // Need to close the current failed stream, and report an error.
+            // Since we can't operate without a stream implementation, put a stub in.
+            RETURN_STATUS_IF_ERROR(closeCurrentStream(false /*validateStreamState*/));
+            mStream.reset(new InnerStreamWrapper<StreamStub>(mContext, mMetadata));
+            (void)mStream->initInstance(nullptr);
+            (void)mStream->setConnectedDevices(devices);
+            return status;
+        }
+    }
+    RETURN_STATUS_IF_ERROR(mStream->setConnectedDevices(devices));
+    if (behavior == CREATE_NEW_STREAM) {
+        // These updates are less critical, only log warning on failure.
+        if (mHwAvSyncId.has_value()) {
+            if (auto status = mStream->updateHwAvSyncId(*mHwAvSyncId); !status.isOk()) {
+                LOG(WARNING) << __func__ << ": could not update HW AV Sync for a new stream: "
+                             << status.getDescription();
+            }
+        }
+        for (const auto& vndParam : mMissedParameters) {
+            if (auto status = mStream->setVendorParameters(vndParam.first, vndParam.second);
+                !status.isOk()) {
+                LOG(WARNING) << __func__ << ": error while setting parameters for a new stream: "
+                             << status.getDescription();
+            }
+        }
+        mMissedParameters.clear();
+        for (const auto& effect : mEffects) {
+            if (auto status = mStream->addEffect(effect); !status.isOk()) {
+                LOG(WARNING) << __func__ << ": error while adding effect for a new stream: "
+                             << status.getDescription();
+            }
+        }
+        if (mBluetoothParametersUpdated) {
+            if (auto status = mStream->bluetoothParametersUpdated(); !status.isOk()) {
+                LOG(WARNING) << __func__
+                             << ": error while updating BT parameters for a new stream: "
+                             << status.getDescription();
+            }
+        }
+        mBluetoothParametersUpdated = false;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamSwitcher::bluetoothParametersUpdated() {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (mIsStubStream) {
+        mBluetoothParametersUpdated = true;
+        return ndk::ScopedAStatus::ok();
+    }
+    return mStream->bluetoothParametersUpdated();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/Mixer.cpp b/audio/aidl/default/alsa/Mixer.cpp
new file mode 100644
index 0000000..126c033
--- /dev/null
+++ b/audio/aidl/default/alsa/Mixer.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2023 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 <algorithm>
+#include <cmath>
+
+#define LOG_TAG "AHAL_AlsaMixer"
+#include <android-base/logging.h>
+#include <android/binder_status.h>
+
+#include "Mixer.h"
+
+namespace aidl::android::hardware::audio::core::alsa {
+
+// static
+const std::map<Mixer::Control, std::vector<Mixer::ControlNamesAndExpectedCtlType>>
+        Mixer::kPossibleControls = {
+                {Mixer::MASTER_SWITCH, {{"Master Playback Switch", MIXER_CTL_TYPE_BOOL}}},
+                {Mixer::MASTER_VOLUME, {{"Master Playback Volume", MIXER_CTL_TYPE_INT}}},
+                {Mixer::HW_VOLUME,
+                 {{"Headphone Playback Volume", MIXER_CTL_TYPE_INT},
+                  {"Headset Playback Volume", MIXER_CTL_TYPE_INT},
+                  {"PCM Playback Volume", MIXER_CTL_TYPE_INT}}},
+                {Mixer::MIC_SWITCH, {{"Capture Switch", MIXER_CTL_TYPE_BOOL}}},
+                {Mixer::MIC_GAIN, {{"Capture Volume", MIXER_CTL_TYPE_INT}}}};
+
+// static
+Mixer::Controls Mixer::initializeMixerControls(struct mixer* mixer) {
+    if (mixer == nullptr) return {};
+    Controls mixerControls;
+    std::string mixerCtlNames;
+    for (const auto& [control, possibleCtls] : kPossibleControls) {
+        for (const auto& [ctlName, expectedCtlType] : possibleCtls) {
+            struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str());
+            if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) {
+                mixerControls.emplace(control, ctl);
+                if (!mixerCtlNames.empty()) {
+                    mixerCtlNames += ",";
+                }
+                mixerCtlNames += ctlName;
+                break;
+            }
+        }
+    }
+    LOG(DEBUG) << __func__ << ": available mixer control names=[" << mixerCtlNames << "]";
+    return mixerControls;
+}
+
+std::ostream& operator<<(std::ostream& s, Mixer::Control c) {
+    switch (c) {
+        case Mixer::Control::MASTER_SWITCH:
+            s << "master mute";
+            break;
+        case Mixer::Control::MASTER_VOLUME:
+            s << "master volume";
+            break;
+        case Mixer::Control::HW_VOLUME:
+            s << "volume";
+            break;
+        case Mixer::Control::MIC_SWITCH:
+            s << "mic mute";
+            break;
+        case Mixer::Control::MIC_GAIN:
+            s << "mic gain";
+            break;
+    }
+    return s;
+}
+
+Mixer::Mixer(int card) : mMixer(mixer_open(card)), mMixerControls(initializeMixerControls(mMixer)) {
+    if (!isValid()) {
+        PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
+    }
+}
+
+Mixer::~Mixer() {
+    if (isValid()) {
+        std::lock_guard l(mMixerAccess);
+        mixer_close(mMixer);
+    }
+}
+
+ndk::ScopedAStatus Mixer::setMasterMute(bool muted) {
+    return setMixerControlMute(MASTER_SWITCH, muted);
+}
+
+ndk::ScopedAStatus Mixer::setMasterVolume(float volume) {
+    return setMixerControlVolume(MASTER_VOLUME, volume);
+}
+
+ndk::ScopedAStatus Mixer::setMicGain(float gain) {
+    return setMixerControlVolume(MIC_GAIN, gain);
+}
+
+ndk::ScopedAStatus Mixer::setMicMute(bool muted) {
+    return setMixerControlMute(MIC_SWITCH, muted);
+}
+
+ndk::ScopedAStatus Mixer::setVolumes(const std::vector<float>& volumes) {
+    if (!isValid()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    auto it = mMixerControls.find(Mixer::HW_VOLUME);
+    if (it == mMixerControls.end()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    std::vector<int> percents;
+    std::transform(
+            volumes.begin(), volumes.end(), std::back_inserter(percents),
+            [](float volume) -> int { return std::floor(std::clamp(volume, 0.0f, 1.0f) * 100); });
+    std::lock_guard l(mMixerAccess);
+    if (int err = setMixerControlPercent(it->second, percents); err != 0) {
+        LOG(ERROR) << __func__ << ": failed to set volume, err=" << err;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Mixer::setMixerControlMute(Mixer::Control ctl, bool muted) {
+    if (!isValid()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    auto it = mMixerControls.find(ctl);
+    if (it == mMixerControls.end()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    std::lock_guard l(mMixerAccess);
+    if (int err = setMixerControlValue(it->second, muted ? 0 : 1); err != 0) {
+        LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << muted << ", err=" << err;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Mixer::setMixerControlVolume(Control ctl, float volume) {
+    if (!isValid()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    auto it = mMixerControls.find(ctl);
+    if (it == mMixerControls.end()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    volume = std::clamp(volume, 0.0f, 1.0f);
+    std::lock_guard l(mMixerAccess);
+    if (int err = setMixerControlPercent(it->second, std::floor(volume * 100)); err != 0) {
+        LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << volume << ", err=" << err;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, int percent) {
+    int ret = 0;
+    const unsigned int n = mixer_ctl_get_num_values(ctl);
+    for (unsigned int id = 0; id < n; id++) {
+        if (int error = mixer_ctl_set_percent(ctl, id, percent); error != 0) {
+            ret = error;
+        }
+    }
+    return ret;
+}
+
+int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) {
+    int ret = 0;
+    const unsigned int n = mixer_ctl_get_num_values(ctl);
+    for (unsigned int id = 0; id < n; id++) {
+        if (int error = mixer_ctl_set_percent(ctl, id, id < percents.size() ? percents[id] : 0);
+            error != 0) {
+            ret = error;
+        }
+    }
+    return ret;
+}
+
+int Mixer::setMixerControlValue(struct mixer_ctl* ctl, int value) {
+    int ret = 0;
+    const unsigned int n = mixer_ctl_get_num_values(ctl);
+    for (unsigned int id = 0; id < n; id++) {
+        if (int error = mixer_ctl_set_value(ctl, id, value); error != 0) {
+            ret = error;
+        }
+    }
+    return ret;
+}
+
+}  // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/Mixer.h b/audio/aidl/default/alsa/Mixer.h
new file mode 100644
index 0000000..8fba1e0
--- /dev/null
+++ b/audio/aidl/default/alsa/Mixer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+
+extern "C" {
+#include <tinyalsa/mixer.h>
+}
+
+namespace aidl::android::hardware::audio::core::alsa {
+
+class Mixer {
+  public:
+    explicit Mixer(int card);
+    ~Mixer();
+
+    bool isValid() const { return mMixer != nullptr; }
+
+    ndk::ScopedAStatus setMasterMute(bool muted);
+    ndk::ScopedAStatus setMasterVolume(float volume);
+    ndk::ScopedAStatus setMicGain(float gain);
+    ndk::ScopedAStatus setMicMute(bool muted);
+    ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes);
+
+  private:
+    enum Control {
+        MASTER_SWITCH,
+        MASTER_VOLUME,
+        HW_VOLUME,
+        MIC_SWITCH,
+        MIC_GAIN,
+    };
+    using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>;
+    using Controls = std::map<Control, struct mixer_ctl*>;
+
+    friend std::ostream& operator<<(std::ostream&, Control);
+    static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
+    static Controls initializeMixerControls(struct mixer* mixer);
+
+    ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted);
+    ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume);
+
+    int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess);
+    int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents)
+            REQUIRES(mMixerAccess);
+    int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess);
+
+    // Since ALSA functions do not use internal locking, enforce thread safety at our level.
+    std::mutex mMixerAccess;
+    // The mixer object is owned by ALSA and will be released when the mixer is closed.
+    struct mixer* const mMixer;
+    // `mMixerControls` will only be initialized in constructor. After that, it will only be
+    // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is
+    // the same as of the mixer itself.
+    const Controls mMixerControls;
+};
+
+}  // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/ModuleAlsa.cpp b/audio/aidl/default/alsa/ModuleAlsa.cpp
new file mode 100644
index 0000000..8e75d56
--- /dev/null
+++ b/audio/aidl/default/alsa/ModuleAlsa.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_ModuleAlsa"
+
+#include <vector>
+
+#include <android-base/logging.h>
+
+#include "Utils.h"
+#include "core-impl/ModuleAlsa.h"
+
+extern "C" {
+#include "alsa_device_profile.h"
+}
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioProfile;
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus ModuleAlsa::populateConnectedDevicePort(AudioPort* audioPort) {
+    auto deviceProfile = alsa::getDeviceProfile(*audioPort);
+    if (!deviceProfile.has_value()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto profile = alsa::readAlsaDeviceInfo(*deviceProfile);
+    if (!profile.has_value()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    std::vector<AudioChannelLayout> channels = alsa::getChannelMasksFromProfile(&profile.value());
+    std::vector<int> sampleRates = alsa::getSampleRatesFromProfile(&profile.value());
+
+    for (size_t i = 0; i < std::min(MAX_PROFILE_FORMATS, AUDIO_PORT_MAX_AUDIO_PROFILES) &&
+                       profile->formats[i] != PCM_FORMAT_INVALID;
+         ++i) {
+        auto audioFormatDescription =
+                alsa::c2aidl_pcm_format_AudioFormatDescription(profile->formats[i]);
+        if (audioFormatDescription.type == AudioFormatType::DEFAULT) {
+            LOG(WARNING) << __func__ << ": unknown pcm type=" << profile->formats[i];
+            continue;
+        }
+        AudioProfile audioProfile = {.format = audioFormatDescription,
+                                     .channelMasks = channels,
+                                     .sampleRates = sampleRates};
+        audioPort->profiles.push_back(std::move(audioProfile));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
new file mode 100644
index 0000000..0605d6f
--- /dev/null
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 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 <cmath>
+#include <limits>
+
+#define LOG_TAG "AHAL_StreamAlsa"
+#include <android-base/logging.h>
+
+#include <Utils.h>
+#include <audio_utils/clock.h>
+#include <error/expected_utils.h>
+
+#include "core-impl/StreamAlsa.h"
+
+namespace aidl::android::hardware::audio::core {
+
+StreamAlsa::StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries)
+    : StreamCommonImpl(context, metadata),
+      mBufferSizeFrames(getContext().getBufferSizeInFrames()),
+      mFrameSizeBytes(getContext().getFrameSize()),
+      mSampleRate(getContext().getSampleRate()),
+      mIsInput(isInput(metadata)),
+      mConfig(alsa::getPcmConfig(getContext(), mIsInput)),
+      mReadWriteRetries(readWriteRetries) {}
+
+::android::status_t StreamAlsa::init() {
+    return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
+}
+
+::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) {
+    if (!mIsInput) {
+        static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+        const size_t delayUs = static_cast<size_t>(
+                std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+        usleep(delayUs);
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::flush() {
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::pause() {
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::standby() {
+    mAlsaDeviceProxies.clear();
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::start() {
+    if (!mAlsaDeviceProxies.empty()) {
+        // This is a resume after a pause.
+        return ::android::OK;
+    }
+    decltype(mAlsaDeviceProxies) alsaDeviceProxies;
+    for (const auto& device : getDeviceProfiles()) {
+        alsa::DeviceProxy proxy;
+        if (device.isExternal) {
+            // Always ask alsa configure as required since the configuration should be supported
+            // by the connected device. That is guaranteed by `setAudioPortConfig` and
+            // `setAudioPatch`.
+            proxy = alsa::openProxyForExternalDevice(
+                    device, const_cast<struct pcm_config*>(&mConfig.value()),
+                    true /*require_exact_match*/);
+        } else {
+            proxy = alsa::openProxyForAttachedDevice(
+                    device, const_cast<struct pcm_config*>(&mConfig.value()), mBufferSizeFrames);
+        }
+        if (!proxy) {
+            return ::android::NO_INIT;
+        }
+        alsaDeviceProxies.push_back(std::move(proxy));
+    }
+    mAlsaDeviceProxies = std::move(alsaDeviceProxies);
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                         int32_t* latencyMs) {
+    if (mAlsaDeviceProxies.empty()) {
+        LOG(FATAL) << __func__ << ": no opened devices";
+        return ::android::NO_INIT;
+    }
+    const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
+    unsigned maxLatency = 0;
+    if (mIsInput) {
+        // For input case, only support single device.
+        proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer,
+                                mReadWriteRetries);
+        maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
+    } else {
+        for (auto& proxy : mAlsaDeviceProxies) {
+            proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
+            maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
+        }
+    }
+    *actualFrameCount = frameCount;
+    maxLatency = std::min(maxLatency, static_cast<unsigned>(std::numeric_limits<int32_t>::max()));
+    *latencyMs = maxLatency;
+    return ::android::OK;
+}
+
+::android::status_t StreamAlsa::refinePosition(StreamDescriptor::Position* position) {
+    if (mAlsaDeviceProxies.empty()) {
+        LOG(FATAL) << __func__ << ": no opened devices";
+        return ::android::NO_INIT;
+    }
+    // Since the proxy can only count transferred frames since its creation,
+    // we override its counter value with ours and let it to correct for buffered frames.
+    alsa::resetTransferredFrames(mAlsaDeviceProxies[0], position->frames);
+    if (mIsInput) {
+        if (int ret = proxy_get_capture_position(mAlsaDeviceProxies[0].get(), &position->frames,
+                                                 &position->timeNs);
+            ret != 0) {
+            LOG(WARNING) << __func__ << ": failed to retrieve capture position: " << ret;
+            return ::android::INVALID_OPERATION;
+        }
+    } else {
+        uint64_t hwFrames;
+        struct timespec timestamp;
+        if (int ret = proxy_get_presentation_position(mAlsaDeviceProxies[0].get(), &hwFrames,
+                                                      &timestamp);
+            ret == 0) {
+            if (hwFrames > std::numeric_limits<int64_t>::max()) {
+                hwFrames -= std::numeric_limits<int64_t>::max();
+            }
+            position->frames = static_cast<int64_t>(hwFrames);
+            position->timeNs = audio_utils_ns_from_timespec(&timestamp);
+        } else {
+            LOG(WARNING) << __func__ << ": failed to retrieve presentation position: " << ret;
+            return ::android::INVALID_OPERATION;
+        }
+    }
+    return ::android::OK;
+}
+
+void StreamAlsa::shutdown() {
+    mAlsaDeviceProxies.clear();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
new file mode 100644
index 0000000..9dcd024
--- /dev/null
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2023 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 <map>
+#include <set>
+
+#define LOG_TAG "AHAL_AlsaUtils"
+#include <Utils.h>
+#include <aidl/android/media/audio/common/AudioFormatType.h>
+#include <aidl/android/media/audio/common/PcmType.h>
+#include <android-base/logging.h>
+
+#include "Utils.h"
+#include "core-impl/utils.h"
+
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::PcmType;
+
+namespace aidl::android::hardware::audio::core::alsa {
+
+namespace {
+
+using AudioChannelCountToMaskMap = std::map<unsigned int, AudioChannelLayout>;
+using AudioFormatDescToPcmFormatMap = std::map<AudioFormatDescription, enum pcm_format>;
+using PcmFormatToAudioFormatDescMap = std::map<enum pcm_format, AudioFormatDescription>;
+
+AudioChannelLayout getInvalidChannelLayout() {
+    static const AudioChannelLayout invalidChannelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::Tag::invalid>(0);
+    return invalidChannelLayout;
+}
+
+static AudioChannelCountToMaskMap make_ChannelCountToMaskMap(
+        const std::set<AudioChannelLayout>& channelMasks) {
+    AudioChannelCountToMaskMap channelMaskToCountMap;
+    for (const auto& channelMask : channelMasks) {
+        channelMaskToCountMap.emplace(getChannelCount(channelMask), channelMask);
+    }
+    return channelMaskToCountMap;
+}
+
+#define DEFINE_CHANNEL_LAYOUT_MASK(n) \
+    AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(AudioChannelLayout::LAYOUT_##n)
+
+const AudioChannelCountToMaskMap& getSupportedChannelOutLayoutMap() {
+    static const std::set<AudioChannelLayout> supportedOutChannelLayouts = {
+            DEFINE_CHANNEL_LAYOUT_MASK(MONO),          DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
+            DEFINE_CHANNEL_LAYOUT_MASK(2POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(QUAD),
+            DEFINE_CHANNEL_LAYOUT_MASK(PENTA),         DEFINE_CHANNEL_LAYOUT_MASK(5POINT1),
+            DEFINE_CHANNEL_LAYOUT_MASK(6POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(7POINT1),
+            DEFINE_CHANNEL_LAYOUT_MASK(7POINT1POINT4), DEFINE_CHANNEL_LAYOUT_MASK(22POINT2),
+    };
+    static const AudioChannelCountToMaskMap outLayouts =
+            make_ChannelCountToMaskMap(supportedOutChannelLayouts);
+    return outLayouts;
+}
+
+const AudioChannelCountToMaskMap& getSupportedChannelInLayoutMap() {
+    static const std::set<AudioChannelLayout> supportedInChannelLayouts = {
+            DEFINE_CHANNEL_LAYOUT_MASK(MONO),
+            DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
+    };
+    static const AudioChannelCountToMaskMap inLayouts =
+            make_ChannelCountToMaskMap(supportedInChannelLayouts);
+    return inLayouts;
+}
+
+#undef DEFINE_CHANNEL_LAYOUT_MASK
+#define DEFINE_CHANNEL_INDEX_MASK(n) \
+    AudioChannelLayout::make<AudioChannelLayout::Tag::indexMask>(AudioChannelLayout::INDEX_MASK_##n)
+
+const AudioChannelCountToMaskMap& getSupportedChannelIndexLayoutMap() {
+    static const std::set<AudioChannelLayout> supportedIndexChannelLayouts = {
+            DEFINE_CHANNEL_INDEX_MASK(1),  DEFINE_CHANNEL_INDEX_MASK(2),
+            DEFINE_CHANNEL_INDEX_MASK(3),  DEFINE_CHANNEL_INDEX_MASK(4),
+            DEFINE_CHANNEL_INDEX_MASK(5),  DEFINE_CHANNEL_INDEX_MASK(6),
+            DEFINE_CHANNEL_INDEX_MASK(7),  DEFINE_CHANNEL_INDEX_MASK(8),
+            DEFINE_CHANNEL_INDEX_MASK(9),  DEFINE_CHANNEL_INDEX_MASK(10),
+            DEFINE_CHANNEL_INDEX_MASK(11), DEFINE_CHANNEL_INDEX_MASK(12),
+            DEFINE_CHANNEL_INDEX_MASK(13), DEFINE_CHANNEL_INDEX_MASK(14),
+            DEFINE_CHANNEL_INDEX_MASK(15), DEFINE_CHANNEL_INDEX_MASK(16),
+            DEFINE_CHANNEL_INDEX_MASK(17), DEFINE_CHANNEL_INDEX_MASK(18),
+            DEFINE_CHANNEL_INDEX_MASK(19), DEFINE_CHANNEL_INDEX_MASK(20),
+            DEFINE_CHANNEL_INDEX_MASK(21), DEFINE_CHANNEL_INDEX_MASK(22),
+            DEFINE_CHANNEL_INDEX_MASK(23), DEFINE_CHANNEL_INDEX_MASK(24),
+    };
+    static const AudioChannelCountToMaskMap indexLayouts =
+            make_ChannelCountToMaskMap(supportedIndexChannelLayouts);
+    return indexLayouts;
+}
+
+#undef DEFINE_CHANNEL_INDEX_MASK
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+const AudioFormatDescToPcmFormatMap& getAudioFormatDescriptorToPcmFormatMap() {
+    static const AudioFormatDescToPcmFormatMap formatDescToPcmFormatMap = {
+            {make_AudioFormatDescription(PcmType::UINT_8_BIT), PCM_FORMAT_S8},
+            {make_AudioFormatDescription(PcmType::INT_16_BIT), PCM_FORMAT_S16_LE},
+            {make_AudioFormatDescription(PcmType::FIXED_Q_8_24), PCM_FORMAT_S24_LE},
+            {make_AudioFormatDescription(PcmType::INT_24_BIT), PCM_FORMAT_S24_3LE},
+            {make_AudioFormatDescription(PcmType::INT_32_BIT), PCM_FORMAT_S32_LE},
+            {make_AudioFormatDescription(PcmType::FLOAT_32_BIT), PCM_FORMAT_FLOAT_LE},
+    };
+    return formatDescToPcmFormatMap;
+}
+
+static PcmFormatToAudioFormatDescMap make_PcmFormatToAudioFormatDescMap(
+        const AudioFormatDescToPcmFormatMap& formatDescToPcmFormatMap) {
+    PcmFormatToAudioFormatDescMap result;
+    for (const auto& formatPair : formatDescToPcmFormatMap) {
+        result.emplace(formatPair.second, formatPair.first);
+    }
+    return result;
+}
+
+const PcmFormatToAudioFormatDescMap& getPcmFormatToAudioFormatDescMap() {
+    static const PcmFormatToAudioFormatDescMap pcmFormatToFormatDescMap =
+            make_PcmFormatToAudioFormatDescMap(getAudioFormatDescriptorToPcmFormatMap());
+    return pcmFormatToFormatDescMap;
+}
+
+}  // namespace
+
+std::ostream& operator<<(std::ostream& os, const DeviceProfile& device) {
+    return os << "<" << device.card << "," << device.device << ">";
+}
+
+AudioChannelLayout getChannelLayoutMaskFromChannelCount(unsigned int channelCount, int isInput) {
+    return findValueOrDefault(
+            isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
+            channelCount, getInvalidChannelLayout());
+}
+
+AudioChannelLayout getChannelIndexMaskFromChannelCount(unsigned int channelCount) {
+    return findValueOrDefault(getSupportedChannelIndexLayoutMap(), channelCount,
+                              getInvalidChannelLayout());
+}
+
+unsigned int getChannelCountFromChannelMask(const AudioChannelLayout& channelMask, bool isInput) {
+    switch (channelMask.getTag()) {
+        case AudioChannelLayout::Tag::layoutMask: {
+            return findKeyOrDefault(
+                    isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
+                    static_cast<unsigned>(getChannelCount(channelMask)), 0u /*defaultValue*/);
+        }
+        case AudioChannelLayout::Tag::indexMask: {
+            return findKeyOrDefault(getSupportedChannelIndexLayoutMap(),
+                                    static_cast<unsigned>(getChannelCount(channelMask)),
+                                    0u /*defaultValue*/);
+        }
+        case AudioChannelLayout::Tag::none:
+        case AudioChannelLayout::Tag::invalid:
+        case AudioChannelLayout::Tag::voiceMask:
+        default:
+            return 0;
+    }
+}
+
+std::vector<AudioChannelLayout> getChannelMasksFromProfile(const alsa_device_profile* profile) {
+    const bool isInput = profile->direction == PCM_IN;
+    std::vector<AudioChannelLayout> channels;
+    for (size_t i = 0; i < AUDIO_PORT_MAX_CHANNEL_MASKS && profile->channel_counts[i] != 0; ++i) {
+        auto layoutMask =
+                alsa::getChannelLayoutMaskFromChannelCount(profile->channel_counts[i], isInput);
+        if (layoutMask.getTag() == AudioChannelLayout::Tag::layoutMask) {
+            channels.push_back(layoutMask);
+        }
+        auto indexMask = alsa::getChannelIndexMaskFromChannelCount(profile->channel_counts[i]);
+        if (indexMask.getTag() == AudioChannelLayout::Tag::indexMask) {
+            channels.push_back(indexMask);
+        }
+    }
+    return channels;
+}
+
+std::optional<DeviceProfile> getDeviceProfile(
+        const ::aidl::android::media::audio::common::AudioDevice& audioDevice, bool isInput) {
+    if (audioDevice.address.getTag() != AudioDeviceAddress::Tag::alsa) {
+        LOG(ERROR) << __func__ << ": not alsa address: " << audioDevice.toString();
+        return std::nullopt;
+    }
+    auto& alsaAddress = audioDevice.address.get<AudioDeviceAddress::Tag::alsa>();
+    if (alsaAddress.size() != 2 || alsaAddress[0] < 0 || alsaAddress[1] < 0) {
+        LOG(ERROR) << __func__
+                   << ": malformed alsa address: " << ::android::internal::ToString(alsaAddress);
+        return std::nullopt;
+    }
+    return DeviceProfile{.card = alsaAddress[0],
+                         .device = alsaAddress[1],
+                         .direction = isInput ? PCM_IN : PCM_OUT,
+                         .isExternal = !audioDevice.type.connection.empty()};
+}
+
+std::optional<DeviceProfile> getDeviceProfile(
+        const ::aidl::android::media::audio::common::AudioPort& audioPort) {
+    if (audioPort.ext.getTag() != AudioPortExt::Tag::device) {
+        LOG(ERROR) << __func__ << ": port id " << audioPort.id << " is not a device port";
+        return std::nullopt;
+    }
+    auto& devicePort = audioPort.ext.get<AudioPortExt::Tag::device>();
+    return getDeviceProfile(devicePort.device, audioPort.flags.getTag() == AudioIoFlags::input);
+}
+
+std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput) {
+    struct pcm_config config;
+    config.channels = alsa::getChannelCountFromChannelMask(context.getChannelLayout(), isInput);
+    if (config.channels == 0) {
+        LOG(ERROR) << __func__ << ": invalid channel=" << context.getChannelLayout().toString();
+        return std::nullopt;
+    }
+    config.format = alsa::aidl2c_AudioFormatDescription_pcm_format(context.getFormat());
+    if (config.format == PCM_FORMAT_INVALID) {
+        LOG(ERROR) << __func__ << ": invalid format=" << context.getFormat().toString();
+        return std::nullopt;
+    }
+    config.rate = context.getSampleRate();
+    if (config.rate == 0) {
+        LOG(ERROR) << __func__ << ": invalid sample rate=" << config.rate;
+        return std::nullopt;
+    }
+    return config;
+}
+
+std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile) {
+    std::vector<int> sampleRates;
+    for (int i = 0; i < std::min(MAX_PROFILE_SAMPLE_RATES, AUDIO_PORT_MAX_SAMPLING_RATES) &&
+                    profile->sample_rates[i] != 0;
+         i++) {
+        sampleRates.push_back(profile->sample_rates[i]);
+    }
+    return sampleRates;
+}
+
+DeviceProxy makeDeviceProxy() {
+    DeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
+        if (proxy != nullptr) {
+            proxy_close(proxy);
+            delete proxy;
+        }
+    });
+    memset(proxy.get(), 0, sizeof(alsa_device_proxy));
+    return proxy;
+}
+
+DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
+                                       struct pcm_config* pcmConfig, size_t bufferFrameCount) {
+    if (deviceProfile.isExternal) {
+        LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile;
+    }
+    alsa_device_profile profile;
+    profile_init(&profile, deviceProfile.direction);
+    profile.card = deviceProfile.card;
+    profile.device = deviceProfile.device;
+    if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) {
+        LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile;
+    }
+    auto proxy = makeDeviceProxy();
+    if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) {
+        LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile
+                   << " error=" << err;
+        return nullptr;
+    }
+    if (int err = proxy_open(proxy.get()); err != 0) {
+        LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
+                   << " error=" << err;
+        return nullptr;
+    }
+    return proxy;
+}
+
+DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
+                                       struct pcm_config* pcmConfig, bool requireExactMatch) {
+    if (!deviceProfile.isExternal) {
+        LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile;
+    }
+    auto profile = readAlsaDeviceInfo(deviceProfile);
+    if (!profile.has_value()) {
+        LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
+        return nullptr;
+    }
+    auto proxy = makeDeviceProxy();
+    if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch);
+        err != 0) {
+        LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile
+                   << " error=" << err;
+        return nullptr;
+    }
+    if (int err = proxy_open(proxy.get()); err != 0) {
+        LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
+                   << " error=" << err;
+        return nullptr;
+    }
+    return proxy;
+}
+
+std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
+    alsa_device_profile profile;
+    profile_init(&profile, deviceProfile.direction);
+    profile.card = deviceProfile.card;
+    profile.device = deviceProfile.device;
+    if (!profile_read_device_info(&profile)) {
+        LOG(ERROR) << __func__ << ": failed to read device info, card=" << profile.card
+                   << ", device=" << profile.device;
+        return std::nullopt;
+    }
+    return profile;
+}
+
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames) {
+    if (proxy != nullptr) {
+        proxy->transferred = frames;
+    }
+}
+
+AudioFormatDescription c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy) {
+    return findValueOrDefault(getPcmFormatToAudioFormatDescMap(), legacy, AudioFormatDescription());
+}
+
+pcm_format aidl2c_AudioFormatDescription_pcm_format(const AudioFormatDescription& aidl) {
+    return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
+}
+
+}  // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
new file mode 100644
index 0000000..37414b3
--- /dev/null
+++ b/audio/aidl/default/alsa/Utils.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <optional>
+#include <vector>
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+
+#include "core-impl/Stream.h"
+
+extern "C" {
+#include <tinyalsa/pcm.h>
+#include "alsa_device_profile.h"
+#include "alsa_device_proxy.h"
+}
+
+namespace aidl::android::hardware::audio::core::alsa {
+
+struct DeviceProfile {
+    int card;
+    int device;
+    int direction; /* PCM_OUT or PCM_IN */
+    bool isExternal;
+};
+std::ostream& operator<<(std::ostream& os, const DeviceProfile& device);
+using DeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
+using DeviceProxy = std::unique_ptr<alsa_device_proxy, DeviceProxyDeleter>;
+
+::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
+        unsigned int channelCount, int isInput);
+::aidl::android::media::audio::common::AudioChannelLayout getChannelIndexMaskFromChannelCount(
+        unsigned int channelCount);
+unsigned int getChannelCountFromChannelMask(
+        const ::aidl::android::media::audio::common::AudioChannelLayout& channelMask, bool isInput);
+std::vector<::aidl::android::media::audio::common::AudioChannelLayout> getChannelMasksFromProfile(
+        const alsa_device_profile* profile);
+std::optional<DeviceProfile> getDeviceProfile(
+        const ::aidl::android::media::audio::common::AudioDevice& audioDevice, bool isInput);
+std::optional<DeviceProfile> getDeviceProfile(
+        const ::aidl::android::media::audio::common::AudioPort& audioPort);
+std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput);
+std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile);
+DeviceProxy makeDeviceProxy();
+DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
+                                       struct pcm_config* pcmConfig, size_t bufferFrameCount);
+DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
+                                       struct pcm_config* pcmConfig, bool requireExactMatch);
+std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames);
+
+::aidl::android::media::audio::common::AudioFormatDescription
+c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy);
+pcm_format aidl2c_AudioFormatDescription_pcm_format(
+        const ::aidl::android::media::audio::common::AudioFormatDescription& aidl);
+
+}  // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
index 2068735..757976f 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
@@ -3,7 +3,7 @@
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
     group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
-    capabilities BLOCK_SUSPEND
+    capabilities BLOCK_SUSPEND SYS_NICE
     # setting RLIMIT_RTPRIO allows binder RT priority inheritance
     rlimit rtprio 10 10
     ioprio rt 4
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index 9636a58..9db6061 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -12,11 +12,21 @@
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
     <version>1</version>
+    <fqname>IModule/stub</fqname>
+  </hal>
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
     <fqname>IModule/usb</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
     <version>1</version>
+    <fqname>IModule/bluetooth</fqname>
+  </hal>
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
     <fqname>IConfig/default</fqname>
   </hal>
 </manifest>
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 6627ae7..00de797 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -50,7 +50,8 @@
     </libraries>
 
     <!-- list of effects to load.
-         Each "effect" element must contain a "name", "library" and a "uuid" attribute.
+         Each "effect" element must contain a "name", "library" and a "uuid" attribute, an optional
+         "type" attribute can be used to add any customized effect type.
          The value of the "library" attribute must correspond to the name of one library element in
          the "libraries" element.
          The "name" attribute used to specific effect type, and should be mapping to a key of
@@ -62,8 +63,8 @@
          result of IFactory.queryEffects() to decide which effect implementation should be part of
          proxy and which not.
 
-         Only "name", "library", and "uuid" attributes in "effects" element are meaningful and
-         parsed out by EffectConfig class, all other attributes are ignored.
+         Only "name", "library", "uuid", and "type" attributes in "effects" element are meaningful
+          and parsed out by EffectConfig class, all other attributes are ignored.
          Only "name" and "uuid" attributes in "effectProxy" element are meaningful and parsed out
          by EffectConfig class, all other attributes are ignored.
     -->
@@ -94,7 +95,7 @@
             <libsw library="equalizersw" uuid="0bed4300-847d-11df-bb17-0002a5d5c51b"/>
             <libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
         </effectProxy>
-        <effect name="extensioneffect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002"/>
+        <effect name="extension_effect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002" type="fa81de0e-588b-11ed-9b6a-0242ac120002"/>
         <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
         <effect name="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
     </effects>
diff --git a/audio/aidl/default/bluetooth/DevicePortProxy.cpp b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
new file mode 100644
index 0000000..12e204a
--- /dev/null
+++ b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2023 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_TAG "AHAL_BluetoothPortProxy"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <audio_utils/primitives.h>
+#include <inttypes.h>
+#include <log/log.h>
+
+#include "core-impl/DevicePortProxy.h"
+
+namespace android::bluetooth::audio::aidl {
+
+namespace {
+
+// The maximum time to wait in std::condition_variable::wait_for()
+constexpr unsigned int kMaxWaitingTimeMs = 4500;
+
+}  // namespace
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
+using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
+using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
+using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using ::aidl::android::hardware::bluetooth::audio::SessionType;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+using ::android::base::StringPrintf;
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) {
+    switch (state) {
+        case BluetoothStreamState::DISABLED:
+            return os << "DISABLED";
+        case BluetoothStreamState::STANDBY:
+            return os << "STANDBY";
+        case BluetoothStreamState::STARTING:
+            return os << "STARTING";
+        case BluetoothStreamState::STARTED:
+            return os << "STARTED";
+        case BluetoothStreamState::SUSPENDING:
+            return os << "SUSPENDING";
+        case BluetoothStreamState::UNKNOWN:
+            return os << "UNKNOWN";
+        default:
+            return os << android::base::StringPrintf("%#hhx", state);
+    }
+}
+
+BluetoothAudioPortAidl::BluetoothAudioPortAidl()
+    : mCookie(::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined),
+      mState(BluetoothStreamState::DISABLED),
+      mSessionType(SessionType::UNKNOWN) {}
+
+BluetoothAudioPortAidl::~BluetoothAudioPortAidl() {
+    unregisterPort();
+}
+
+bool BluetoothAudioPortAidl::registerPort(const AudioDeviceDescription& description) {
+    if (inUse()) {
+        LOG(ERROR) << __func__ << debugMessage() << " already in use";
+        return false;
+    }
+
+    if (!initSessionType(description)) return false;
+
+    auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
+                                           const BluetoothAudioStatus& status) {
+        (void)start_resp;
+        port->controlResultHandler(cookie, status);
+    };
+    auto session_changed_cb = [port = this](uint16_t cookie) {
+        port->sessionChangedHandler(cookie);
+    };
+    // TODO: Add audio_config_changed_cb
+    PortStatusCallbacks cbacks = {
+            .control_result_cb_ = control_result_cb,
+            .session_changed_cb_ = session_changed_cb,
+    };
+    mCookie = BluetoothAudioSessionControl::RegisterControlResultCback(mSessionType, cbacks);
+    auto isOk = (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
+    if (isOk) {
+        std::lock_guard guard(mCvMutex);
+        mState = BluetoothStreamState::STANDBY;
+    }
+    LOG(DEBUG) << __func__ << debugMessage();
+    return isOk;
+}
+
+bool BluetoothAudioPortAidl::initSessionType(const AudioDeviceDescription& description) {
+    if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP &&
+        (description.type == AudioDeviceType::OUT_DEVICE ||
+         description.type == AudioDeviceType::OUT_HEADPHONE ||
+         description.type == AudioDeviceType::OUT_SPEAKER)) {
+        LOG(VERBOSE) << __func__
+                     << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
+               description.type == AudioDeviceType::OUT_HEARING_AID) {
+        LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+               description.type == AudioDeviceType::OUT_HEADSET) {
+        LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+               description.type == AudioDeviceType::OUT_SPEAKER) {
+        LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+               description.type == AudioDeviceType::IN_HEADSET) {
+        LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+               description.type == AudioDeviceType::OUT_BROADCAST) {
+        LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
+                     << description.toString() << ")";
+        mSessionType = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
+    } else {
+        LOG(ERROR) << __func__ << ": unknown device=" << description.toString();
+        return false;
+    }
+
+    if (!BluetoothAudioSessionControl::IsSessionReady(mSessionType)) {
+        LOG(ERROR) << __func__ << ": device=" << description.toString()
+                   << ", session_type=" << toString(mSessionType) << " is not ready";
+        return false;
+    }
+    return true;
+}
+
+void BluetoothAudioPortAidl::unregisterPort() {
+    if (!inUse()) {
+        LOG(WARNING) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return;
+    }
+    BluetoothAudioSessionControl::UnregisterControlResultCback(mSessionType, mCookie);
+    mCookie = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
+    LOG(VERBOSE) << __func__ << debugMessage() << " port unregistered";
+}
+
+void BluetoothAudioPortAidl::controlResultHandler(uint16_t cookie,
+                                                  const BluetoothAudioStatus& status) {
+    std::lock_guard guard(mCvMutex);
+    if (!inUse()) {
+        LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
+        return;
+    }
+    if (mCookie != cookie) {
+        LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
+                   << StringPrintf("%#hx", cookie) << ") is corrupted";
+        return;
+    }
+    BluetoothStreamState previous_state = mState;
+    LOG(INFO) << "control_result_cb:" << debugMessage() << ", previous_state=" << previous_state
+              << ", status=" << toString(status);
+
+    switch (previous_state) {
+        case BluetoothStreamState::STARTED:
+            /* Only Suspend signal can be send in STARTED state*/
+            if (status == BluetoothAudioStatus::RECONFIGURATION ||
+                status == BluetoothAudioStatus::SUCCESS) {
+                mState = BluetoothStreamState::STANDBY;
+            } else {
+                LOG(WARNING) << StringPrintf(
+                        "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+                        "previous_state=%#hhx",
+                        toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+                        previous_state);
+            }
+            break;
+        case BluetoothStreamState::STARTING:
+            if (status == BluetoothAudioStatus::SUCCESS) {
+                mState = BluetoothStreamState::STARTED;
+            } else {
+                // Set to standby since the stack may be busy switching between outputs
+                LOG(WARNING) << StringPrintf(
+                        "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+                        "previous_state=%#hhx",
+                        toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+                        previous_state);
+                mState = BluetoothStreamState::STANDBY;
+            }
+            break;
+        case BluetoothStreamState::SUSPENDING:
+            if (status == BluetoothAudioStatus::SUCCESS) {
+                mState = BluetoothStreamState::STANDBY;
+            } else {
+                // It will be failed if the headset is disconnecting, and set to disable
+                // to wait for re-init again
+                LOG(WARNING) << StringPrintf(
+                        "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+                        "previous_state=%#hhx",
+                        toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+                        previous_state);
+                mState = BluetoothStreamState::DISABLED;
+            }
+            break;
+        default:
+            LOG(ERROR) << "control_result_cb: unexpected previous_state="
+                       << StringPrintf(
+                                  "control_result_cb: status=%s failure for session_type= %s, "
+                                  "cookie=%#hx, previous_state=%#hhx",
+                                  toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+                                  previous_state);
+            return;
+    }
+    mInternalCv.notify_all();
+}
+
+void BluetoothAudioPortAidl::sessionChangedHandler(uint16_t cookie) {
+    std::lock_guard guard(mCvMutex);
+    if (!inUse()) {
+        LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
+        return;
+    }
+    if (mCookie != cookie) {
+        LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
+                   << StringPrintf("%#hx", cookie) << ") is corrupted";
+        return;
+    }
+    BluetoothStreamState previous_state = mState;
+    LOG(VERBOSE) << "session_changed_cb:" << debugMessage()
+                 << ", previous_state=" << previous_state;
+    mState = BluetoothStreamState::DISABLED;
+    mInternalCv.notify_all();
+}
+
+bool BluetoothAudioPortAidl::inUse() const {
+    return (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortAidl::getPreferredDataIntervalUs(size_t* interval_us) const {
+    if (!interval_us) {
+        LOG(ERROR) << __func__ << ": bad input arg";
+        return false;
+    }
+
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+
+    const AudioConfiguration& hal_audio_cfg =
+            BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
+    if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
+        LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
+        return false;
+    }
+
+    *interval_us = hal_audio_cfg.get<AudioConfiguration::pcmConfig>().dataIntervalUs;
+    return true;
+}
+
+bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration* audio_cfg) const {
+    if (!audio_cfg) {
+        LOG(ERROR) << __func__ << ": bad input arg";
+        return false;
+    }
+
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+
+    const AudioConfiguration& hal_audio_cfg =
+            BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
+    if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
+        LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
+        return false;
+    }
+    *audio_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state*=" << getState() << ", PcmConfig=["
+                 << audio_cfg->toString() << "]";
+    if (audio_cfg->channelMode == ChannelMode::UNKNOWN) {
+        return false;
+    }
+    return true;
+}
+
+bool BluetoothAudioPortAidl::standby() {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    std::lock_guard guard(mCvMutex);
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+    if (mState == BluetoothStreamState::DISABLED) {
+        mState = BluetoothStreamState::STANDBY;
+        LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
+        return true;
+    }
+    return false;
+}
+
+bool BluetoothAudioPortAidl::condWaitState(BluetoothStreamState state) {
+    const auto waitTime = std::chrono::milliseconds(kMaxWaitingTimeMs);
+    std::unique_lock lock(mCvMutex);
+    base::ScopedLockAssertion lock_assertion(mCvMutex);
+    switch (state) {
+        case BluetoothStreamState::STARTING: {
+            LOG(VERBOSE) << __func__ << debugMessage() << " waiting for STARTED";
+            mInternalCv.wait_for(lock, waitTime, [this] {
+                base::ScopedLockAssertion lock_assertion(mCvMutex);
+                return mState != BluetoothStreamState::STARTING;
+            });
+            return mState == BluetoothStreamState::STARTED;
+        }
+        case BluetoothStreamState::SUSPENDING: {
+            LOG(VERBOSE) << __func__ << debugMessage() << " waiting for SUSPENDED";
+            mInternalCv.wait_for(lock, waitTime, [this] {
+                base::ScopedLockAssertion lock_assertion(mCvMutex);
+                return mState != BluetoothStreamState::SUSPENDING;
+            });
+            return mState == BluetoothStreamState::STANDBY;
+        }
+        default:
+            LOG(WARNING) << __func__ << debugMessage() << " waiting for KNOWN";
+            return false;
+    }
+    return false;
+}
+
+bool BluetoothAudioPortAidl::start() {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
+                 << ", mono=" << (mIsStereoToMono ? "true" : "false") << " request";
+
+    {
+        std::unique_lock lock(mCvMutex);
+        base::ScopedLockAssertion lock_assertion(mCvMutex);
+        if (mState == BluetoothStreamState::STARTED) {
+            return true;  // nop, return
+        } else if (mState == BluetoothStreamState::SUSPENDING ||
+                   mState == BluetoothStreamState::STARTING) {
+            /* If port is in transient state, give some time to respond */
+            auto state_ = mState;
+            lock.unlock();
+            if (!condWaitState(state_)) {
+                LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+                return false;
+            }
+        }
+    }
+
+    bool retval = false;
+    {
+        std::unique_lock lock(mCvMutex);
+        base::ScopedLockAssertion lock_assertion(mCvMutex);
+        if (mState == BluetoothStreamState::STARTED) {
+            retval = true;
+        } else if (mState == BluetoothStreamState::STANDBY) {
+            mState = BluetoothStreamState::STARTING;
+            lock.unlock();
+            if (BluetoothAudioSessionControl::StartStream(mSessionType)) {
+                retval = condWaitState(BluetoothStreamState::STARTING);
+            } else {
+                LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
+                           << " Hal fails";
+            }
+        }
+    }
+
+    if (retval) {
+        LOG(INFO) << __func__ << debugMessage() << ", state=" << getState()
+                  << ", mono=" << (mIsStereoToMono ? "true" : "false") << " done";
+    } else {
+        LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+    }
+
+    return retval;  // false if any failure like timeout
+}
+
+bool BluetoothAudioPortAidl::suspend() {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+
+    {
+        std::unique_lock lock(mCvMutex);
+        base::ScopedLockAssertion lock_assertion(mCvMutex);
+        if (mState == BluetoothStreamState::STANDBY) {
+            return true;  // nop, return
+        } else if (mState == BluetoothStreamState::SUSPENDING ||
+                   mState == BluetoothStreamState::STARTING) {
+            /* If port is in transient state, give some time to respond */
+            auto state_ = mState;
+            lock.unlock();
+            if (!condWaitState(state_)) {
+                LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+                return false;
+            }
+        }
+    }
+
+    bool retval = false;
+    {
+        std::unique_lock lock(mCvMutex);
+        base::ScopedLockAssertion lock_assertion(mCvMutex);
+        if (mState == BluetoothStreamState::STANDBY) {
+            retval = true;
+        } else if (mState == BluetoothStreamState::STARTED) {
+            mState = BluetoothStreamState::SUSPENDING;
+            lock.unlock();
+            if (BluetoothAudioSessionControl::SuspendStream(mSessionType)) {
+                retval = condWaitState(BluetoothStreamState::SUSPENDING);
+            } else {
+                LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
+                           << " Hal fails";
+            }
+        }
+    }
+
+    if (retval) {
+        LOG(INFO) << __func__ << debugMessage() << ", state=" << getState() << " done";
+    } else {
+        LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+    }
+
+    return retval;  // false if any failure like timeout
+}
+
+void BluetoothAudioPortAidl::stop() {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return;
+    }
+    std::lock_guard guard(mCvMutex);
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+    if (mState != BluetoothStreamState::DISABLED) {
+        BluetoothAudioSessionControl::StopStream(mSessionType);
+        mState = BluetoothStreamState::DISABLED;
+    }
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
+}
+
+size_t BluetoothAudioPortAidlOut::writeData(const void* buffer, size_t bytes) const {
+    if (!buffer) {
+        LOG(ERROR) << __func__ << ": bad input arg";
+        return 0;
+    }
+
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return 0;
+    }
+
+    if (!mIsStereoToMono) {
+        return BluetoothAudioSessionControl::OutWritePcmData(mSessionType, buffer, bytes);
+    }
+
+    // WAR to mix the stereo into Mono (16 bits per sample)
+    const size_t write_frames = bytes >> 2;
+    if (write_frames == 0) return 0;
+    auto src = static_cast<const int16_t*>(buffer);
+    std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
+    downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
+    // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
+    auto totalWrite = BluetoothAudioSessionControl::OutWritePcmData(mSessionType, dst.get(),
+                                                                    write_frames * 2);
+    return totalWrite * 2;
+}
+
+size_t BluetoothAudioPortAidlIn::readData(void* buffer, size_t bytes) const {
+    if (!buffer) {
+        LOG(ERROR) << __func__ << ": bad input arg";
+        return 0;
+    }
+
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return 0;
+    }
+
+    return BluetoothAudioSessionControl::InReadPcmData(mSessionType, buffer, bytes);
+}
+
+bool BluetoothAudioPortAidl::getPresentationPosition(
+        PresentationPosition& presentation_position) const {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    bool retval = BluetoothAudioSessionControl::GetPresentationPosition(mSessionType,
+                                                                        presentation_position);
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
+                 << presentation_position.toString();
+
+    return retval;
+}
+
+bool BluetoothAudioPortAidl::updateSourceMetadata(const SourceMetadata& source_metadata) const {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
+               << source_metadata.tracks.size() << " track(s)";
+    if (source_metadata.tracks.size() == 0) return true;
+    return BluetoothAudioSessionControl::UpdateSourceMetadata(mSessionType, source_metadata);
+}
+
+bool BluetoothAudioPortAidl::updateSinkMetadata(const SinkMetadata& sink_metadata) const {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
+               << sink_metadata.tracks.size() << " track(s)";
+    if (sink_metadata.tracks.size() == 0) return true;
+    return BluetoothAudioSessionControl::UpdateSinkMetadata(mSessionType, sink_metadata);
+}
+
+BluetoothStreamState BluetoothAudioPortAidl::getState() const {
+    return mState;
+}
+
+bool BluetoothAudioPortAidl::setState(BluetoothStreamState state) {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    std::lock_guard guard(mCvMutex);
+    LOG(DEBUG) << __func__ << ": BluetoothAudioPortAidl old state = " << mState
+               << " new state = " << state;
+    mState = state;
+    return true;
+}
+
+bool BluetoothAudioPortAidl::isA2dp() const {
+    return mSessionType == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+           mSessionType == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+bool BluetoothAudioPortAidl::isLeAudio() const {
+    return mSessionType == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+           mSessionType == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
+           mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+           mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+           mSessionType == SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
+           mSessionType == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+std::string BluetoothAudioPortAidl::debugMessage() const {
+    return StringPrintf(": session_type=%s, cookie=%#hx", toString(mSessionType).c_str(), mCookie);
+}
+
+}  // namespace android::bluetooth::audio::aidl
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
new file mode 100644
index 0000000..bfe7ca0
--- /dev/null
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_ModuleBluetooth"
+
+#include <android-base/logging.h>
+
+#include "core-impl/ModuleBluetooth.h"
+#include "core-impl/StreamBluetooth.h"
+
+namespace aidl::android::hardware::audio::core {
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
+        std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
+    if (!mBluetoothA2dp) {
+        auto handle = ndk::SharedRefBase::make<BluetoothA2dp>();
+        handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+        mBluetoothA2dp = handle;
+    }
+    *_aidl_return = mBluetoothA2dp.getInstance();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
+    if (!mBluetoothLe) {
+        auto handle = ndk::SharedRefBase::make<BluetoothLe>();
+        handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+        mBluetoothLe = handle;
+    }
+    *_aidl_return = mBluetoothLe.getInstance();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
+Module::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
+    return std::make_tuple(std::weak_ptr<IBluetooth>(), mBluetoothA2dp.getInstance(),
+                           mBluetoothLe.getInstance());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::getMicMute(bool* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::setMicMute(bool in_mute __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::createInputStream(
+        StreamContext&& context, const SinkMetadata& sinkMetadata,
+        const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+    return createStreamInstance<StreamInBluetooth>(result, std::move(context), sinkMetadata,
+                                                   microphones, getBtProfileManagerHandles());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::createOutputStream(
+        StreamContext&& context, const SourceMetadata& sourceMetadata,
+        const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+    return createStreamInstance<StreamOutBluetooth>(result, std::move(context), sourceMetadata,
+                                                    offloadInfo, getBtProfileManagerHandles());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::onMasterVolumeChanged(float) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
new file mode 100644
index 0000000..91a33c2
--- /dev/null
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_StreamBluetooth"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <audio_utils/clock.h>
+
+#include "BluetoothAudioSessionControl.h"
+#include "core-impl/StreamBluetooth.h"
+
+namespace aidl::android::hardware::audio::core {
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::audio::core::VendorParameter;
+using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
+using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioDevice;
+using ::aidl::android::media::audio::common::AudioDeviceAddress;
+using ::aidl::android::media::audio::common::AudioFormatDescription;
+using ::aidl::android::media::audio::common::AudioFormatType;
+using ::aidl::android::media::audio::common::AudioOffloadInfo;
+using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using ::aidl::android::media::audio::common::MicrophoneInfo;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
+using ::android::bluetooth::audio::aidl::BluetoothStreamState;
+
+constexpr int kBluetoothDefaultInputBufferMs = 20;
+constexpr int kBluetoothDefaultOutputBufferMs = 10;
+// constexpr int kBluetoothSpatializerOutputBufferMs = 10;
+
+size_t getFrameCount(uint64_t durationUs, uint32_t sampleRate) {
+    return (durationUs * sampleRate) / 1000000;
+}
+
+// pcm configuration params are not really used by the module
+StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
+                                 Module::BtProfileHandles&& btHandles)
+    : StreamCommonImpl(context, metadata),
+      mSampleRate(getContext().getSampleRate()),
+      mChannelLayout(getContext().getChannelLayout()),
+      mFormat(getContext().getFormat()),
+      mFrameSizeBytes(getContext().getFrameSize()),
+      mIsInput(isInput(metadata)),
+      mBluetoothA2dp(std::move(std::get<Module::BtInterface::BTA2DP>(btHandles))),
+      mBluetoothLe(std::move(std::get<Module::BtInterface::BTLE>(btHandles))) {
+    mPreferredDataIntervalUs =
+            mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs;
+    mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
+    mIsInitialized = false;
+    mIsReadyToClose = false;
+}
+
+::android::status_t StreamBluetooth::init() {
+    return ::android::OK;  // defering this till we get AudioDeviceDescription
+}
+
+const StreamCommonInterface::ConnectedDevices& StreamBluetooth::getConnectedDevices() const {
+    std::lock_guard guard(mLock);
+    return StreamCommonImpl::getConnectedDevices();
+}
+
+ndk::ScopedAStatus StreamBluetooth::setConnectedDevices(
+        const std::vector<AudioDevice>& connectedDevices) {
+    if (mIsInput && connectedDevices.size() > 1) {
+        LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
+                   << ") for input stream";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    for (const auto& connectedDevice : connectedDevices) {
+        if (connectedDevice.address.getTag() != AudioDeviceAddress::mac) {
+            LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    std::lock_guard guard(mLock);
+    RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
+    mIsInitialized = false;  // updated connected device list, need initialization
+    return ndk::ScopedAStatus::ok();
+}
+
+::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::flush() {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::pause() {
+    return standby();
+}
+
+::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
+                                              size_t* actualFrameCount, int32_t* latencyMs) {
+    std::lock_guard guard(mLock);
+    if (!mIsInitialized || mIsReadyToClose) {
+        // 'setConnectedDevices' has been called or stream is ready to close, so no transfers
+        *actualFrameCount = 0;
+        *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
+        return ::android::OK;
+    }
+    *actualFrameCount = 0;
+    *latencyMs = 0;
+    for (auto proxy : mBtDeviceProxies) {
+        if (!proxy->start()) {
+            LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to start ";
+            return -EIO;
+        }
+        const size_t fc = std::min(frameCount, mPreferredFrameCount);
+        const size_t bytesToTransfer = fc * mFrameSizeBytes;
+        if (mIsInput) {
+            const size_t totalRead = proxy->readData(buffer, bytesToTransfer);
+            *actualFrameCount = std::max(*actualFrameCount, totalRead / mFrameSizeBytes);
+        } else {
+            const size_t totalWrite = proxy->writeData(buffer, bytesToTransfer);
+            *actualFrameCount = std::max(*actualFrameCount, totalWrite / mFrameSizeBytes);
+        }
+        PresentationPosition presentation_position;
+        if (!proxy->getPresentationPosition(presentation_position)) {
+            LOG(ERROR) << __func__ << ": getPresentationPosition returned error ";
+            return ::android::UNKNOWN_ERROR;
+        }
+        *latencyMs =
+                std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
+                                               NANOS_PER_MILLISECOND));
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::initialize() {
+    if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::IsAidlAvailable()) {
+        LOG(ERROR) << __func__ << ": IBluetoothAudioProviderFactory service not available";
+        return ::android::UNKNOWN_ERROR;
+    }
+    if (StreamCommonImpl::getConnectedDevices().empty()) {
+        LOG(ERROR) << __func__ << ", has no connected devices";
+        return ::android::NO_INIT;
+    }
+    // unregister older proxies (if any)
+    for (auto proxy : mBtDeviceProxies) {
+        proxy->stop();
+        proxy->unregisterPort();
+    }
+    mBtDeviceProxies.clear();
+    for (auto it = StreamCommonImpl::getConnectedDevices().begin();
+         it != StreamCommonImpl::getConnectedDevices().end(); ++it) {
+        std::shared_ptr<BluetoothAudioPortAidl> proxy =
+                mIsInput ? std::shared_ptr<BluetoothAudioPortAidl>(
+                                   std::make_shared<BluetoothAudioPortAidlIn>())
+                         : std::shared_ptr<BluetoothAudioPortAidl>(
+                                   std::make_shared<BluetoothAudioPortAidlOut>());
+        if (proxy->registerPort(it->type)) {
+            LOG(ERROR) << __func__ << ": cannot init HAL";
+            return ::android::UNKNOWN_ERROR;
+        }
+        PcmConfiguration config;
+        if (!proxy->loadAudioConfig(&config)) {
+            LOG(ERROR) << __func__ << ": state=" << proxy->getState()
+                       << " failed to get audio config";
+            return ::android::UNKNOWN_ERROR;
+        }
+        // TODO: Ensure minimum duration for spatialized output?
+        // WAR to support Mono / 16 bits per sample as the Bluetooth stack required
+        if (!mIsInput && config.channelMode == ChannelMode::MONO && config.bitsPerSample == 16) {
+            proxy->forcePcmStereoToMono(true);
+            config.channelMode = ChannelMode::STEREO;
+            LOG(INFO) << __func__ << ": force channels = to be AUDIO_CHANNEL_OUT_STEREO";
+        }
+        if (!checkConfigParams(config)) {
+            LOG(ERROR) << __func__ << " checkConfigParams failed";
+            return ::android::UNKNOWN_ERROR;
+        }
+        mBtDeviceProxies.push_back(std::move(proxy));
+    }
+    mIsInitialized = true;
+    return ::android::OK;
+}
+
+bool StreamBluetooth::checkConfigParams(
+        ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config) {
+    if ((int)mSampleRate != config.sampleRateHz) {
+        LOG(ERROR) << __func__ << ": Sample Rate mismatch, stream val = " << mSampleRate
+                   << " hal val = " << config.sampleRateHz;
+        return false;
+    }
+    auto channelCount = aidl::android::hardware::audio::common::getChannelCount(mChannelLayout);
+    if ((config.channelMode == ChannelMode::MONO && channelCount != 1) ||
+        (config.channelMode == ChannelMode::STEREO && channelCount != 2)) {
+        LOG(ERROR) << __func__ << ": Channel count mismatch, stream val = " << channelCount
+                   << " hal val = " << toString(config.channelMode);
+        return false;
+    }
+    if (mFormat.type != AudioFormatType::PCM) {
+        LOG(ERROR) << __func__ << ": unexpected format type "
+                   << aidl::android::media::audio::common::toString(mFormat.type);
+        return false;
+    }
+    int8_t bps = aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(mFormat.pcm) * 8;
+    if (bps != config.bitsPerSample) {
+        LOG(ERROR) << __func__ << ": bits per sample mismatch, stream val = " << bps
+                   << " hal val = " << config.bitsPerSample;
+        return false;
+    }
+    if (config.dataIntervalUs > 0) {
+        mPreferredDataIntervalUs =
+                std::min((int32_t)mPreferredDataIntervalUs, config.dataIntervalUs);
+        mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
+    }
+    return true;
+}
+
+ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
+    std::lock_guard guard(mLock);
+    mIsReadyToClose = true;
+    return ndk::ScopedAStatus::ok();
+}
+
+::android::status_t StreamBluetooth::standby() {
+    std::lock_guard guard(mLock);
+    if (!mIsInitialized) {
+        if (auto status = initialize(); status != ::android::OK) return status;
+    }
+    for (auto proxy : mBtDeviceProxies) {
+        if (!proxy->suspend()) {
+            LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to stand by ";
+            return -EIO;
+        }
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::start() {
+    std::lock_guard guard(mLock);
+    if (!mIsInitialized) return initialize();
+    return ::android::OK;
+}
+
+void StreamBluetooth::shutdown() {
+    std::lock_guard guard(mLock);
+    for (auto proxy : mBtDeviceProxies) {
+        proxy->stop();
+        proxy->unregisterPort();
+    }
+    mBtDeviceProxies.clear();
+}
+
+ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
+    std::lock_guard guard(mLock);
+    if (!mIsInitialized) return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    bool isOk = true;
+    if (isInput(metadata)) {
+        isOk = mBtDeviceProxies[0]->updateSinkMetadata(std::get<SinkMetadata>(metadata));
+    } else {
+        for (auto proxy : mBtDeviceProxies) {
+            if (!proxy->updateSourceMetadata(std::get<SourceMetadata>(metadata))) isOk = false;
+        }
+    }
+    return isOk ? ndk::ScopedAStatus::ok()
+                : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
+    if (mIsInput) {
+        LOG(WARNING) << __func__ << ": not handled";
+        return ndk::ScopedAStatus::ok();
+    }
+    auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
+                         bool isEnabled) -> bool {
+        if (!isEnabled) {
+            if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
+            return false;
+        }
+        return proxy->standby();
+    };
+    bool hasA2dpParam, enableA2dp;
+    auto btA2dp = mBluetoothA2dp.lock();
+    hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
+    bool hasLeParam, enableLe;
+    auto btLe = mBluetoothLe.lock();
+    hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
+    std::unique_lock lock(mLock);
+    ::android::base::ScopedLockAssertion lock_assertion(mLock);
+    if (!mIsInitialized) {
+        LOG(WARNING) << __func__ << ": init not done";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    for (auto proxy : mBtDeviceProxies) {
+        if ((hasA2dpParam && proxy->isA2dp() && !applyParam(proxy, enableA2dp)) ||
+            (hasLeParam && proxy->isLeAudio() && !applyParam(proxy, enableLe))) {
+            LOG(DEBUG) << __func__ << ": applyParam failed";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
+                                     const std::vector<MicrophoneInfo>& microphones,
+                                     Module::BtProfileHandles&& btProfileHandles)
+    : StreamIn(std::move(context), microphones),
+      StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles)) {}
+
+ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
+        std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
+                                       const SourceMetadata& sourceMetadata,
+                                       const std::optional<AudioOffloadInfo>& offloadInfo,
+                                       Module::BtProfileHandles&& btProfileHandles)
+    : StreamOut(std::move(context), offloadInfo),
+      StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles)) {}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index fabb93b..e2bc833 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -33,14 +33,19 @@
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_6;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_PENTA;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_QUAD;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_TRI;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index d57790a..9a3a447 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -535,12 +535,17 @@
             <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_MONO"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_STEREO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_FRONT_BACK"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_TRI"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_6"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT0POINT2"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1POINT2"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT0POINT2"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_QUAD"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_PENTA"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_5POINT1"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO"/>
             <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO"/>
diff --git a/audio/aidl/default/extension/ExtensionEffect.cpp b/audio/aidl/default/extension/ExtensionEffect.cpp
index c4eebc0..4a4d71b6 100644
--- a/audio/aidl/default/extension/ExtensionEffect.cpp
+++ b/audio/aidl/default/extension/ExtensionEffect.cpp
@@ -30,8 +30,8 @@
 using aidl::android::hardware::audio::effect::DefaultExtension;
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::ExtensionEffect;
-using aidl::android::hardware::audio::effect::getEffectUuidExtensionImpl;
-using aidl::android::hardware::audio::effect::getEffectUuidExtensionType;
+using aidl::android::hardware::audio::effect::getEffectImplUuidExtension;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidExtension;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::Range;
 using aidl::android::hardware::audio::effect::VendorExtension;
@@ -39,7 +39,7 @@
 
 extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
                                            std::shared_ptr<IEffect>* instanceSpp) {
-    if (!in_impl_uuid || *in_impl_uuid != getEffectUuidExtensionImpl()) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
         LOG(ERROR) << __func__ << "uuid not supported";
         return EX_ILLEGAL_ARGUMENT;
     }
@@ -54,7 +54,7 @@
 }
 
 extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
-    if (!in_impl_uuid || *in_impl_uuid != getEffectUuidExtensionImpl()) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
         LOG(ERROR) << __func__ << "uuid not supported";
         return EX_ILLEGAL_ARGUMENT;
     }
@@ -67,8 +67,8 @@
 const std::string ExtensionEffect::kEffectName = "ExtensionEffectExample";
 
 const Descriptor ExtensionEffect::kDescriptor = {
-        .common = {.id = {.type = getEffectUuidExtensionType(),
-                          .uuid = getEffectUuidExtensionImpl(),
+        .common = {.id = {.type = getEffectTypeUuidExtension(),
+                          .uuid = getEffectImplUuidExtension(),
                           .proxy = std::nullopt},
                    .name = ExtensionEffect::kEffectName,
                    .implementor = "The Android Open Source Project"}};
diff --git a/audio/aidl/default/include/core-impl/AidlConversionXsdc.h b/audio/aidl/default/include/core-impl/AidlConversionXsdc.h
new file mode 100644
index 0000000..c9aefc7
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/AidlConversionXsdc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/SurroundSoundConfig.h>
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <android_audio_policy_configuration.h>
+#include <media/AidlConversionUtil.h>
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<::aidl::android::media::audio::common::AudioFormatDescription>
+xsdc2aidl_AudioFormatDescription(const std::string& xsdc);
+
+ConversionResult<SurroundSoundConfig> xsdc2aidl_SurroundSoundConfig(
+        const ::android::audio::policy::configuration::SurroundSound& xsdc);
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
index 47918f0..090d585 100644
--- a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
@@ -18,6 +18,7 @@
 
 #include <string>
 
+#include <aidl/android/hardware/audio/core/SurroundSoundConfig.h>
 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
 #include <android_audio_policy_configuration.h>
 #include <android_audio_policy_configuration_enums.h>
@@ -35,6 +36,10 @@
     ::android::status_t getStatus() const { return mConverter.getStatus(); }
 
     const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
+    const SurroundSoundConfig& getSurroundSoundConfig();
+
+    // Public for testing purposes.
+    static const SurroundSoundConfig& getDefaultSurroundSoundConfig();
 
   private:
     const std::optional<::android::audio::policy::configuration::AudioPolicyConfiguration>&
@@ -48,7 +53,6 @@
     void parseVolumes();
     ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
             const std::string& xsdcCurvePoint);
-
     ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
             const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
 
diff --git a/audio/aidl/default/include/core-impl/Bluetooth.h b/audio/aidl/default/include/core-impl/Bluetooth.h
index 10e9045..44899bc 100644
--- a/audio/aidl/default/include/core-impl/Bluetooth.h
+++ b/audio/aidl/default/include/core-impl/Bluetooth.h
@@ -22,6 +22,15 @@
 
 namespace aidl::android::hardware::audio::core {
 
+class ParamChangeHandler {
+  public:
+    ParamChangeHandler() = default;
+    void registerHandler(std::function<ndk::ScopedAStatus()> handler) { mHandler = handler; }
+
+  protected:
+    std::function<ndk::ScopedAStatus()> mHandler = nullptr;
+};
+
 class Bluetooth : public BnBluetooth {
   public:
     Bluetooth();
@@ -34,7 +43,7 @@
     HfpConfig mHfpConfig;
 };
 
-class BluetoothA2dp : public BnBluetoothA2dp {
+class BluetoothA2dp : public BnBluetoothA2dp, public ParamChangeHandler {
   public:
     BluetoothA2dp() = default;
 
@@ -49,7 +58,7 @@
     bool mEnabled = false;
 };
 
-class BluetoothLe : public BnBluetoothLe {
+class BluetoothLe : public BnBluetoothLe, public ParamChangeHandler {
   public:
     BluetoothLe() = default;
 
diff --git a/audio/aidl/default/include/core-impl/ChildInterface.h b/audio/aidl/default/include/core-impl/ChildInterface.h
new file mode 100644
index 0000000..2421b59
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ChildInterface.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <utility>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder_platform.h>
+#include <system/thread_defs.h>
+
+namespace aidl::android::hardware::audio::core {
+
+// Helper used for interfaces that require a persistent instance. We hold them via a strong
+// pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
+template <class C>
+struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
+    ChildInterface() = default;
+    ChildInterface& operator=(const std::shared_ptr<C>& c) {
+        return operator=(std::shared_ptr<C>(c));
+    }
+    ChildInterface& operator=(std::shared_ptr<C>&& c) {
+        this->first = std::move(c);
+        return *this;
+    }
+    explicit operator bool() const { return !!this->first; }
+    C& operator*() const { return *(this->first); }
+    C* operator->() const { return this->first; }
+    // Use 'getInstance' when returning the interface instance.
+    std::shared_ptr<C> getInstance() {
+        if (this->second.get() == nullptr) {
+            this->second = this->first->asBinder();
+            AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
+                                           ANDROID_PRIORITY_AUDIO);
+        }
+        return this->first;
+    }
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h
index 70320e4..6277c38 100644
--- a/audio/aidl/default/include/core-impl/Configuration.h
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -45,6 +45,8 @@
 
 std::unique_ptr<Configuration> getPrimaryConfiguration();
 std::unique_ptr<Configuration> getRSubmixConfiguration();
+std::unique_ptr<Configuration> getStubConfiguration();
 std::unique_ptr<Configuration> getUsbConfiguration();
+std::unique_ptr<Configuration> getBluetoothConfiguration();
 
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/DevicePortProxy.h b/audio/aidl/default/include/core-impl/DevicePortProxy.h
new file mode 100644
index 0000000..13b8c91
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/DevicePortProxy.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+
+#include <android-base/thread_annotations.h>
+
+#include <aidl/android/hardware/audio/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <aidl/android/media/audio/common/AudioDeviceDescription.h>
+
+#include "BluetoothAudioSessionControl.h"
+
+namespace android::bluetooth::audio::aidl {
+
+enum class BluetoothStreamState : uint8_t {
+    DISABLED = 0,  // This stream is closing or Bluetooth profiles (A2DP/LE) is disabled
+    STANDBY,
+    STARTING,
+    STARTED,
+    SUSPENDING,
+    UNKNOWN,
+};
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state);
+
+/**
+ * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
+ * Session Control. All methods are not thread safe, so users must acquire a
+ * lock. Note: currently, getState() of DevicePortProxy is only used for
+ * verbose logging, it is not locked, so the state may not be synchronized.
+ */
+class BluetoothAudioPort {
+  public:
+    BluetoothAudioPort() = default;
+    virtual ~BluetoothAudioPort() = default;
+
+    /**
+     * Fetch output control / data path of BluetoothAudioPort and setup
+     * callbacks into BluetoothAudioProvider. If registerPort() returns false, the audio
+     * HAL must delete this BluetoothAudioPort and return EINVAL to caller
+     */
+    virtual bool registerPort(
+            const ::aidl::android::media::audio::common::AudioDeviceDescription&) = 0;
+
+    /**
+     * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl.
+     * Audio HAL must delete this BluetoothAudioPort after calling this.
+     */
+    virtual void unregisterPort() = 0;
+
+    /**
+     * When the Audio framework / HAL tries to query audio config about format,
+     * channel mask and sample rate, it uses this function to fetch from the
+     * Bluetooth stack
+     */
+    virtual bool loadAudioConfig(
+            ::aidl::android::hardware::bluetooth::audio::PcmConfiguration*) const = 0;
+
+    /**
+     * WAR to support Mono mode / 16 bits per sample
+     */
+    virtual void forcePcmStereoToMono(bool) = 0;
+
+    /**
+     * When the Audio framework / HAL wants to change the stream state, it invokes
+     * these 4 functions to control the Bluetooth stack (Audio Control Path).
+     * Note: standby(), start() and suspend() will return true when there are no errors.
+
+     * Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is
+     * disabled, the port is first set to STANDBY by calling suspend and then mState is set to
+     * DISABLED. To reset the state back to STANDBY this method is called.
+     */
+    virtual bool standby() = 0;
+
+    /**
+     * Called by Audio framework / HAL to start the stream
+     */
+    virtual bool start() = 0;
+
+    /**
+     * Called by Audio framework / HAL to suspend the stream
+     */
+    virtual bool suspend() = 0;
+
+    /**
+     * Called by Audio framework / HAL to stop the stream
+     */
+    virtual void stop() = 0;
+
+    /**
+     * Called by the Audio framework / HAL to fetch information about audio frames
+     * presented to an external sink, or frames presented fror an internal sink
+     */
+    virtual bool getPresentationPosition(
+            ::aidl::android::hardware::bluetooth::audio::PresentationPosition&) const = 0;
+
+    /**
+     * Called by the Audio framework / HAL when the metadata of the stream's
+     * source has been changed.
+     */
+    virtual bool updateSourceMetadata(
+            const ::aidl::android::hardware::audio::common::SourceMetadata&) const {
+        return false;
+    }
+
+    /**
+     * Called by the Audio framework / HAL when the metadata of the stream's
+     * sink has been changed.
+     */
+    virtual bool updateSinkMetadata(
+            const ::aidl::android::hardware::audio::common::SinkMetadata&) const {
+        return false;
+    }
+
+    /**
+     * Return the current BluetoothStreamState
+     */
+    virtual BluetoothStreamState getState() const = 0;
+
+    /**
+     * Set the current BluetoothStreamState
+     */
+    virtual bool setState(BluetoothStreamState) = 0;
+
+    virtual bool isA2dp() const = 0;
+
+    virtual bool isLeAudio() const = 0;
+
+    virtual bool getPreferredDataIntervalUs(size_t*) const = 0;
+
+    virtual size_t writeData(const void*, size_t) const { return 0; }
+
+    virtual size_t readData(void*, size_t) const { return 0; }
+};
+
+class BluetoothAudioPortAidl : public BluetoothAudioPort {
+  public:
+    BluetoothAudioPortAidl();
+    virtual ~BluetoothAudioPortAidl();
+
+    bool registerPort(const ::aidl::android::media::audio::common::AudioDeviceDescription&
+                              description) override;
+
+    void unregisterPort() override;
+
+    bool loadAudioConfig(::aidl::android::hardware::bluetooth::audio::PcmConfiguration* audio_cfg)
+            const override;
+
+    void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; }
+
+    bool standby() override;
+    bool start() override;
+    bool suspend() override;
+    void stop() override;
+
+    bool getPresentationPosition(::aidl::android::hardware::bluetooth::audio::PresentationPosition&
+                                         presentation_position) const override;
+
+    bool updateSourceMetadata(const ::aidl::android::hardware::audio::common::SourceMetadata&
+                                      sourceMetadata) const override;
+
+    bool updateSinkMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
+                                    sinkMetadata) const override;
+
+    /**
+     * Return the current BluetoothStreamState
+     * Note: This method is used for logging, does not lock, so value returned may not be latest
+     */
+    BluetoothStreamState getState() const override NO_THREAD_SAFETY_ANALYSIS;
+
+    bool setState(BluetoothStreamState state) override;
+
+    bool isA2dp() const override;
+
+    bool isLeAudio() const override;
+
+    bool getPreferredDataIntervalUs(size_t* interval_us) const override;
+
+  protected:
+    uint16_t mCookie;
+    BluetoothStreamState mState GUARDED_BY(mCvMutex);
+    ::aidl::android::hardware::bluetooth::audio::SessionType mSessionType;
+    // WR to support Mono: True if fetching Stereo and mixing into Mono
+    bool mIsStereoToMono = false;
+
+    bool inUse() const;
+
+    std::string debugMessage() const;
+
+  private:
+    // start()/suspend() report state change status via callback. Wait until kMaxWaitingTimeMs or a
+    // state change after a call to start()/suspend() and analyse the returned status. Below mutex,
+    // conditional variable serves this purpose.
+    mutable std::mutex mCvMutex;
+    std::condition_variable mInternalCv GUARDED_BY(mCvMutex);
+
+    // Check and initialize session type for |devices| If failed, this
+    // BluetoothAudioPortAidl is not initialized and must be deleted.
+    bool initSessionType(
+            const ::aidl::android::media::audio::common::AudioDeviceDescription& description);
+
+    bool condWaitState(BluetoothStreamState state);
+
+    void controlResultHandler(
+            uint16_t cookie,
+            const ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus& status);
+    void sessionChangedHandler(uint16_t cookie);
+};
+
+class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl {
+  public:
+    // The audio data path to the Bluetooth stack (Software encoding)
+    size_t writeData(const void* buffer, size_t bytes) const override;
+};
+
+class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl {
+  public:
+    // The audio data path from the Bluetooth stack (Software decoded)
+    size_t readData(void* buffer, size_t bytes) const override;
+};
+
+}  // namespace android::bluetooth::audio::aidl
\ No newline at end of file
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 83ecfaa..fb3eef2 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -16,12 +16,14 @@
 
 #pragma once
 
+#include <iostream>
 #include <map>
 #include <memory>
 #include <set>
 
 #include <aidl/android/hardware/audio/core/BnModule.h>
 
+#include "core-impl/ChildInterface.h"
 #include "core-impl/Configuration.h"
 #include "core-impl/Stream.h"
 
@@ -31,41 +33,20 @@
   public:
     // This value is used for all AudioPatches and reported by all streams.
     static constexpr int32_t kLatencyMs = 10;
-    enum Type : int { DEFAULT, R_SUBMIX, USB };
+    enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
+    enum BtInterface : int { BTCONF, BTA2DP, BTLE };
+
+    static std::shared_ptr<Module> createInstance(Type type);
 
     explicit Module(Type type) : mType(type) {}
 
-    static std::shared_ptr<Module> createInstance(Type type);
-    static StreamIn::CreateInstance getStreamInCreator(Type type);
-    static StreamOut::CreateInstance getStreamOutCreator(Type type);
+    typedef std::tuple<std::weak_ptr<IBluetooth>, std::weak_ptr<IBluetoothA2dp>,
+                       std::weak_ptr<IBluetoothLe>>
+            BtProfileHandles;
 
-  private:
-    struct VendorDebug {
-        static const std::string kForceTransientBurstName;
-        static const std::string kForceSynchronousDrainName;
-        bool forceTransientBurst = false;
-        bool forceSynchronousDrain = false;
-    };
-    // Helper used for interfaces that require a persistent instance. We hold them via a strong
-    // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
-    template <class C>
-    struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
-        ChildInterface() {}
-        ChildInterface& operator=(const std::shared_ptr<C>& c) {
-            return operator=(std::shared_ptr<C>(c));
-        }
-        ChildInterface& operator=(std::shared_ptr<C>&& c) {
-            this->first = std::move(c);
-            this->second = this->first->asBinder();
-            AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
-                                           ANDROID_PRIORITY_AUDIO);
-            return *this;
-        }
-        explicit operator bool() const { return !!this->first; }
-        C& operator*() const { return *(this->first); }
-        C* operator->() const { return this->first; }
-        std::shared_ptr<C> getPtr() const { return this->first; }
-    };
+  protected:
+    // The vendor extension done via inheritance can override interface methods and augment
+    // a call to the base implementation.
 
     ndk::ScopedAStatus setModuleDebug(
             const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
@@ -146,50 +127,53 @@
     ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
 
-    void cleanUpPatch(int32_t patchId);
-    ndk::ScopedAStatus createStreamContext(
-            int32_t in_portConfigId, int64_t in_bufferSizeFrames,
-            std::shared_ptr<IStreamCallback> asyncCallback,
-            std::shared_ptr<IStreamOutEventCallback> outEventCallback,
-            ::aidl::android::hardware::audio::core::StreamContext* out_context);
-    std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
-            int32_t portConfigId);
-    std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
-    ndk::ScopedAStatus findPortIdForNewStream(
-            int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
-    internal::Configuration& getConfig();
-    template <typename C>
-    std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
-    void registerPatch(const AudioPatch& patch);
-    void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
-    bool isMmapSupported();
-
     // This value is used for all AudioPatches.
     static constexpr int32_t kMinimumStreamBufferSizeFrames = 256;
     // The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
     static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
 
+  private:
+    struct VendorDebug {
+        static const std::string kForceTransientBurstName;
+        static const std::string kForceSynchronousDrainName;
+        bool forceTransientBurst = false;
+        bool forceSynchronousDrain = false;
+    };
+    // ids of device ports created at runtime via 'connectExternalDevice'.
+    // Also stores a list of ids of mix ports with dynamic profiles that were populated from
+    // the connected port. This list can be empty, thus an int->int multimap can't be used.
+    using ConnectedDevicePorts = std::map<int32_t, std::vector<int32_t>>;
+    // Maps port ids and port config ids to patch ids.
+    // Multimap because both ports and configs can be used by multiple patches.
+    using Patches = std::multimap<int32_t, int32_t>;
+
     const Type mType;
     std::unique_ptr<internal::Configuration> mConfig;
     ModuleDebug mDebug;
     VendorDebug mVendorDebug;
-    ChildInterface<ITelephony> mTelephony;
-    ChildInterface<IBluetooth> mBluetooth;
-    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
-    ChildInterface<IBluetoothLe> mBluetoothLe;
-    // ids of device ports created at runtime via 'connectExternalDevice'.
-    // Also stores ids of mix ports with dynamic profiles which got populated from the connected
-    // port.
-    std::map<int32_t, std::vector<int32_t>> mConnectedDevicePorts;
+    ConnectedDevicePorts mConnectedDevicePorts;
     Streams mStreams;
-    // Maps port ids and port config ids to patch ids.
-    // Multimap because both ports and configs can be used by multiple patches.
-    std::multimap<int32_t, int32_t> mPatches;
+    Patches mPatches;
     bool mMicMute = false;
+    bool mMasterMute = false;
+    float mMasterVolume = 1.0f;
     ChildInterface<sounddose::ISoundDose> mSoundDose;
     std::optional<bool> mIsMmapSupported;
 
   protected:
+    // The following virtual functions are intended for vendor extension via inheritance.
+
+    virtual ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) = 0;
+    virtual ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) = 0;
     // If the module is unable to populate the connected device port correctly, the returned error
     // code must correspond to the errors of `IModule.connectedExternalDevice` method.
     virtual ndk::ScopedAStatus populateConnectedDevicePort(
@@ -203,9 +187,38 @@
             const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
     virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
     virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
+    virtual std::unique_ptr<internal::Configuration> initializeConfig();
 
-    bool mMasterMute = false;
-    float mMasterVolume = 1.0f;
+    // Utility and helper functions accessible to subclasses.
+    ndk::ScopedAStatus bluetoothParametersUpdated();
+    void cleanUpPatch(int32_t patchId);
+    ndk::ScopedAStatus createStreamContext(
+            int32_t in_portConfigId, int64_t in_bufferSizeFrames,
+            std::shared_ptr<IStreamCallback> asyncCallback,
+            std::shared_ptr<IStreamOutEventCallback> outEventCallback,
+            ::aidl::android::hardware::audio::core::StreamContext* out_context);
+    std::vector<::aidl::android::media::audio::common::AudioDevice> findConnectedDevices(
+            int32_t portConfigId);
+    std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
+    ndk::ScopedAStatus findPortIdForNewStream(
+            int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+    virtual BtProfileHandles getBtProfileManagerHandles();
+    internal::Configuration& getConfig();
+    const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
+    bool getMasterMute() const { return mMasterMute; }
+    bool getMasterVolume() const { return mMasterVolume; }
+    bool getMicMute() const { return mMicMute; }
+    const Patches& getPatches() const { return mPatches; }
+    const Streams& getStreams() const { return mStreams; }
+    Type getType() const { return mType; }
+    bool isMmapSupported();
+    template <typename C>
+    std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
+    void registerPatch(const AudioPatch& patch);
+    ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
+                                                   const AudioPatch& newPatch);
 };
 
+std::ostream& operator<<(std::ostream& os, Module::Type t);
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleAlsa.h b/audio/aidl/default/include/core-impl/ModuleAlsa.h
new file mode 100644
index 0000000..5815961
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleAlsa.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+// This class is intended to be used as a base class for implementations
+// that use TinyAlsa. This can be either a primary module or a USB Audio
+// module. This class does not define a complete module implementation,
+// and should never be used on its own. Derived classes are expected to
+// provide necessary overrides for all interface methods omitted here.
+class ModuleAlsa : public Module {
+  public:
+    explicit ModuleAlsa(Module::Type type) : Module(type) {}
+
+  protected:
+    // Extension methods of 'Module'.
+    ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
new file mode 100644
index 0000000..68b4e6b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Bluetooth.h"
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleBluetooth final : public Module {
+  public:
+    ModuleBluetooth() : Module(Type::BLUETOOTH) {}
+
+  private:
+    BtProfileHandles getBtProfileManagerHandles() override;
+
+    ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
+    ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMicMute(bool in_mute) override;
+
+    ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) override;
+    ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) override;
+    ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
+    ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+
+    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
+    ChildInterface<IBluetoothLe> mBluetoothLe;
+};
+
+}  // namespace aidl::android::hardware::audio::core
\ No newline at end of file
diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h
new file mode 100644
index 0000000..6264237
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModulePrimary.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModulePrimary final : public Module {
+  public:
+    ModulePrimary() : Module(Type::DEFAULT) {}
+
+  protected:
+    ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
+
+    ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) override;
+    ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) override;
+
+  private:
+    ChildInterface<ITelephony> mTelephony;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
new file mode 100644
index 0000000..c4bf7b9
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleRemoteSubmix : public Module {
+  public:
+    ModuleRemoteSubmix() : Module(Type::R_SUBMIX) {}
+
+  private:
+    // IModule interfaces
+    ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMicMute(bool in_mute) override;
+
+    // Module interfaces
+    ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) override;
+    ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) override;
+    ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+    ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
+            override;
+    ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
+    ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleStub.h b/audio/aidl/default/include/core-impl/ModuleStub.h
new file mode 100644
index 0000000..4f77161
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleStub.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleStub final : public Module {
+  public:
+    ModuleStub() : Module(Type::STUB) {}
+
+  protected:
+    ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
+
+    ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) override;
+    ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) override;
+
+  private:
+    ChildInterface<IBluetooth> mBluetooth;
+    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
+    ChildInterface<IBluetoothLe> mBluetoothLe;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index 1aa2244..a296b8c 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -16,13 +16,13 @@
 
 #pragma once
 
-#include "core-impl/Module.h"
+#include "core-impl/ModuleAlsa.h"
 
 namespace aidl::android::hardware::audio::core {
 
-class ModuleUsb : public Module {
+class ModuleUsb final : public ModuleAlsa {
   public:
-    explicit ModuleUsb(Module::Type type) : Module(type) {}
+    ModuleUsb() : ModuleAlsa(Type::USB) {}
 
   private:
     // IModule interfaces
@@ -32,6 +32,17 @@
     ndk::ScopedAStatus setMicMute(bool in_mute) override;
 
     // Module interfaces
+    ndk::ScopedAStatus createInputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result) override;
+    ndk::ScopedAStatus createOutputStream(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result) override;
     ndk::ScopedAStatus populateConnectedDevicePort(
             ::aidl::android::media::audio::common::AudioPort* audioPort) override;
     ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 65680df..a02655f 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -25,6 +25,7 @@
 #include <variant>
 
 #include <StreamWorker.h>
+#include <Utils.h>
 #include <aidl/android/hardware/audio/common/SinkMetadata.h>
 #include <aidl/android/hardware/audio/common/SourceMetadata.h>
 #include <aidl/android/hardware/audio/core/BnStreamCommon.h>
@@ -34,12 +35,15 @@
 #include <aidl/android/hardware/audio/core/IStreamOutEventCallback.h>
 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
 #include <aidl/android/media/audio/common/AudioDevice.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioOffloadInfo.h>
 #include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include <error/expected_utils.h>
 #include <fmq/AidlMessageQueue.h>
 #include <system/thread_defs.h>
 #include <utils/Errors.h>
 
+#include "core-impl/ChildInterface.h"
 #include "core-impl/utils.h"
 
 namespace aidl::android::hardware::audio::core {
@@ -62,7 +66,8 @@
             DataMQ;
 
     // Ensure that this value is not used by any of StreamDescriptor.State enums
-    static constexpr int32_t STATE_CLOSED = -1;
+    static constexpr StreamDescriptor::State STATE_CLOSED =
+            static_cast<StreamDescriptor::State>(-1);
 
     struct DebugParameters {
         // An extra delay for transient states, in ms.
@@ -75,18 +80,23 @@
 
     StreamContext() = default;
     StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
+                  int portId,
                   const ::aidl::android::media::audio::common::AudioFormatDescription& format,
                   const ::aidl::android::media::audio::common::AudioChannelLayout& channelLayout,
-                  int sampleRate, std::unique_ptr<DataMQ> dataMQ,
+                  int sampleRate, const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+                  int32_t mixPortHandle, std::unique_ptr<DataMQ> dataMQ,
                   std::shared_ptr<IStreamCallback> asyncCallback,
                   std::shared_ptr<IStreamOutEventCallback> outEventCallback,
                   DebugParameters debugParameters)
         : mCommandMQ(std::move(commandMQ)),
           mInternalCommandCookie(std::rand()),
           mReplyMQ(std::move(replyMQ)),
+          mPortId(portId),
           mFormat(format),
           mChannelLayout(channelLayout),
           mSampleRate(sampleRate),
+          mFlags(flags),
+          mMixPortHandle(mixPortHandle),
           mDataMQ(std::move(dataMQ)),
           mAsyncCallback(asyncCallback),
           mOutEventCallback(outEventCallback),
@@ -95,29 +105,38 @@
         : mCommandMQ(std::move(other.mCommandMQ)),
           mInternalCommandCookie(other.mInternalCommandCookie),
           mReplyMQ(std::move(other.mReplyMQ)),
+          mPortId(other.mPortId),
           mFormat(other.mFormat),
           mChannelLayout(other.mChannelLayout),
           mSampleRate(other.mSampleRate),
+          mFlags(std::move(other.mFlags)),
+          mMixPortHandle(other.mMixPortHandle),
           mDataMQ(std::move(other.mDataMQ)),
           mAsyncCallback(std::move(other.mAsyncCallback)),
           mOutEventCallback(std::move(other.mOutEventCallback)),
-          mDebugParameters(std::move(other.mDebugParameters)) {}
+          mDebugParameters(std::move(other.mDebugParameters)),
+          mFrameCount(other.mFrameCount) {}
     StreamContext& operator=(StreamContext&& other) {
         mCommandMQ = std::move(other.mCommandMQ);
         mInternalCommandCookie = other.mInternalCommandCookie;
         mReplyMQ = std::move(other.mReplyMQ);
+        mPortId = std::move(other.mPortId);
         mFormat = std::move(other.mFormat);
         mChannelLayout = std::move(other.mChannelLayout);
         mSampleRate = other.mSampleRate;
+        mFlags = std::move(other.mFlags);
+        mMixPortHandle = other.mMixPortHandle;
         mDataMQ = std::move(other.mDataMQ);
         mAsyncCallback = std::move(other.mAsyncCallback);
         mOutEventCallback = std::move(other.mOutEventCallback);
         mDebugParameters = std::move(other.mDebugParameters);
+        mFrameCount = other.mFrameCount;
         return *this;
     }
 
     void fillDescriptor(StreamDescriptor* desc);
     std::shared_ptr<IStreamCallback> getAsyncCallback() const { return mAsyncCallback; }
+    size_t getBufferSizeInFrames() const;
     ::aidl::android::media::audio::common::AudioChannelLayout getChannelLayout() const {
         return mChannelLayout;
     }
@@ -126,73 +145,84 @@
     ::aidl::android::media::audio::common::AudioFormatDescription getFormat() const {
         return mFormat;
     }
+    ::aidl::android::media::audio::common::AudioIoFlags getFlags() const { return mFlags; }
     bool getForceTransientBurst() const { return mDebugParameters.forceTransientBurst; }
     bool getForceSynchronousDrain() const { return mDebugParameters.forceSynchronousDrain; }
     size_t getFrameSize() const;
     int getInternalCommandCookie() const { return mInternalCommandCookie; }
+    int32_t getMixPortHandle() const { return mMixPortHandle; }
     std::shared_ptr<IStreamOutEventCallback> getOutEventCallback() const {
         return mOutEventCallback;
     }
+    int getPortId() const { return mPortId; }
     ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
     int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
     int getSampleRate() const { return mSampleRate; }
     bool isValid() const;
+    // 'reset' is called on a Binder thread when closing the stream. Does not use
+    // locking because it only cleans MQ pointers which were also set on the Binder thread.
     void reset();
+    // 'advanceFrameCount' and 'getFrameCount' are only called on the worker thread.
+    long advanceFrameCount(size_t increase) { return mFrameCount += increase; }
+    long getFrameCount() const { return mFrameCount; }
 
   private:
     std::unique_ptr<CommandMQ> mCommandMQ;
     int mInternalCommandCookie;  // The value used to confirm that the command was posted internally
     std::unique_ptr<ReplyMQ> mReplyMQ;
+    int mPortId;
     ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
     ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
     int mSampleRate;
+    ::aidl::android::media::audio::common::AudioIoFlags mFlags;
+    int32_t mMixPortHandle;
     std::unique_ptr<DataMQ> mDataMQ;
     std::shared_ptr<IStreamCallback> mAsyncCallback;
     std::shared_ptr<IStreamOutEventCallback> mOutEventCallback;  // Only used by output streams
     DebugParameters mDebugParameters;
+    long mFrameCount = 0;
 };
 
+// This interface provides operations of the stream which are executed on the worker thread.
 struct DriverInterface {
-    using CreateInstance = std::function<DriverInterface*(const StreamContext&)>;
     virtual ~DriverInterface() = default;
-    // This function is called once, on the main thread, before starting the worker thread.
-    virtual ::android::status_t init() = 0;
-    // This function is called from Binder pool thread. It must be done in a thread-safe manner
-    // if this method and other methods in this interface share data.
-    virtual ::android::status_t setConnectedDevices(
-            const std::vector<::aidl::android::media::audio::common::AudioDevice>&
-                    connectedDevices) = 0;
-    // All the functions below are called on the worker thread.
+    // All the methods below are called on the worker thread.
+    virtual ::android::status_t init() = 0;  // This function is only called once.
     virtual ::android::status_t drain(StreamDescriptor::DrainMode mode) = 0;
     virtual ::android::status_t flush() = 0;
     virtual ::android::status_t pause() = 0;
+    virtual ::android::status_t standby() = 0;
+    virtual ::android::status_t start() = 0;
     virtual ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                          int32_t* latencyMs) = 0;
-    virtual ::android::status_t standby() = 0;
+    // No need to implement 'refinePosition' unless the driver can provide more precise
+    // data than just total frame count. For example, the driver may correctly account
+    // for any intermediate buffers.
+    virtual ::android::status_t refinePosition(StreamDescriptor::Position* /*position*/) {
+        return ::android::OK;
+    }
+    virtual void shutdown() = 0;  // This function is only called once.
 };
 
 class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
   public:
-    bool isClosed() const {
-        return static_cast<int32_t>(mState.load()) == StreamContext::STATE_CLOSED;
+    bool isClosed() const { return mState == StreamContext::STATE_CLOSED; }
+    StreamDescriptor::State setClosed() {
+        auto prevState = mState.exchange(StreamContext::STATE_CLOSED);
+        if (prevState != StreamContext::STATE_CLOSED) {
+            mStatePriorToClosing = prevState;
+        }
+        return mStatePriorToClosing;
     }
-    void setClosed() { mState = static_cast<StreamDescriptor::State>(StreamContext::STATE_CLOSED); }
     void setIsConnected(bool connected) { mIsConnected = connected; }
 
   protected:
     using DataBufferElement = int8_t;
 
-    StreamWorkerCommonLogic(const StreamContext& context, DriverInterface* driver)
-        : mDriver(driver),
-          mInternalCommandCookie(context.getInternalCommandCookie()),
-          mFrameSize(context.getFrameSize()),
-          mCommandMQ(context.getCommandMQ()),
-          mReplyMQ(context.getReplyMQ()),
-          mDataMQ(context.getDataMQ()),
-          mAsyncCallback(context.getAsyncCallback()),
-          mTransientStateDelayMs(context.getTransientStateDelayMs()),
-          mForceTransientBurst(context.getForceTransientBurst()),
-          mForceSynchronousDrain(context.getForceSynchronousDrain()) {}
+    StreamWorkerCommonLogic(StreamContext* context, DriverInterface* driver)
+        : mContext(context),
+          mDriver(driver),
+          mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
     std::string init() override;
     void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
     void populateReplyWrongState(StreamDescriptor::Reply* reply,
@@ -202,39 +232,37 @@
         mTransientStateStart = std::chrono::steady_clock::now();
     }
 
+    // The context is only used for reading, except for updating the frame count,
+    // which happens on the worker thread only.
+    StreamContext* const mContext;
     DriverInterface* const mDriver;
+    // This is the state the stream was in before being closed. It is retrieved by the main
+    // thread after joining the worker thread.
+    StreamDescriptor::State mStatePriorToClosing = StreamDescriptor::State::STANDBY;
     // Atomic fields are used both by the main and worker threads.
     std::atomic<bool> mIsConnected = false;
     static_assert(std::atomic<StreamDescriptor::State>::is_always_lock_free);
     std::atomic<StreamDescriptor::State> mState = StreamDescriptor::State::STANDBY;
-    // All fields are used on the worker thread only.
-    const int mInternalCommandCookie;
-    const size_t mFrameSize;
-    StreamContext::CommandMQ* const mCommandMQ;
-    StreamContext::ReplyMQ* const mReplyMQ;
-    StreamContext::DataMQ* const mDataMQ;
-    std::shared_ptr<IStreamCallback> mAsyncCallback;
+    // All fields below are used on the worker thread only.
     const std::chrono::duration<int, std::milli> mTransientStateDelayMs;
     std::chrono::time_point<std::chrono::steady_clock> mTransientStateStart;
-    const bool mForceTransientBurst;
-    const bool mForceSynchronousDrain;
     // We use an array and the "size" field instead of a vector to be able to detect
     // memory allocation issues.
     std::unique_ptr<DataBufferElement[]> mDataBuffer;
     size_t mDataBufferSize;
-    long mFrameCount = 0;
 };
 
 // This interface is used to decouple stream implementations from a concrete StreamWorker
 // implementation.
 struct StreamWorkerInterface {
-    using CreateInstance = std::function<StreamWorkerInterface*(const StreamContext& context,
-                                                                DriverInterface* driver)>;
+    using CreateInstance =
+            std::function<StreamWorkerInterface*(StreamContext* context, DriverInterface* driver)>;
     virtual ~StreamWorkerInterface() = default;
     virtual bool isClosed() const = 0;
     virtual void setIsConnected(bool isConnected) = 0;
-    virtual void setClosed() = 0;
+    virtual StreamDescriptor::State setClosed() = 0;
     virtual bool start() = 0;
+    virtual pid_t getTid() = 0;
     virtual void stop() = 0;
 };
 
@@ -244,21 +272,23 @@
     using WorkerImpl = ::android::hardware::audio::common::StreamWorker<WorkerLogic>;
 
   public:
-    StreamWorkerImpl(const StreamContext& context, DriverInterface* driver)
+    StreamWorkerImpl(StreamContext* context, DriverInterface* driver)
         : WorkerImpl(context, driver) {}
     bool isClosed() const override { return WorkerImpl::isClosed(); }
     void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
-    void setClosed() override { WorkerImpl::setClosed(); }
+    StreamDescriptor::State setClosed() override { return WorkerImpl::setClosed(); }
     bool start() override {
-        return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_AUDIO);
+        // This is an "audio service thread," must have elevated priority.
+        return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
     }
+    pid_t getTid() override { return WorkerImpl::getTid(); }
     void stop() override { return WorkerImpl::stop(); }
 };
 
 class StreamInWorkerLogic : public StreamWorkerCommonLogic {
   public:
     static const std::string kThreadName;
-    StreamInWorkerLogic(const StreamContext& context, DriverInterface* driver)
+    StreamInWorkerLogic(StreamContext* context, DriverInterface* driver)
         : StreamWorkerCommonLogic(context, driver) {}
 
   protected:
@@ -272,8 +302,9 @@
 class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
   public:
     static const std::string kThreadName;
-    StreamOutWorkerLogic(const StreamContext& context, DriverInterface* driver)
-        : StreamWorkerCommonLogic(context, driver), mEventCallback(context.getOutEventCallback()) {}
+    StreamOutWorkerLogic(StreamContext* context, DriverInterface* driver)
+        : StreamWorkerCommonLogic(context, driver),
+          mEventCallback(context->getOutEventCallback()) {}
 
   protected:
     Status cycle() override;
@@ -285,14 +316,20 @@
 };
 using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;
 
-// This provides a C++ interface with methods of the IStreamCommon Binder interface,
-// but intentionally does not inherit from it. This is needed to avoid inheriting
-// StreamIn and StreamOut from two Binder interface classes, as these parts of the class
-// will be reference counted separately.
-//
-// The implementation of these common methods is in the StreamCommonImpl template class.
+// This interface provides operations of the stream which are executed on a Binder pool thread.
+// These methods originate both from the AIDL interface and its implementation.
 struct StreamCommonInterface {
+    using ConnectedDevices = std::vector<::aidl::android::media::audio::common::AudioDevice>;
+    using Metadata =
+            std::variant<::aidl::android::hardware::audio::common::SinkMetadata /*IStreamIn*/,
+                         ::aidl::android::hardware::audio::common::SourceMetadata /*IStreamOut*/>;
+
+    static constexpr bool isInput(const Metadata& metadata) { return metadata.index() == 0; }
+
     virtual ~StreamCommonInterface() = default;
+    // Methods below originate from the 'IStreamCommon' interface.
+    // This is semantically equivalent to inheriting from 'IStreamCommon' with a benefit
+    // that concrete stream implementations can inherit both from this interface and IStreamIn/Out.
     virtual ndk::ScopedAStatus close() = 0;
     virtual ndk::ScopedAStatus prepareToClose() = 0;
     virtual ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) = 0;
@@ -306,11 +343,31 @@
     virtual ndk::ScopedAStatus removeEffect(
             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&
                     in_effect) = 0;
+    // Methods below are common for both 'IStreamIn' and 'IStreamOut'. Note that
+    // 'updateMetadata' in them uses an individual structure which is wrapped here.
+    // The 'Common' suffix is added to distinguish them from the methods from 'IStreamIn/Out'.
+    virtual ndk::ScopedAStatus getStreamCommonCommon(
+            std::shared_ptr<IStreamCommon>* _aidl_return) = 0;
+    virtual ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) = 0;
+    // Methods below are called by implementation of 'IModule', 'IStreamIn' and 'IStreamOut'.
+    virtual ndk::ScopedAStatus initInstance(
+            const std::shared_ptr<StreamCommonInterface>& delegate) = 0;
+    virtual const StreamContext& getContext() const = 0;
+    virtual bool isClosed() const = 0;
+    virtual const ConnectedDevices& getConnectedDevices() const = 0;
+    virtual ndk::ScopedAStatus setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
+    virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
 };
 
-class StreamCommon : public BnStreamCommon {
+// This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
+// a weak pointer to avoid creating a reference loop. The loop will occur because
+// 'IStreamIn/Out.getStreamCommon' must return the same instance every time, thus
+// the stream implementation must hold a strong pointer to an instance of 'IStreamCommon'.
+// Also, we use 'StreamCommonInterface' here instead of 'IStreamCommon'.
+class StreamCommonDelegator : public BnStreamCommon {
   public:
-    explicit StreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate)
+    explicit StreamCommonDelegator(const std::shared_ptr<StreamCommonInterface>& delegate)
         : mDelegate(delegate) {}
 
   private:
@@ -361,9 +418,21 @@
     std::weak_ptr<StreamCommonInterface> mDelegate;
 };
 
-template <class Metadata>
-class StreamCommonImpl : public StreamCommonInterface {
+// The implementation of DriverInterface must be provided by each concrete stream implementation.
+// Note that StreamCommonImpl does not own the context. This is to support swapping on the fly
+// implementations of the stream while keeping the same IStreamIn/Out instance. It's that instance
+// who must be owner of the context.
+class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface {
   public:
+    StreamCommonImpl(StreamContext* context, const Metadata& metadata,
+                     const StreamWorkerInterface::CreateInstance& createWorker)
+        : mContext(*context), mMetadata(metadata), mWorker(createWorker(context, this)) {}
+    StreamCommonImpl(StreamContext* context, const Metadata& metadata)
+        : StreamCommonImpl(
+                  context, metadata,
+                  isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {}
+    ~StreamCommonImpl();
+
     ndk::ScopedAStatus close() override;
     ndk::ScopedAStatus prepareToClose() override;
     ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
@@ -378,46 +447,53 @@
             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
             override;
 
-    ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return);
-    ndk::ScopedAStatus init() {
-        return mWorker->start() ? ndk::ScopedAStatus::ok()
-                                : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-    }
-    bool isClosed() const { return mWorker->isClosed(); }
-    void setIsConnected(
-            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
-        mWorker->setIsConnected(!devices.empty());
-        mConnectedDevices = devices;
-        mDriver->setConnectedDevices(devices);
-    }
-    ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
+    ndk::ScopedAStatus getStreamCommonCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override;
+    ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+
+    ndk::ScopedAStatus initInstance(
+            const std::shared_ptr<StreamCommonInterface>& delegate) override;
+    const StreamContext& getContext() const override { return mContext; }
+    bool isClosed() const override { return mWorker->isClosed(); }
+    const ConnectedDevices& getConnectedDevices() const override { return mConnectedDevices; }
+    ndk::ScopedAStatus setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
 
   protected:
-    StreamCommonImpl(const Metadata& metadata, StreamContext&& context,
-                     const DriverInterface::CreateInstance& createDriver,
-                     const StreamWorkerInterface::CreateInstance& createWorker)
-        : mMetadata(metadata),
-          mContext(std::move(context)),
-          mDriver(createDriver(mContext)),
-          mWorker(createWorker(mContext, mDriver.get())) {}
-    ~StreamCommonImpl();
-    void stopWorker();
-    void createStreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate);
+    static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
+        return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+            return new StreamInWorker(ctx, driver);
+        };
+    }
+    static StreamWorkerInterface::CreateInstance getDefaultOutWorkerCreator() {
+        return [](StreamContext* ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+            return new StreamOutWorker(ctx, driver);
+        };
+    }
 
-    std::shared_ptr<StreamCommon> mCommon;
-    ndk::SpAIBinder mCommonBinder;
+    virtual void onClose(StreamDescriptor::State statePriorToClosing) = 0;
+    void stopWorker();
+
+    const StreamContext& mContext;
     Metadata mMetadata;
-    StreamContext mContext;
-    std::unique_ptr<DriverInterface> mDriver;
     std::unique_ptr<StreamWorkerInterface> mWorker;
-    std::vector<::aidl::android::media::audio::common::AudioDevice> mConnectedDevices;
+    ChildInterface<StreamCommonDelegator> mCommon;
+    ConnectedDevices mConnectedDevices;
 };
 
-class StreamIn : public StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>,
-                 public BnStreamIn {
+// Note: 'StreamIn/Out' can not be used on their own. Instead, they must be used for defining
+// concrete input/output stream implementations.
+class StreamIn : virtual public StreamCommonInterface, public BnStreamIn {
+  protected:
+    void defaultOnClose();
+
     ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
-        return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>::
-                getStreamCommon(_aidl_return);
+        return getStreamCommonCommon(_aidl_return);
+    }
+    ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
+                                              in_sinkMetadata) override {
+        return updateMetadataCommon(in_sinkMetadata);
     }
     ndk::ScopedAStatus getActiveMicrophones(
             std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
@@ -426,49 +502,40 @@
     ndk::ScopedAStatus setMicrophoneDirection(MicrophoneDirection in_direction) override;
     ndk::ScopedAStatus getMicrophoneFieldDimension(float* _aidl_return) override;
     ndk::ScopedAStatus setMicrophoneFieldDimension(float in_zoom) override;
-    ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
-                                              in_sinkMetadata) override {
-        return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata>::
-                updateMetadata(in_sinkMetadata);
-    }
     ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
     ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
 
-  protected:
     friend class ndk::SharedRefBase;
 
-    static ndk::ScopedAStatus initInstance(const std::shared_ptr<StreamIn>& stream);
-
-    StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-             StreamContext&& context, const DriverInterface::CreateInstance& createDriver,
-             const StreamWorkerInterface::CreateInstance& createWorker,
+    StreamIn(StreamContext&& context,
              const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
-    void createStreamCommon(const std::shared_ptr<StreamIn>& myPtr) {
-        StreamCommonImpl<
-                ::aidl::android::hardware::audio::common::SinkMetadata>::createStreamCommon(myPtr);
-    }
 
+    StreamContext mContextInstance;
     const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
-
-  public:
-    using CreateInstance = std::function<ndk::ScopedAStatus(
-            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            StreamContext&& context,
-            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
-            std::shared_ptr<StreamIn>* result)>;
 };
 
-class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>,
-                  public BnStreamOut {
+class StreamInHwGainHelper {
+  protected:
+    explicit StreamInHwGainHelper(const StreamContext* context);
+
+    ndk::ScopedAStatus getHwGainImpl(std::vector<float>* _aidl_return);
+    ndk::ScopedAStatus setHwGainImpl(const std::vector<float>& in_channelGains);
+
+    const size_t mChannelCount;
+    std::vector<float> mHwGains;
+};
+
+class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
+  protected:
+    void defaultOnClose();
+
     ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
-        return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
-                getStreamCommon(_aidl_return);
+        return getStreamCommonCommon(_aidl_return);
     }
     ndk::ScopedAStatus updateMetadata(
             const ::aidl::android::hardware::audio::common::SourceMetadata& in_sourceMetadata)
             override {
-        return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
-                updateMetadata(in_sourceMetadata);
+        return updateMetadataCommon(in_sourceMetadata);
     }
     ndk::ScopedAStatus updateOffloadMetadata(
             const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&
@@ -493,34 +560,40 @@
             override;
     ndk::ScopedAStatus selectPresentation(int32_t in_presentationId, int32_t in_programId) override;
 
-    void createStreamCommon(const std::shared_ptr<StreamOut>& myPtr) {
-        StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
-                createStreamCommon(myPtr);
-    }
-
-  protected:
     friend class ndk::SharedRefBase;
 
-    static ndk::ScopedAStatus initInstance(const std::shared_ptr<StreamOut>& stream);
-
-    StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-              StreamContext&& context, const DriverInterface::CreateInstance& createDriver,
-              const StreamWorkerInterface::CreateInstance& createWorker,
+    StreamOut(StreamContext&& context,
               const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                       offloadInfo);
 
-    std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
+    StreamContext mContextInstance;
+    const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
     std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
-
-  public:
-    using CreateInstance = std::function<ndk::ScopedAStatus(
-            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-            StreamContext&& context,
-            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
-                    offloadInfo,
-            std::shared_ptr<StreamOut>* result)>;
 };
 
+class StreamOutHwVolumeHelper {
+  protected:
+    explicit StreamOutHwVolumeHelper(const StreamContext* context);
+
+    ndk::ScopedAStatus getHwVolumeImpl(std::vector<float>* _aidl_return);
+    ndk::ScopedAStatus setHwVolumeImpl(const std::vector<float>& in_channelVolumes);
+
+    const size_t mChannelCount;
+    std::vector<float> mHwVolumes;
+};
+
+// The recommended way to create a stream instance.
+// 'StreamImpl' is the concrete stream implementation, 'StreamInOrOut' is either 'StreamIn' or
+// 'StreamOut', the rest are the arguments forwarded to the constructor of 'StreamImpl'.
+template <class StreamImpl, class StreamInOrOut, class... Args>
+ndk::ScopedAStatus createStreamInstance(std::shared_ptr<StreamInOrOut>* result, Args&&... args) {
+    std::shared_ptr<StreamInOrOut> stream =
+            ::ndk::SharedRefBase::make<StreamImpl>(std::forward<Args>(args)...);
+    RETURN_STATUS_IF_ERROR(stream->initInstance(stream));
+    *result = std::move(stream);
+    return ndk::ScopedAStatus::ok();
+}
+
 class StreamWrapper {
   public:
     explicit StreamWrapper(const std::shared_ptr<StreamIn>& streamIn)
@@ -529,25 +602,23 @@
         : mStream(streamOut), mStreamBinder(streamOut->asBinder()) {}
     ndk::SpAIBinder getBinder() const { return mStreamBinder; }
     bool isStreamOpen() const {
-        return std::visit(
-                [](auto&& ws) -> bool {
-                    auto s = ws.lock();
-                    return s && !s->isClosed();
-                },
-                mStream);
+        auto s = mStream.lock();
+        return s && !s->isClosed();
     }
-    void setStreamIsConnected(
+    ndk::ScopedAStatus setConnectedDevices(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
-        std::visit(
-                [&](auto&& ws) {
-                    auto s = ws.lock();
-                    if (s) s->setIsConnected(devices);
-                },
-                mStream);
+        auto s = mStream.lock();
+        if (s) return s->setConnectedDevices(devices);
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus bluetoothParametersUpdated() {
+        auto s = mStream.lock();
+        if (s) return s->bluetoothParametersUpdated();
+        return ndk::ScopedAStatus::ok();
     }
 
   private:
-    std::variant<std::weak_ptr<StreamIn>, std::weak_ptr<StreamOut>> mStream;
+    std::weak_ptr<StreamCommonInterface> mStream;
     ndk::SpAIBinder mStreamBinder;
 };
 
@@ -565,12 +636,21 @@
         mStreams.insert(std::pair{portConfigId, sw});
         mStreams.insert(std::pair{portId, std::move(sw)});
     }
-    void setStreamIsConnected(
+    ndk::ScopedAStatus setStreamConnectedDevices(
             int32_t portConfigId,
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
         if (auto it = mStreams.find(portConfigId); it != mStreams.end()) {
-            it->second.setStreamIsConnected(devices);
+            return it->second.setConnectedDevices(devices);
         }
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus bluetoothParametersUpdated() {
+        bool isOk = true;
+        for (auto& it : mStreams) {
+            if (!it.second.bluetoothParametersUpdated().isOk()) isOk = false;
+        }
+        return isOk ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
 
   private:
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
new file mode 100644
index 0000000..2c3b284
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <optional>
+#include <vector>
+
+#include "Stream.h"
+#include "alsa/Utils.h"
+
+namespace aidl::android::hardware::audio::core {
+
+// This class is intended to be used as a base class for implementations
+// that use TinyAlsa.
+// This class does not define a complete stream implementation,
+// and should never be used on its own. Derived classes are expected to
+// provide necessary overrides for all interface methods omitted here.
+class StreamAlsa : public StreamCommonImpl {
+  public:
+    StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries);
+    // Methods of 'DriverInterface'.
+    ::android::status_t init() override;
+    ::android::status_t drain(StreamDescriptor::DrainMode) override;
+    ::android::status_t flush() override;
+    ::android::status_t pause() override;
+    ::android::status_t standby() override;
+    ::android::status_t start() override;
+    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                 int32_t* latencyMs) override;
+    ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
+    void shutdown() override;
+
+  protected:
+    // Called from 'start' to initialize 'mAlsaDeviceProxies', the vector must be non-empty.
+    virtual std::vector<alsa::DeviceProfile> getDeviceProfiles() = 0;
+
+    const size_t mBufferSizeFrames;
+    const size_t mFrameSizeBytes;
+    const int mSampleRate;
+    const bool mIsInput;
+    const std::optional<struct pcm_config> mConfig;
+    const int mReadWriteRetries;
+    // All fields below are only used on the worker thread.
+    std::vector<alsa::DeviceProxy> mAlsaDeviceProxies;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
new file mode 100644
index 0000000..c2f8c1d
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/IBluetooth.h>
+#include <aidl/android/hardware/audio/core/IBluetoothA2dp.h>
+#include <aidl/android/hardware/audio/core/IBluetoothLe.h>
+
+#include "core-impl/DevicePortProxy.h"
+#include "core-impl/Module.h"
+#include "core-impl/Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamBluetooth : public StreamCommonImpl {
+  public:
+    StreamBluetooth(StreamContext* context, const Metadata& metadata,
+                    Module::BtProfileHandles&& btHandles);
+    // Methods of 'DriverInterface'.
+    ::android::status_t init() override;
+    ::android::status_t drain(StreamDescriptor::DrainMode) override;
+    ::android::status_t flush() override;
+    ::android::status_t pause() override;
+    ::android::status_t standby() override;
+    ::android::status_t start() override;
+    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                 int32_t* latencyMs) override;
+    void shutdown() override;
+
+    // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+    ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+    ndk::ScopedAStatus prepareToClose() override;
+    const ConnectedDevices& getConnectedDevices() const override;
+    ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
+
+  private:
+    // Audio Pcm Config
+    const uint32_t mSampleRate;
+    const ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
+    const ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
+    const size_t mFrameSizeBytes;
+    const bool mIsInput;
+    const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
+    const std::weak_ptr<IBluetoothLe> mBluetoothLe;
+    size_t mPreferredDataIntervalUs;
+    size_t mPreferredFrameCount;
+
+    mutable std::mutex mLock;
+    bool mIsInitialized GUARDED_BY(mLock);
+    bool mIsReadyToClose GUARDED_BY(mLock);
+    std::vector<std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>>
+            mBtDeviceProxies GUARDED_BY(mLock);
+
+    ::android::status_t initialize() REQUIRES(mLock);
+    bool checkConfigParams(::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config);
+};
+
+class StreamInBluetooth final : public StreamIn, public StreamBluetooth {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamInBluetooth(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            Module::BtProfileHandles&& btHandles);
+
+  private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+    ndk::ScopedAStatus getActiveMicrophones(
+            std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+            override;
+};
+
+class StreamOutBluetooth final : public StreamOut, public StreamBluetooth {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamOutBluetooth(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            Module::BtProfileHandles&& btHandles);
+
+  private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
new file mode 100644
index 0000000..b3ddd0b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "StreamAlsa.h"
+#include "StreamSwitcher.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamPrimary : public StreamAlsa {
+  public:
+    StreamPrimary(StreamContext* context, const Metadata& metadata);
+
+  protected:
+    std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
+
+    const bool mIsInput;
+};
+
+class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamInPrimary(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+  private:
+    static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+    ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
+};
+
+class StreamOutPrimary final : public StreamOut,
+                               public StreamSwitcher,
+                               public StreamOutHwVolumeHelper {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamOutPrimary(StreamContext&& context,
+                     const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+                     const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                             offloadInfo);
+
+  private:
+    static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+    ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
new file mode 100644
index 0000000..94404a1
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+#include "core-impl/Stream.h"
+#include "core-impl/StreamSwitcher.h"
+#include "r_submix/SubmixRoute.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamRemoteSubmix : public StreamCommonImpl {
+  public:
+    StreamRemoteSubmix(
+            StreamContext* context, const Metadata& metadata,
+            const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
+
+    ::android::status_t init() override;
+    ::android::status_t drain(StreamDescriptor::DrainMode) override;
+    ::android::status_t flush() override;
+    ::android::status_t pause() override;
+    ::android::status_t standby() override;
+    ::android::status_t start() override;
+    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                 int32_t* latencyMs) override;
+    ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
+    void shutdown() override;
+
+    // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+    ndk::ScopedAStatus prepareToClose() override;
+
+  private:
+    size_t getPipeSizeInFrames();
+    size_t getStreamPipeSizeInFrames();
+    ::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
+    ::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
+
+    const ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress;
+    const bool mIsInput;
+    r_submix::AudioConfig mStreamConfig;
+    std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
+
+    // Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
+    // locks and none of the mutex locks should be taken together.
+    static std::mutex sSubmixRoutesLock;
+    static std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
+                    std::shared_ptr<r_submix::SubmixRoute>>
+            sSubmixRoutes GUARDED_BY(sSubmixRoutesLock);
+
+    // limit for number of read error log entries to avoid spamming the logs
+    static constexpr int kMaxReadErrorLogs = 5;
+    // The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
+    // to the duration of a record buffer at the current record sample rate (of the device, not of
+    // the recording itself). Here we have: 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
+    static constexpr int kMaxReadFailureAttempts = 3;
+    // 5ms between two read attempts when pipe is empty
+    static constexpr int kReadAttemptSleepUs = 5000;
+};
+
+class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamInRemoteSubmix(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+  private:
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+    ndk::ScopedAStatus getActiveMicrophones(
+            std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+            override;
+};
+
+class StreamOutRemoteSubmix final : public StreamOut, public StreamSwitcher {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamOutRemoteSubmix(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo);
+
+  private:
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index df0182c..3857e0e 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -20,58 +20,52 @@
 
 namespace aidl::android::hardware::audio::core {
 
-class DriverStub : public DriverInterface {
+class StreamStub : public StreamCommonImpl {
   public:
-    DriverStub(const StreamContext& context, bool isInput);
+    StreamStub(StreamContext* context, const Metadata& metadata);
+    // Methods of 'DriverInterface'.
     ::android::status_t init() override;
-    ::android::status_t setConnectedDevices(
-            const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
-            override;
     ::android::status_t drain(StreamDescriptor::DrainMode) override;
     ::android::status_t flush() override;
     ::android::status_t pause() override;
+    ::android::status_t standby() override;
+    ::android::status_t start() override;
     ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                  int32_t* latencyMs) override;
-    ::android::status_t standby() override;
+    void shutdown() override;
 
   private:
+    const size_t mBufferSizeFrames;
     const size_t mFrameSizeBytes;
     const int mSampleRate;
     const bool mIsAsynchronous;
     const bool mIsInput;
+    bool mIsInitialized = false;  // Used for validating the state machine logic.
+    bool mIsStandby = true;       // Used for validating the state machine logic.
 };
 
-class StreamInStub final : public StreamIn {
+class StreamInStub final : public StreamIn, public StreamStub {
   public:
-    static ndk::ScopedAStatus createInstance(
-            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            StreamContext&& context,
-            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
-            std::shared_ptr<StreamIn>* result);
-
-  private:
     friend class ndk::SharedRefBase;
     StreamInStub(
+            StreamContext&& context,
             const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            StreamContext&& context,
             const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
-};
-
-class StreamOutStub final : public StreamOut {
-  public:
-    static ndk::ScopedAStatus createInstance(
-            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-            StreamContext&& context,
-            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
-                    offloadInfo,
-            std::shared_ptr<StreamOut>* result);
 
   private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+};
+
+class StreamOutStub final : public StreamOut, public StreamStub {
+  public:
     friend class ndk::SharedRefBase;
-    StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-                  StreamContext&& context,
+    StreamOutStub(StreamContext&& context,
+                  const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
                   const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                           offloadInfo);
+
+  private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/include/core-impl/StreamSwitcher.h
new file mode 100644
index 0000000..5764ad6
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamSwitcher.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+// 'StreamSwitcher' is an implementation of 'StreamCommonInterface' which allows
+// dynamically switching the underlying stream implementation based on currently
+// connected devices. This is achieved by replacing inheritance from
+// 'StreamCommonImpl' with owning an instance of it. StreamSwitcher must be
+// extended in order to supply the logic for choosing the stream
+// implementation. When there are no connected devices, for instance, upon the
+// creation, the StreamSwitcher engages an instance of a stub stream in order to
+// keep serving requests coming via 'StreamDescriptor'.
+//
+// StreamSwitcher implements the 'IStreamCommon' interface directly, with
+// necessary delegation to the current stream implementation. While the stub
+// stream is engaged, any requests made via 'IStreamCommon' (parameters, effects
+// setting, etc) are postponed and only delivered on device connection change
+// to the "real" stream implementation provided by the extending class. This is why
+// the behavior of StreamSwitcher in the "stub" state is not identical to behavior
+// of 'StreamStub'. It can become a full substitute for 'StreamStub' once
+// device connection change event occurs and the extending class returns
+// 'LEAVE_CURRENT_STREAM' from 'switchCurrentStream' method.
+//
+// There is a natural limitation that the current stream implementation may only
+// be switched when the stream is in the 'STANDBY' state. Thus, when the event
+// to switch the stream occurs, the current stream is stopped and joined, and
+// its last state is validated. Since the change of the set of connected devices
+// normally occurs on patch updates, if the stream was not in standby, this is
+// reported to the caller of 'IModule.setAudioPatch' as the 'EX_ILLEGAL_STATE'
+// error.
+//
+// The simplest use case, when the implementor just needs to emulate the legacy HAL API
+// behavior of receiving the connected devices upon stream creation, the implementation
+// of the extending class can look as follows. We assume that 'StreamLegacy' implementation
+// is the one requiring to know connected devices on creation:
+//
+//   class StreamLegacy : public StreamCommonImpl {
+//     public:
+//       StreamLegacy(StreamContext* context, const Metadata& metadata,
+//                    const std::vector<AudioDevice>& devices);
+//   };
+//
+//   class StreamOutLegacy final : public StreamOut, public StreamSwitcher {
+//     public:
+//       StreamOutLegacy(StreamContext&& context, metatadata etc.)
+//     private:
+//       DeviceSwitchBehavior switchCurrentStream(const std::vector<AudioDevice>&) override {
+//           // This implementation effectively postpones stream creation until
+//           // receiving the first call to 'setConnectedDevices' with a non-empty list.
+//           return isStubStream() ? DeviceSwitchBehavior::CREATE_NEW_STREAM :
+//               DeviceSwitchBehavior::USE_CURRENT_STREAM;
+//       }
+//       std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+//               const std::vector<AudioDevice>& devices,
+//               StreamContext* context, const Metadata& metadata) override {
+//           return std::unique_ptr<StreamCommonInterfaceEx>(new InnerStreamWrapper<StreamLegacy>(
+//               context, metadata, devices));
+//       }
+//       void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+//   }
+//
+
+class StreamCommonInterfaceEx : virtual public StreamCommonInterface {
+  public:
+    virtual StreamDescriptor::State getStatePriorToClosing() const = 0;
+};
+
+template <typename T>
+class InnerStreamWrapper : public T, public StreamCommonInterfaceEx {
+  public:
+    template <typename... Args>
+    InnerStreamWrapper(Args&&... args) : T(std::forward<Args>(args)...) {}
+    StreamDescriptor::State getStatePriorToClosing() const override { return mStatePriorToClosing; }
+
+  private:
+    // Do not need to do anything on close notification from the inner stream
+    // because StreamSwitcher handles IStreamCommon::close by itself.
+    void onClose(StreamDescriptor::State statePriorToClosing) override {
+        mStatePriorToClosing = statePriorToClosing;
+    }
+
+    StreamDescriptor::State mStatePriorToClosing = StreamDescriptor::State::STANDBY;
+};
+
+class StreamSwitcher : virtual public StreamCommonInterface {
+  public:
+    StreamSwitcher(StreamContext* context, const Metadata& metadata);
+
+    ndk::ScopedAStatus close() override;
+    ndk::ScopedAStatus prepareToClose() override;
+    ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
+    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+                                           std::vector<VendorParameter>* _aidl_return) override;
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool in_async) override;
+    ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
+    ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
+            override;
+
+    ndk::ScopedAStatus getStreamCommonCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override;
+    ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+
+    ndk::ScopedAStatus initInstance(
+            const std::shared_ptr<StreamCommonInterface>& delegate) override;
+    const StreamContext& getContext() const override;
+    bool isClosed() const override;
+    const ConnectedDevices& getConnectedDevices() const override;
+    ndk::ScopedAStatus setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
+
+  protected:
+    // Since switching a stream requires closing down the current stream, StreamSwitcher
+    // asks the extending class its intent on the connected devices change.
+    enum DeviceSwitchBehavior {
+        // Continue using the current stream implementation. If it's the stub implementation,
+        // StreamSwitcher starts treating the stub stream as a "real" implementation,
+        // without effectively closing it and starting again.
+        USE_CURRENT_STREAM,
+        // This is the normal case when the extending class provides a "real" implementation
+        // which is not a stub implementation.
+        CREATE_NEW_STREAM,
+        // This is the case when the extending class wants to revert back to the initial
+        // condition of using a stub stream provided by the StreamSwitcher. This behavior
+        // is only allowed when the list of connected devices is empty.
+        SWITCH_TO_STUB_STREAM,
+        // Use when the set of devices is not supported by the extending class. This returns
+        // 'EX_UNSUPPORTED_OPERATION' from 'setConnectedDevices'.
+        UNSUPPORTED_DEVICES,
+    };
+    // StreamSwitcher will call these methods from 'setConnectedDevices'. If the switch behavior
+    // is 'CREATE_NEW_STREAM', the 'createwNewStream' function will be called (with the same
+    // device vector) for obtaining a new stream implementation, assuming that closing
+    // the current stream was a success.
+    virtual DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
+    virtual std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) = 0;
+    virtual void onClose(StreamDescriptor::State streamPriorToClosing) = 0;
+
+    bool isStubStream() const { return mIsStubStream; }
+    StreamCommonInterfaceEx* getCurrentStream() const { return mStream.get(); }
+
+  private:
+    using VndParam = std::pair<std::vector<VendorParameter>, bool /*isAsync*/>;
+
+    static constexpr bool isValidClosingStreamState(StreamDescriptor::State state) {
+        return state == StreamDescriptor::State::STANDBY || state == StreamDescriptor::State::ERROR;
+    }
+
+    ndk::ScopedAStatus closeCurrentStream(bool validateStreamState);
+
+    // StreamSwitcher does not own the context.
+    StreamContext* mContext;
+    Metadata mMetadata;
+    ChildInterface<StreamCommonDelegator> mCommon;
+    // The current stream.
+    std::unique_ptr<StreamCommonInterfaceEx> mStream;
+    // Indicates whether 'mCurrentStream' is a stub stream implementation
+    // maintained by StreamSwitcher until the extending class provides a "real"
+    // implementation. The invariant of this state is that there are no connected
+    // devices.
+    bool mIsStubStream = true;
+    // Storage for the data from commands received via 'IStreamCommon'.
+    std::optional<int32_t> mHwAvSyncId;
+    std::vector<VndParam> mMissedParameters;
+    std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
+    bool mBluetoothParametersUpdated = false;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 36e64cb..608f27d 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -16,90 +16,61 @@
 
 #pragma once
 
+#include <atomic>
 #include <mutex>
 #include <vector>
 
 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
 
-#include "core-impl/Stream.h"
-
-extern "C" {
-#include <tinyalsa/pcm.h>
-#include "alsa_device_proxy.h"
-}
+#include "StreamAlsa.h"
 
 namespace aidl::android::hardware::audio::core {
 
-class DriverUsb : public DriverInterface {
+class StreamUsb : public StreamAlsa {
   public:
-    DriverUsb(const StreamContext& context, bool isInput);
-    ::android::status_t init() override;
-    ::android::status_t setConnectedDevices(
-            const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
-            override;
-    ::android::status_t drain(StreamDescriptor::DrainMode) override;
-    ::android::status_t flush() override;
-    ::android::status_t pause() override;
+    StreamUsb(StreamContext* context, const Metadata& metadata);
+    // Methods of 'DriverInterface'.
     ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                  int32_t* latencyMs) override;
-    ::android::status_t standby() override;
 
-  private:
-    ::android::status_t exitStandby();
+    // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+    ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
 
-    std::mutex mLock;
+  protected:
+    std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
 
-    const size_t mFrameSizeBytes;
-    std::optional<struct pcm_config> mConfig;
-    const bool mIsInput;
-    // Cached device addresses for connected devices.
-    std::vector<::aidl::android::media::audio::common::AudioDeviceAddress> mConnectedDevices
-            GUARDED_BY(mLock);
-    std::vector<std::shared_ptr<alsa_device_proxy>> mAlsaDeviceProxies GUARDED_BY(mLock);
-    bool mIsStandby = true;
+    mutable std::mutex mLock;
+    std::vector<alsa::DeviceProfile> mConnectedDeviceProfiles GUARDED_BY(mLock);
+    std::atomic<bool> mConnectedDevicesUpdated = false;
 };
 
-class StreamInUsb final : public StreamIn {
+class StreamInUsb final : public StreamIn, public StreamUsb {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamInUsb(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+  private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
     ndk::ScopedAStatus getActiveMicrophones(
             std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
             override;
-
-  public:
-    static ndk::ScopedAStatus createInstance(
-            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            StreamContext&& context,
-            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
-            std::shared_ptr<StreamIn>* result);
-
-  private:
-    friend class ndk::SharedRefBase;
-    StreamInUsb(
-            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            StreamContext&& context,
-            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
 };
 
-class StreamOutUsb final : public StreamOut {
+class StreamOutUsb final : public StreamOut, public StreamUsb, public StreamOutHwVolumeHelper {
   public:
-    static ndk::ScopedAStatus createInstance(
-            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-            StreamContext&& context,
-            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
-                    offloadInfo,
-            std::shared_ptr<StreamOut>* result);
-
-  private:
     friend class ndk::SharedRefBase;
-    StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
-                 StreamContext&& context,
+    StreamOutUsb(StreamContext&& context,
+                 const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
                  const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                          offloadInfo);
 
+  private:
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
     ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
     ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
-
-    int mChannelCount;
-    std::vector<float> mHwVolumes;
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
index ec23edb..383ea24 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -20,6 +20,7 @@
 #include <string>
 #include <unordered_map>
 
+#include <media/AidlConversionUtil.h>
 #include <system/audio_config.h>
 #include <utils/Errors.h>
 
@@ -52,10 +53,16 @@
                                      const ::android::status_t& status) {
         std::string errorMessage;
         if (status != ::android::OK) {
-            if (!isReadableConfigFile) {
-                errorMessage = "Could not read requested config file:" + configFilePath;
+            if (configFilePath.empty()) {
+                errorMessage = "No audio configuration files found";
+            } else if (!isReadableConfigFile) {
+                errorMessage = std::string("Could not read requested XML config file: \"")
+                                       .append(configFilePath)
+                                       .append("\"");
             } else {
-                errorMessage = "Invalid config file: " + configFilePath;
+                errorMessage = std::string("Invalid XML config file: \"")
+                                       .append(configFilePath)
+                                       .append("\"");
             }
         }
         return errorMessage;
@@ -78,7 +85,7 @@
  *     </Modules>
  */
 template <typename W, typename X, typename A>
-static std::vector<A> convertWrappedCollectionToAidl(
+std::vector<A> convertWrappedCollectionToAidlUnchecked(
         const std::vector<W>& xsdcWrapperTypeVec,
         std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
         std::function<A(const X&)> convertToAidl) {
@@ -100,12 +107,12 @@
 }
 
 template <typename X, typename A>
-static std::vector<A> convertCollectionToAidl(const std::vector<X>& xsdcTypeVec,
-                                              std::function<A(const X&)> convertToAidl) {
+std::vector<A> convertCollectionToAidlUnchecked(const std::vector<X>& xsdcTypeVec,
+                                                std::function<A(const X&)> itemConversion) {
     std::vector<A> resultAidlTypeVec;
     resultAidlTypeVec.reserve(xsdcTypeVec.size());
     std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
-                   convertToAidl);
+                   itemConversion);
     return resultAidlTypeVec;
 }
 
@@ -121,8 +128,7 @@
  *     </Wrapper>
  */
 template <typename W, typename R>
-static std::unordered_map<std::string, R> generateReferenceMap(
-        const std::vector<W>& xsdcWrapperTypeVec) {
+std::unordered_map<std::string, R> generateReferenceMap(const std::vector<W>& xsdcWrapperTypeVec) {
     std::unordered_map<std::string, R> resultMap;
     if (!xsdcWrapperTypeVec.empty()) {
         /*
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 22cdb6b..698e7a5 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -124,11 +124,11 @@
 
     virtual RetCode setCommon(const Parameter::Common& common) {
         mCommon = common;
-        LOG(INFO) << __func__ << mCommon.toString();
+        LOG(VERBOSE) << __func__ << mCommon.toString();
         return RetCode::SUCCESS;
     }
     virtual Parameter::Common getCommon() {
-        LOG(DEBUG) << __func__ << mCommon.toString();
+        LOG(VERBOSE) << __func__ << mCommon.toString();
         return mCommon;
     }
 
diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h
deleted file mode 100644
index b456817..0000000
--- a/audio/aidl/default/include/effect-impl/EffectWorker.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-#pragma once
-#include <algorithm>
-#include <memory>
-#include <mutex>
-#include <string>
-
-#include "EffectContext.h"
-#include "EffectThread.h"
-
-namespace aidl::android::hardware::audio::effect {
-
-std::string toString(RetCode& code);
-
-class EffectWorker : public EffectThread {
-  public:
-    // set effect context for worker, suppose to only happen once here
-    void setContext(std::shared_ptr<EffectContext> context) {
-        std::call_once(mOnceFlag, [&]() { mContext = context; });
-    };
-
-    // handle FMQ and call effect implemented virtual function
-    void process() override {
-        RETURN_VALUE_IF(!mContext, void(), "nullContext");
-        std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
-        std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
-        std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
-
-        // Only this worker will read from input data MQ and write to output data MQ.
-        auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
-        if (readSamples && writeSamples) {
-            auto processSamples = std::min(readSamples, writeSamples);
-            LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write "
-                       << writeSamples << " process " << processSamples;
-
-            auto buffer = mContext->getWorkBuffer();
-            inputMQ->read(buffer, processSamples);
-
-            IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
-            outputMQ->write(buffer, status.fmqProduced);
-            statusMQ->writeBlocking(&status, 1);
-            LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed
-                       << " produced " << status.fmqProduced;
-        } else {
-            // TODO: maybe add some sleep here to avoid busy waiting
-        }
-    }
-
-    // must implement by each effect implementation
-    // TODO: consider if this interface need adjustment to handle in-place processing
-    virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
-
-  private:
-    // make sure the context only set once.
-    std::once_flag mOnceFlag;
-    std::shared_ptr<EffectContext> mContext;
-};
-
-}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
index f8a86e1..344846a 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
@@ -40,14 +40,15 @@
   public:
     explicit EffectConfig(const std::string& file);
 
-    struct LibraryUuid {
+    struct Library {
         std::string name;  // library name
-        ::aidl::android::media::audio::common::AudioUuid uuid;
+        ::aidl::android::media::audio::common::AudioUuid uuid;  // implementation UUID
+        std::optional<::aidl::android::media::audio::common::AudioUuid> type;  // optional type UUID
     };
     // <effects>
     struct EffectLibraries {
-        std::optional<struct LibraryUuid> proxyLibrary;
-        std::vector<struct LibraryUuid> libraries;
+        std::optional<struct Library> proxyLibrary;
+        std::vector<struct Library> libraries;
     };
 
     int getSkippedElements() const { return mSkippedElements; }
@@ -56,7 +57,7 @@
         return mEffectsMap;
     }
 
-    static bool findUuid(const std::string& xmlEffectName,
+    static bool findUuid(const std::pair<std::string, struct EffectLibraries>& effectElem,
                          ::aidl::android::media::audio::common::AudioUuid* uuid);
 
     using ProcessingLibrariesMap = std::map<Processing::Type, std::vector<struct EffectLibraries>>;
@@ -96,8 +97,8 @@
     bool parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml);
 
     // Function to parse effect.library name and effect.uuid from xml
-    bool parseLibraryUuid(const tinyxml2::XMLElement& xml, struct LibraryUuid& libraryUuid,
-                          bool isProxy = false);
+    bool parseLibrary(const tinyxml2::XMLElement& xml, struct Library& library,
+                      bool isProxy = false);
 
     const char* dump(const tinyxml2::XMLElement& element,
                      tinyxml2::XMLPrinter&& printer = {}) const;
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index ad59ca7..d0b8204 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -24,6 +24,7 @@
 #include <vector>
 
 #include <aidl/android/hardware/audio/effect/BnFactory.h>
+#include <android-base/thread_annotations.h>
 #include "EffectConfig.h"
 
 namespace aidl::android::hardware::audio::effect {
@@ -82,9 +83,11 @@
   private:
     const EffectConfig mConfig;
     ~Factory();
+
+    std::mutex mMutex;
     // Set of effect descriptors supported by the devices.
-    std::set<Descriptor> mDescSet;
-    std::set<Descriptor::Identity> mIdentitySet;
+    std::set<Descriptor> mDescSet GUARDED_BY(mMutex);
+    std::set<Descriptor::Identity> mIdentitySet GUARDED_BY(mMutex);
 
     static constexpr int kMapEntryHandleIndex = 0;
     static constexpr int kMapEntryInterfaceIndex = 1;
@@ -94,26 +97,29 @@
                        std::string /* library name */>
             DlEntry;
 
-    std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap;
+    std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap
+            GUARDED_BY(mMutex);
 
     typedef std::pair<aidl::android::media::audio::common::AudioUuid, ndk::SpAIBinder> EffectEntry;
-    std::map<std::weak_ptr<IEffect>, EffectEntry, std::owner_less<>> mEffectMap;
+    std::map<std::weak_ptr<IEffect>, EffectEntry, std::owner_less<>> mEffectMap GUARDED_BY(mMutex);
 
-    ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
-    void cleanupEffectMap();
+    ndk::ScopedAStatus destroyEffectImpl_l(const std::shared_ptr<IEffect>& in_handle)
+            REQUIRES(mMutex);
+    void cleanupEffectMap_l() REQUIRES(mMutex);
     bool openEffectLibrary(const ::aidl::android::media::audio::common::AudioUuid& impl,
                            const std::string& path);
     void createIdentityWithConfig(
-            const EffectConfig::LibraryUuid& configLib,
+            const EffectConfig::Library& configLib,
             const ::aidl::android::media::audio::common::AudioUuid& typeUuidStr,
             const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
 
-    ndk::ScopedAStatus getDescriptorWithUuid(
-            const aidl::android::media::audio::common::AudioUuid& uuid, Descriptor* desc);
+    ndk::ScopedAStatus getDescriptorWithUuid_l(
+            const aidl::android::media::audio::common::AudioUuid& uuid, Descriptor* desc)
+            REQUIRES(mMutex);
 
     void loadEffectLibs();
     /* Get effect_dl_interface_s from library handle */
-    void getDlSyms(DlEntry& entry);
+    void getDlSyms_l(DlEntry& entry) REQUIRES(mMutex);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index af71aa8..a0c0fab 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -16,20 +16,21 @@
 
 #include <cstdlib>
 #include <ctime>
+#include <sstream>
 #include <utility>
+#include <vector>
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
 #include "core-impl/Config.h"
 #include "core-impl/Module.h"
-#include "core-impl/ModuleUsb.h"
 
 using aidl::android::hardware::audio::core::Config;
 using aidl::android::hardware::audio::core::Module;
-using aidl::android::hardware::audio::core::ModuleUsb;
 
 int main() {
     // Random values are used in the implementation.
@@ -52,18 +53,21 @@
     CHECK_EQ(STATUS_OK, status);
 
     // Make modules
-    auto createModule = [](Module::Type type, const std::string& instance) {
+    auto createModule = [](Module::Type type) {
         auto module = Module::createInstance(type);
         ndk::SpAIBinder moduleBinder = module->asBinder();
-        const std::string moduleName = std::string(Module::descriptor).append("/").append(instance);
+        std::stringstream moduleName;
+        moduleName << Module::descriptor << "/" << type;
         AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
-        binder_status_t status = AServiceManager_addService(moduleBinder.get(), moduleName.c_str());
+        binder_status_t status =
+                AServiceManager_addService(moduleBinder.get(), moduleName.str().c_str());
         CHECK_EQ(STATUS_OK, status);
         return std::make_pair(module, moduleBinder);
     };
-    auto modules = {createModule(Module::Type::DEFAULT, "default"),
-                    createModule(Module::Type::R_SUBMIX, "r_submix"),
-                    createModule(Module::Type::USB, "usb")};
+    auto modules = {createModule(Module::Type::DEFAULT), createModule(Module::Type::R_SUBMIX),
+                    createModule(Module::Type::USB), createModule(Module::Type::STUB),
+                    createModule(Module::Type::BLUETOOTH)};
+    (void)modules;
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/automotive/vehicle/aidl/impl/utils/test/Android.bp b/audio/aidl/default/primary/PrimaryMixer.cpp
similarity index 61%
copy from automotive/vehicle/aidl/impl/utils/test/Android.bp
copy to audio/aidl/default/primary/PrimaryMixer.cpp
index ad9954f..577d010 100644
--- a/automotive/vehicle/aidl/impl/utils/test/Android.bp
+++ b/audio/aidl/default/primary/PrimaryMixer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
+#define LOG_TAG "AHAL_PrimaryMixer"
+
+#include "PrimaryMixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+// static
+PrimaryMixer& PrimaryMixer::getInstance() {
+    static PrimaryMixer gInstance;
+    return gInstance;
 }
 
-cc_library_headers {
-    name: "VehicleHalTestUtilHeaders",
-    vendor: true,
-    header_libs: ["VehicleHalUtilHeaders"],
-    export_include_dirs: ["include"],
-}
+}  // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/PrimaryMixer.h b/audio/aidl/default/primary/PrimaryMixer.h
new file mode 100644
index 0000000..3806428
--- /dev/null
+++ b/audio/aidl/default/primary/PrimaryMixer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+
+#include "alsa/Mixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+class PrimaryMixer : public alsa::Mixer {
+  public:
+    static constexpr int kAlsaCard = 0;
+    static constexpr int kAlsaDevice = 0;
+
+    static PrimaryMixer& getInstance();
+
+  private:
+    PrimaryMixer() : alsa::Mixer(kAlsaCard) {}
+};
+
+}  // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
new file mode 100644
index 0000000..e01be8a
--- /dev/null
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2023 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 <limits>
+
+#define LOG_TAG "AHAL_StreamPrimary"
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <error/expected_utils.h>
+
+#include "PrimaryMixer.h"
+#include "core-impl/StreamPrimary.h"
+#include "core-impl/StreamStub.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+using android::base::GetBoolProperty;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
+    : StreamAlsa(context, metadata, 3 /*readWriteRetries*/), mIsInput(isInput(metadata)) {}
+
+std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
+    static const std::vector<alsa::DeviceProfile> kBuiltInSource{
+            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+                                .device = primary::PrimaryMixer::kAlsaDevice,
+                                .direction = PCM_IN,
+                                .isExternal = false}};
+    static const std::vector<alsa::DeviceProfile> kBuiltInSink{
+            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+                                .device = primary::PrimaryMixer::kAlsaDevice,
+                                .direction = PCM_OUT,
+                                .isExternal = false}};
+    return mIsInput ? kBuiltInSource : kBuiltInSink;
+}
+
+StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
+                                 const std::vector<MicrophoneInfo>& microphones)
+    : StreamIn(std::move(context), microphones),
+      StreamSwitcher(&mContextInstance, sinkMetadata),
+      StreamInHwGainHelper(&mContextInstance) {}
+
+bool StreamInPrimary::useStubStream(const AudioDevice& device) {
+    static const bool kSimulateInput =
+            GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
+    return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
+           device.type.type == AudioDeviceType::IN_FM_TUNER ||
+           device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    LOG(DEBUG) << __func__;
+    if (devices.size() > 1) {
+        LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+                   << devices.size();
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+        return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+    }
+    return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    if (devices.empty()) {
+        LOG(FATAL) << __func__ << ": called with empty devices";  // see 'switchCurrentStream'
+    }
+    if (useStubStream(devices[0])) {
+        return std::unique_ptr<StreamCommonInterfaceEx>(
+                new InnerStreamWrapper<StreamStub>(context, metadata));
+    }
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
+    if (isStubStream()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    return getHwGainImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamInPrimary::setHwGain(const std::vector<float>& in_channelGains) {
+    if (isStubStream()) {
+        LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    auto currentGains = mHwGains;
+    RETURN_STATUS_IF_ERROR(setHwGainImpl(in_channelGains));
+    if (in_channelGains.size() < 1) {
+        LOG(FATAL) << __func__ << ": unexpected gain vector size: " << in_channelGains.size();
+    }
+    if (auto status = primary::PrimaryMixer::getInstance().setMicGain(in_channelGains[0]);
+        !status.isOk()) {
+        mHwGains = currentGains;
+        return status;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata,
+                                   const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamOut(std::move(context), offloadInfo),
+      StreamSwitcher(&mContextInstance, sourceMetadata),
+      StreamOutHwVolumeHelper(&mContextInstance) {}
+
+bool StreamOutPrimary::useStubStream(const AudioDevice& device) {
+    static const bool kSimulateOutput =
+            GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
+    return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
+           device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    LOG(DEBUG) << __func__;
+    if (devices.size() > 1) {
+        LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+                   << devices.size();
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+        return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+    }
+    return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    if (devices.empty()) {
+        LOG(FATAL) << __func__ << ": called with empty devices";  // see 'switchCurrentStream'
+    }
+    if (useStubStream(devices[0])) {
+        return std::unique_ptr<StreamCommonInterfaceEx>(
+                new InnerStreamWrapper<StreamStub>(context, metadata));
+    }
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {
+    if (isStubStream()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    return getHwVolumeImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamOutPrimary::setHwVolume(const std::vector<float>& in_channelVolumes) {
+    if (isStubStream()) {
+        LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    auto currentVolumes = mHwVolumes;
+    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
+    if (auto status = primary::PrimaryMixer::getInstance().setVolumes(in_channelVolumes);
+        !status.isOk()) {
+        mHwVolumes = currentVolumes;
+        return status;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
new file mode 100644
index 0000000..adea877
--- /dev/null
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_ModuleRemoteSubmix"
+
+#include <vector>
+
+#include <android-base/logging.h>
+#include <error/expected_utils.h>
+
+#include "core-impl/ModuleRemoteSubmix.h"
+#include "core-impl/StreamRemoteSubmix.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::setMicMute(bool in_mute __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
+        StreamContext&& context, const SinkMetadata& sinkMetadata,
+        const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+    return createStreamInstance<StreamInRemoteSubmix>(result, std::move(context), sinkMetadata,
+                                                      microphones);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
+        StreamContext&& context, const SourceMetadata& sourceMetadata,
+        const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+    return createStreamInstance<StreamOutRemoteSubmix>(result, std::move(context), sourceMetadata,
+                                                       offloadInfo);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
+    // Find the corresponding mix port and copy its profiles.
+    std::vector<AudioRoute> routes;
+    // At this moment, the port has the same ID as the template port, see connectExternalDevice.
+    RETURN_STATUS_IF_ERROR(getAudioRoutesForAudioPort(audioPort->id, &routes));
+    if (routes.empty()) {
+        LOG(ERROR) << __func__ << ": no routes found for the port " << audioPort->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& route = *routes.begin();
+    AudioPort mixPort;
+    if (route.sinkPortId == audioPort->id) {
+        if (route.sourcePortIds.empty()) {
+            LOG(ERROR) << __func__ << ": invalid route " << route.toString();
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        RETURN_STATUS_IF_ERROR(getAudioPort(*route.sourcePortIds.begin(), &mixPort));
+    } else {
+        RETURN_STATUS_IF_ERROR(getAudioPort(route.sinkPortId, &mixPort));
+    }
+    audioPort->profiles = mixPort.profiles;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::checkAudioPatchEndpointsMatch(
+        const std::vector<AudioPortConfig*>& sources, const std::vector<AudioPortConfig*>& sinks) {
+    for (const auto& source : sources) {
+        for (const auto& sink : sinks) {
+            if (source->sampleRate != sink->sampleRate ||
+                source->channelMask != sink->channelMask || source->format != sink->format) {
+                LOG(ERROR) << __func__
+                           << ": mismatch port configuration, source=" << source->toString()
+                           << ", sink=" << sink->toString();
+                return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+            }
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::onMasterMuteChanged(bool __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleRemoteSubmix::onMasterVolumeChanged(float __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
new file mode 100644
index 0000000..3134b86
--- /dev/null
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_StreamRemoteSubmix"
+#include <android-base/logging.h>
+
+#include <cmath>
+
+#include "core-impl/StreamRemoteSubmix.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata,
+                                       const AudioDeviceAddress& deviceAddress)
+    : StreamCommonImpl(context, metadata),
+      mDeviceAddress(deviceAddress),
+      mIsInput(isInput(metadata)) {
+    mStreamConfig.frameSize = context->getFrameSize();
+    mStreamConfig.format = context->getFormat();
+    mStreamConfig.channelLayout = context->getChannelLayout();
+    mStreamConfig.sampleRate = context->getSampleRate();
+}
+
+std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
+std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
+
+::android::status_t StreamRemoteSubmix::init() {
+    {
+        std::lock_guard guard(sSubmixRoutesLock);
+        auto routeItr = sSubmixRoutes.find(mDeviceAddress);
+        if (routeItr != sSubmixRoutes.end()) {
+            mCurrentRoute = routeItr->second;
+        }
+    }
+    // If route is not available for this port, add it.
+    if (mCurrentRoute == nullptr) {
+        // Initialize the pipe.
+        mCurrentRoute = std::make_shared<SubmixRoute>();
+        if (::android::OK != mCurrentRoute->createPipe(mStreamConfig)) {
+            LOG(ERROR) << __func__ << ": create pipe failed";
+            return ::android::NO_INIT;
+        }
+        {
+            std::lock_guard guard(sSubmixRoutesLock);
+            sSubmixRoutes.emplace(mDeviceAddress, mCurrentRoute);
+        }
+    } else {
+        if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
+            LOG(ERROR) << __func__ << ": invalid stream config";
+            return ::android::NO_INIT;
+        }
+        sp<MonoPipe> sink = mCurrentRoute->getSink();
+        if (sink == nullptr) {
+            LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
+            return ::android::NO_INIT;
+        }
+        // If the sink has been shutdown or pipe recreation is forced, delete the pipe and
+        // recreate it.
+        if (sink->isShutdown()) {
+            LOG(DEBUG) << __func__ << ": Non-nullptr shut down sink when opening stream";
+            if (::android::OK != mCurrentRoute->resetPipe()) {
+                LOG(ERROR) << __func__ << ": reset pipe failed";
+                return ::android::NO_INIT;
+            }
+        }
+    }
+
+    mCurrentRoute->openStream(mIsInput);
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::flush() {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::pause() {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::standby() {
+    mCurrentRoute->standby(mIsInput);
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::start() {
+    mCurrentRoute->exitStandby(mIsInput);
+    return ::android::OK;
+}
+
+ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
+    if (!mIsInput) {
+        std::shared_ptr<SubmixRoute> route = nullptr;
+        {
+            std::lock_guard guard(sSubmixRoutesLock);
+            auto routeItr = sSubmixRoutes.find(mDeviceAddress);
+            if (routeItr != sSubmixRoutes.end()) {
+                route = routeItr->second;
+            }
+        }
+        if (route != nullptr) {
+            sp<MonoPipe> sink = route->getSink();
+            if (sink == nullptr) {
+                ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+            }
+            LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
+
+            sink->shutdown(true);
+        } else {
+            LOG(DEBUG) << __func__ << ": stream already closed.";
+            ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+// Remove references to the specified input and output streams.  When the device no longer
+// references input and output streams destroy the associated pipe.
+void StreamRemoteSubmix::shutdown() {
+    mCurrentRoute->closeStream(mIsInput);
+    // If all stream instances are closed, we can remove route information for this port.
+    if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
+        mCurrentRoute->releasePipe();
+        LOG(DEBUG) << __func__ << ": pipe destroyed";
+
+        std::lock_guard guard(sSubmixRoutesLock);
+        sSubmixRoutes.erase(mDeviceAddress);
+    }
+    mCurrentRoute.reset();
+}
+
+::android::status_t StreamRemoteSubmix::transfer(void* buffer, size_t frameCount,
+                                                 size_t* actualFrameCount, int32_t* latencyMs) {
+    *latencyMs = (getStreamPipeSizeInFrames() * MILLIS_PER_SECOND) / mStreamConfig.sampleRate;
+    LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
+
+    sp<MonoPipe> sink = mCurrentRoute->getSink();
+    if (sink != nullptr) {
+        if (sink->isShutdown()) {
+            sink.clear();
+            LOG(VERBOSE) << __func__ << ": pipe shutdown, ignoring the transfer.";
+            // the pipe has already been shutdown, this buffer will be lost but we must simulate
+            // timing so we don't drain the output faster than realtime
+            const size_t delayUs = static_cast<size_t>(
+                    std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+            usleep(delayUs);
+
+            *actualFrameCount = frameCount;
+            return ::android::OK;
+        }
+    } else {
+        LOG(ERROR) << __func__ << ": transfer without a pipe!";
+        return ::android::UNEXPECTED_NULL;
+    }
+
+    return (mIsInput ? inRead(buffer, frameCount, actualFrameCount)
+                     : outWrite(buffer, frameCount, actualFrameCount));
+}
+
+::android::status_t StreamRemoteSubmix::refinePosition(StreamDescriptor::Position* position) {
+    sp<MonoPipeReader> source = mCurrentRoute->getSource();
+    if (source == nullptr) {
+        return ::android::NO_INIT;
+    }
+    const ssize_t framesInPipe = source->availableToRead();
+    if (framesInPipe < 0) {
+        return ::android::INVALID_OPERATION;
+    }
+    if (mIsInput) {
+        position->frames += framesInPipe;
+    } else {
+        if (position->frames > framesInPipe) {
+            position->frames -= framesInPipe;
+        } else {
+            position->frames = 0;
+        }
+    }
+    return ::android::OK;
+}
+
+// Calculate the maximum size of the pipe buffer in frames for the specified stream.
+size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
+    auto pipeConfig = mCurrentRoute->mPipeConfig;
+    const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
+    return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
+}
+
+::android::status_t StreamRemoteSubmix::outWrite(void* buffer, size_t frameCount,
+                                                 size_t* actualFrameCount) {
+    sp<MonoPipe> sink = mCurrentRoute->getSink();
+    if (sink != nullptr) {
+        if (sink->isShutdown()) {
+            sink.clear();
+            LOG(VERBOSE) << __func__ << ": pipe shutdown, ignoring the write.";
+            // the pipe has already been shutdown, this buffer will be lost but we must
+            // simulate timing so we don't drain the output faster than realtime
+            const size_t delayUs = static_cast<size_t>(
+                    std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+            usleep(delayUs);
+            *actualFrameCount = frameCount;
+            return ::android::OK;
+        }
+    } else {
+        LOG(FATAL) << __func__ << ": without a pipe!";
+        return ::android::UNKNOWN_ERROR;
+    }
+
+    const size_t availableToWrite = sink->availableToWrite();
+    // NOTE: sink has been checked above and sink and source life cycles are synchronized
+    sp<MonoPipeReader> source = mCurrentRoute->getSource();
+    // If the write to the sink should be blocked, flush enough frames from the pipe to make space
+    // to write the most recent data.
+    if (!mCurrentRoute->shouldBlockWrite() && availableToWrite < frameCount) {
+        static uint8_t flushBuffer[64];
+        const size_t flushBufferSizeFrames = sizeof(flushBuffer) / mStreamConfig.frameSize;
+        size_t framesToFlushFromSource = frameCount - availableToWrite;
+        LOG(VERBOSE) << __func__ << ": flushing " << framesToFlushFromSource
+                     << " frames from the pipe to avoid blocking";
+        while (framesToFlushFromSource) {
+            const size_t flushSize = std::min(framesToFlushFromSource, flushBufferSizeFrames);
+            framesToFlushFromSource -= flushSize;
+            // read does not block
+            source->read(flushBuffer, flushSize);
+        }
+    }
+
+    ssize_t writtenFrames = sink->write(buffer, frameCount);
+    if (writtenFrames < 0) {
+        if (writtenFrames == (ssize_t)::android::NEGOTIATE) {
+            LOG(ERROR) << __func__ << ": write to pipe returned NEGOTIATE";
+            sink.clear();
+            *actualFrameCount = 0;
+            return ::android::UNKNOWN_ERROR;
+        } else {
+            // write() returned UNDERRUN or WOULD_BLOCK, retry
+            LOG(ERROR) << __func__ << ": write to pipe returned unexpected " << writtenFrames;
+            writtenFrames = sink->write(buffer, frameCount);
+        }
+    }
+    sink.clear();
+
+    if (writtenFrames < 0) {
+        LOG(ERROR) << __func__ << ": failed writing to pipe with " << writtenFrames;
+        *actualFrameCount = 0;
+        return ::android::UNKNOWN_ERROR;
+    }
+    LOG(VERBOSE) << __func__ << ": wrote " << writtenFrames << "frames";
+    *actualFrameCount = writtenFrames;
+    return ::android::OK;
+}
+
+::android::status_t StreamRemoteSubmix::inRead(void* buffer, size_t frameCount,
+                                               size_t* actualFrameCount) {
+    // about to read from audio source
+    sp<MonoPipeReader> source = mCurrentRoute->getSource();
+    if (source == nullptr || source->availableToRead() == 0) {
+        if (source == nullptr) {
+            int readErrorCount = mCurrentRoute->notifyReadError();
+            if (readErrorCount < kMaxReadErrorLogs) {
+                LOG(ERROR) << __func__
+                           << ": no audio pipe yet we're trying to read! (not all errors will be "
+                              "logged)";
+            } else {
+                LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
+            }
+        } else {
+            LOG(INFO) << __func__ << ": no data to read yet, providing empty data";
+        }
+        const size_t delayUs = static_cast<size_t>(
+                std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
+        usleep(delayUs);
+        memset(buffer, 0, mStreamConfig.frameSize * frameCount);
+        *actualFrameCount = frameCount;
+        return ::android::OK;
+    }
+
+    // read the data from the pipe
+    int attempts = 0;
+    const size_t delayUs = static_cast<size_t>(std::roundf(kReadAttemptSleepUs));
+    char* buff = (char*)buffer;
+    size_t remainingFrames = frameCount;
+
+    while ((remainingFrames > 0) && (attempts < kMaxReadFailureAttempts)) {
+        LOG(VERBOSE) << __func__ << ": frames available to read " << source->availableToRead();
+
+        ssize_t framesRead = source->read(buff, remainingFrames);
+
+        LOG(VERBOSE) << __func__ << ": frames read " << framesRead;
+
+        if (framesRead > 0) {
+            remainingFrames -= framesRead;
+            buff += framesRead * mStreamConfig.frameSize;
+            LOG(VERBOSE) << __func__ << ": (attempts = " << attempts << ") got " << framesRead
+                         << " frames, remaining=" << remainingFrames;
+        } else {
+            attempts++;
+            LOG(WARNING) << __func__ << ": read returned " << framesRead
+                         << " , read failure attempts = " << attempts;
+            usleep(delayUs);
+        }
+    }
+    // done using the source
+    source.clear();
+
+    if (remainingFrames > 0) {
+        const size_t remainingBytes = remainingFrames * mStreamConfig.frameSize;
+        LOG(VERBOSE) << __func__ << ": clearing remaining_frames = " << remainingFrames;
+        memset(((char*)buffer) + (mStreamConfig.frameSize * frameCount) - remainingBytes, 0,
+               remainingBytes);
+    }
+
+    long readCounterFrames = mCurrentRoute->updateReadCounterFrames(frameCount);
+    *actualFrameCount = frameCount;
+
+    // compute how much we need to sleep after reading the data by comparing the wall clock with
+    //   the projected time at which we should return.
+    // wall clock after reading from the pipe
+    auto recordDurationUs = std::chrono::steady_clock::now() - mCurrentRoute->getRecordStartTime();
+
+    // readCounterFrames contains the number of frames that have been read since the beginning of
+    // recording (including this call): it's converted to usec and compared to how long we've been
+    // recording for, which gives us how long we must wait to sync the projected recording time, and
+    // the observed recording time.
+    const int projectedVsObservedOffsetUs =
+            std::roundf((readCounterFrames * MICROS_PER_SECOND / mStreamConfig.sampleRate) -
+                        recordDurationUs.count());
+
+    LOG(VERBOSE) << __func__ << ": record duration " << recordDurationUs.count()
+                 << " microseconds, will wait: " << projectedVsObservedOffsetUs << " microseconds";
+    if (projectedVsObservedOffsetUs > 0) {
+        usleep(projectedVsObservedOffsetUs);
+    }
+    return ::android::OK;
+}
+
+StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
+                                           const SinkMetadata& sinkMetadata,
+                                           const std::vector<MicrophoneInfo>& microphones)
+    : StreamIn(std::move(context), microphones), StreamSwitcher(&mContextInstance, sinkMetadata) {}
+
+ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
+        std::vector<MicrophoneDynamicInfo>* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": not supported";
+    *_aidl_return = std::vector<MicrophoneDynamicInfo>();
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamInRemoteSubmix::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    // This implementation effectively postpones stream creation until
+    // receiving the first call to 'setConnectedDevices' with a non-empty list.
+    if (isStubStream()) {
+        if (devices.size() == 1) {
+            auto deviceDesc = devices.front().type;
+            if (deviceDesc.type ==
+                ::aidl::android::media::audio::common::AudioDeviceType::IN_SUBMIX) {
+                return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+            }
+            LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+                       << " not supported";
+        } else {
+            LOG(ERROR) << __func__ << ": Only single device supported.";
+        }
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInRemoteSubmix::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
+
+StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
+                                             const SourceMetadata& sourceMetadata,
+                                             const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamOut(std::move(context), offloadInfo),
+      StreamSwitcher(&mContextInstance, sourceMetadata) {}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutRemoteSubmix::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    // This implementation effectively postpones stream creation until
+    // receiving the first call to 'setConnectedDevices' with a non-empty list.
+    if (isStubStream()) {
+        if (devices.size() == 1) {
+            auto deviceDesc = devices.front().type;
+            if (deviceDesc.type ==
+                ::aidl::android::media::audio::common::AudioDeviceType::OUT_SUBMIX) {
+                return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+            }
+            LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+                       << " not supported";
+        } else {
+            LOG(ERROR) << __func__ << ": Only single device supported.";
+        }
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutRemoteSubmix::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
new file mode 100644
index 0000000..ddac64d
--- /dev/null
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2023 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_TAG "AHAL_SubmixRoute"
+#include <android-base/logging.h>
+#include <media/AidlConversionCppNdk.h>
+
+#include <Utils.h>
+
+#include "SubmixRoute.h"
+
+using aidl::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+// Verify a submix input or output stream can be opened.
+bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
+    // If the stream is already open, don't open it again.
+    // ENABLE_LEGACY_INPUT_OPEN is default behaviour
+    if (!isInput && isStreamOutOpen()) {
+        LOG(ERROR) << __func__ << ": output stream already open.";
+        return false;
+    }
+    // If either stream is open, verify the existing pipe config matches the stream config.
+    if (hasAtleastOneStreamOpen() && !isStreamConfigCompatible(streamConfig)) {
+        return false;
+    }
+    return true;
+}
+
+// Compare this stream config with existing pipe config, returning false if they do *not*
+// match, true otherwise.
+bool SubmixRoute::isStreamConfigCompatible(const AudioConfig& streamConfig) {
+    if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
+        LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
+                   << streamConfig.channelLayout.toString()
+                   << " pipe config channels = " << mPipeConfig.channelLayout.toString();
+        return false;
+    }
+    if (streamConfig.sampleRate != mPipeConfig.sampleRate) {
+        LOG(ERROR) << __func__
+                   << ": sample rate mismatch, stream sample rate = " << streamConfig.sampleRate
+                   << " pipe config sample rate = " << mPipeConfig.sampleRate;
+        return false;
+    }
+    if (streamConfig.format != mPipeConfig.format) {
+        LOG(ERROR) << __func__
+                   << ": format mismatch, stream format = " << streamConfig.format.toString()
+                   << " pipe config format = " << mPipeConfig.format.toString();
+        return false;
+    }
+    return true;
+}
+
+bool SubmixRoute::hasAtleastOneStreamOpen() {
+    std::lock_guard guard(mLock);
+    return (mStreamInOpen || mStreamOutOpen);
+}
+
+// We DO NOT block if:
+// - no peer input stream is present
+// - the peer input is in standby AFTER having been active.
+// We DO block if:
+// - the input was never activated to avoid discarding first frames in the pipe in case capture
+// start was delayed
+bool SubmixRoute::shouldBlockWrite() {
+    std::lock_guard guard(mLock);
+    return (mStreamInOpen || (mStreamInStandby && (mReadCounterFrames != 0)));
+}
+
+int SubmixRoute::notifyReadError() {
+    std::lock_guard guard(mLock);
+    return ++mReadErrorCount;
+}
+
+long SubmixRoute::updateReadCounterFrames(size_t frameCount) {
+    std::lock_guard guard(mLock);
+    mReadCounterFrames += frameCount;
+    return mReadCounterFrames;
+}
+
+void SubmixRoute::openStream(bool isInput) {
+    std::lock_guard guard(mLock);
+    if (isInput) {
+        if (mStreamInOpen) {
+            mInputRefCount++;
+        } else {
+            mInputRefCount = 1;
+            mStreamInOpen = true;
+        }
+        mStreamInStandby = true;
+        mReadCounterFrames = 0;
+        mReadErrorCount = 0;
+    } else {
+        mStreamOutOpen = true;
+    }
+}
+
+void SubmixRoute::closeStream(bool isInput) {
+    std::lock_guard guard(mLock);
+    if (isInput) {
+        mInputRefCount--;
+        if (mInputRefCount == 0) {
+            mStreamInOpen = false;
+            if (mSink != nullptr) {
+                mSink->shutdown(true);
+            }
+        }
+    } else {
+        mStreamOutOpen = false;
+    }
+}
+
+// If SubmixRoute doesn't exist for a port, create a pipe for the submix audio device of size
+// buffer_size_frames and store config of the submix audio device.
+::android::status_t SubmixRoute::createPipe(const AudioConfig& streamConfig) {
+    const int channelCount = getChannelCount(streamConfig.channelLayout);
+    const audio_format_t audioFormat = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioFormatDescription_audio_format_t(streamConfig.format));
+    const ::android::NBAIO_Format format =
+            ::android::Format_from_SR_C(streamConfig.sampleRate, channelCount, audioFormat);
+    const ::android::NBAIO_Format offers[1] = {format};
+    size_t numCounterOffers = 0;
+
+    const size_t pipeSizeInFrames =
+            r_submix::kDefaultPipeSizeInFrames *
+            ((float)streamConfig.sampleRate / r_submix::kDefaultSampleRateHz);
+    LOG(VERBOSE) << __func__ << ": creating pipe, rate : " << streamConfig.sampleRate
+                 << ", pipe size : " << pipeSizeInFrames;
+
+    // Create a MonoPipe with optional blocking set to true.
+    sp<MonoPipe> sink = sp<MonoPipe>::make(pipeSizeInFrames, format, true /*writeCanBlock*/);
+    if (sink == nullptr) {
+        LOG(FATAL) << __func__ << ": sink is null";
+        return ::android::UNEXPECTED_NULL;
+    }
+
+    // Negotiation between the source and sink cannot fail as the device open operation
+    // creates both ends of the pipe using the same audio format.
+    ssize_t index = sink->negotiate(offers, 1, nullptr, numCounterOffers);
+    if (index != 0) {
+        LOG(FATAL) << __func__ << ": Negotiation for the sink failed, index = " << index;
+        return ::android::BAD_INDEX;
+    }
+    sp<MonoPipeReader> source = sp<MonoPipeReader>::make(sink.get());
+    if (source == nullptr) {
+        LOG(FATAL) << __func__ << ": source is null";
+        return ::android::UNEXPECTED_NULL;
+    }
+    numCounterOffers = 0;
+    index = source->negotiate(offers, 1, nullptr, numCounterOffers);
+    if (index != 0) {
+        LOG(FATAL) << __func__ << ": Negotiation for the source failed, index = " << index;
+        return ::android::BAD_INDEX;
+    }
+    LOG(VERBOSE) << __func__ << ": created pipe";
+
+    mPipeConfig = streamConfig;
+    mPipeConfig.frameCount = sink->maxFrames();
+
+    LOG(VERBOSE) << __func__ << ": Pipe frame size : " << mPipeConfig.frameSize
+                 << ", pipe frames : " << mPipeConfig.frameCount;
+
+    // Save references to the source and sink.
+    {
+        std::lock_guard guard(mLock);
+        mSink = std::move(sink);
+        mSource = std::move(source);
+    }
+
+    return ::android::OK;
+}
+
+// Release references to the sink and source.
+void SubmixRoute::releasePipe() {
+    std::lock_guard guard(mLock);
+    mSink.clear();
+    mSource.clear();
+}
+
+::android::status_t SubmixRoute::resetPipe() {
+    releasePipe();
+    return createPipe(mPipeConfig);
+}
+
+void SubmixRoute::standby(bool isInput) {
+    std::lock_guard guard(mLock);
+
+    if (isInput) {
+        mStreamInStandby = true;
+    } else if (!mStreamOutStandby) {
+        mStreamOutStandby = true;
+        mStreamOutStandbyTransition = true;
+    }
+}
+
+void SubmixRoute::exitStandby(bool isInput) {
+    std::lock_guard guard(mLock);
+
+    if (isInput) {
+        if (mStreamInStandby || mStreamOutStandbyTransition) {
+            mStreamInStandby = false;
+            mStreamOutStandbyTransition = false;
+            // keep track of when we exit input standby (== first read == start "real recording")
+            // or when we start recording silence, and reset projected time
+            mRecordStartTime = std::chrono::steady_clock::now();
+            mReadCounterFrames = 0;
+        }
+    } else {
+        if (mStreamOutStandby) {
+            mStreamOutStandby = false;
+            mStreamOutStandbyTransition = true;
+        }
+    }
+}
+
+}  // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
new file mode 100644
index 0000000..1a98df2
--- /dev/null
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 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 <mutex>
+
+#include <audio_utils/clock.h>
+
+#include <media/nbaio/MonoPipe.h>
+#include <media/nbaio/MonoPipeReader.h>
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+
+#include "core-impl/Stream.h"
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::PcmType;
+using ::android::MonoPipe;
+using ::android::MonoPipeReader;
+using ::android::sp;
+
+namespace aidl::android::hardware::audio::core::r_submix {
+
+static constexpr int kDefaultSampleRateHz = 48000;
+// Size at default sample rate
+// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe().
+static constexpr int kDefaultPipeSizeInFrames = (1024 * 4);
+
+// Configuration of the audio stream.
+struct AudioConfig {
+    int sampleRate = kDefaultSampleRateHz;
+    AudioFormatDescription format =
+            AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
+    AudioChannelLayout channelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO);
+    size_t frameSize;
+    size_t frameCount;
+};
+
+class SubmixRoute {
+  public:
+    AudioConfig mPipeConfig;
+
+    bool isStreamInOpen() {
+        std::lock_guard guard(mLock);
+        return mStreamInOpen;
+    }
+    bool getStreamInStandby() {
+        std::lock_guard guard(mLock);
+        return mStreamInStandby;
+    }
+    bool isStreamOutOpen() {
+        std::lock_guard guard(mLock);
+        return mStreamOutOpen;
+    }
+    bool getStreamOutStandby() {
+        std::lock_guard guard(mLock);
+        return mStreamOutStandby;
+    }
+    long getReadCounterFrames() {
+        std::lock_guard guard(mLock);
+        return mReadCounterFrames;
+    }
+    int getReadErrorCount() {
+        std::lock_guard guard(mLock);
+        return mReadErrorCount;
+    }
+    std::chrono::time_point<std::chrono::steady_clock> getRecordStartTime() {
+        std::lock_guard guard(mLock);
+        return mRecordStartTime;
+    }
+    sp<MonoPipe> getSink() {
+        std::lock_guard guard(mLock);
+        return mSink;
+    }
+    sp<MonoPipeReader> getSource() {
+        std::lock_guard guard(mLock);
+        return mSource;
+    }
+
+    bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig);
+    void closeStream(bool isInput);
+    ::android::status_t createPipe(const AudioConfig& streamConfig);
+    void exitStandby(bool isInput);
+    bool hasAtleastOneStreamOpen();
+    int notifyReadError();
+    void openStream(bool isInput);
+    void releasePipe();
+    ::android::status_t resetPipe();
+    bool shouldBlockWrite();
+    void standby(bool isInput);
+    long updateReadCounterFrames(size_t frameCount);
+
+  private:
+    bool isStreamConfigCompatible(const AudioConfig& streamConfig);
+
+    std::mutex mLock;
+
+    bool mStreamInOpen GUARDED_BY(mLock) = false;
+    int mInputRefCount GUARDED_BY(mLock) = 0;
+    bool mStreamInStandby GUARDED_BY(mLock) = true;
+    bool mStreamOutStandbyTransition GUARDED_BY(mLock) = false;
+    bool mStreamOutOpen GUARDED_BY(mLock) = false;
+    bool mStreamOutStandby GUARDED_BY(mLock) = true;
+    // how many frames have been requested to be read since standby
+    long mReadCounterFrames GUARDED_BY(mLock) = 0;
+    int mReadErrorCount GUARDED_BY(mLock) = 0;
+    // wall clock when recording starts
+    std::chrono::time_point<std::chrono::steady_clock> mRecordStartTime GUARDED_BY(mLock);
+
+    // Pipe variables: they handle the ring buffer that "pipes" audio:
+    //  - from the submix virtual audio output == what needs to be played
+    //    remotely, seen as an output for the client
+    //  - to the virtual audio source == what is captured by the component
+    //    which "records" the submix / virtual audio source, and handles it as needed.
+    // A usecase example is one where the component capturing the audio is then sending it over
+    // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a
+    // TV with Wifi Display capabilities), or to a wireless audio player.
+    sp<MonoPipe> mSink GUARDED_BY(mLock);
+    sp<MonoPipeReader> mSource GUARDED_BY(mLock);
+};
+
+}  // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/stub/ModuleStub.cpp b/audio/aidl/default/stub/ModuleStub.cpp
new file mode 100644
index 0000000..9f6e0b4
--- /dev/null
+++ b/audio/aidl/default/stub/ModuleStub.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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 <vector>
+
+#define LOG_TAG "AHAL_ModuleStub"
+#include <Utils.h>
+#include <android-base/logging.h>
+
+#include "core-impl/Bluetooth.h"
+#include "core-impl/ModuleStub.h"
+#include "core-impl/StreamStub.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus ModuleStub::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
+    if (!mBluetooth) {
+        mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
+    }
+    *_aidl_return = mBluetooth.getInstance();
+    LOG(DEBUG) << __func__
+               << ": returning instance of IBluetooth: " << _aidl_return->get()->asBinder().get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleStub::getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
+    if (!mBluetoothA2dp) {
+        mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
+    }
+    *_aidl_return = mBluetoothA2dp.getInstance();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: "
+               << _aidl_return->get()->asBinder().get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleStub::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
+    if (!mBluetoothLe) {
+        mBluetoothLe = ndk::SharedRefBase::make<BluetoothLe>();
+    }
+    *_aidl_return = mBluetoothLe.getInstance();
+    LOG(DEBUG) << __func__
+               << ": returning instance of IBluetoothLe: " << _aidl_return->get()->asBinder().get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleStub::createInputStream(StreamContext&& context,
+                                                 const SinkMetadata& sinkMetadata,
+                                                 const std::vector<MicrophoneInfo>& microphones,
+                                                 std::shared_ptr<StreamIn>* result) {
+    return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
+                                              microphones);
+}
+
+ndk::ScopedAStatus ModuleStub::createOutputStream(
+        StreamContext&& context, const SourceMetadata& sourceMetadata,
+        const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+    return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
+                                               offloadInfo);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
new file mode 100644
index 0000000..660a51e
--- /dev/null
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 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 <cmath>
+
+#define LOG_TAG "AHAL_Stream"
+#include <android-base/logging.h>
+#include <audio_utils/clock.h>
+
+#include "core-impl/Module.h"
+#include "core-impl/StreamStub.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
+    : StreamCommonImpl(context, metadata),
+      mBufferSizeFrames(getContext().getBufferSizeInFrames()),
+      mFrameSizeBytes(getContext().getFrameSize()),
+      mSampleRate(getContext().getSampleRate()),
+      mIsAsynchronous(!!getContext().getAsyncCallback()),
+      mIsInput(isInput(metadata)) {}
+
+::android::status_t StreamStub::init() {
+    mIsInitialized = true;
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    if (!mIsInput) {
+        if (!mIsAsynchronous) {
+            static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+            const size_t delayUs = static_cast<size_t>(
+                    std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+            usleep(delayUs);
+        } else {
+            usleep(500);
+        }
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::flush() {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::pause() {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::standby() {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    usleep(500);
+    mIsStandby = true;
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::start() {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    usleep(500);
+    mIsStandby = false;
+    return ::android::OK;
+}
+
+::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                         int32_t* latencyMs) {
+    if (!mIsInitialized) {
+        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+    }
+    if (mIsStandby) {
+        LOG(FATAL) << __func__ << ": must not happen while in standby";
+    }
+    static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+    static constexpr float kScaleFactor = .8f;
+    if (mIsAsynchronous) {
+        usleep(500);
+    } else {
+        const size_t delayUs = static_cast<size_t>(
+                std::roundf(kScaleFactor * frameCount * kMicrosPerSecond / mSampleRate));
+        usleep(delayUs);
+    }
+    if (mIsInput) {
+        uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
+        for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
+            byteBuffer[i] = std::rand() % 255;
+        }
+    }
+    *actualFrameCount = frameCount;
+    *latencyMs = Module::kLatencyMs;
+    return ::android::OK;
+}
+
+void StreamStub::shutdown() {
+    mIsInitialized = false;
+}
+
+StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
+                           const std::vector<MicrophoneInfo>& microphones)
+    : StreamIn(std::move(context), microphones), StreamStub(&mContextInstance, sinkMetadata) {}
+
+StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata,
+                             const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamOut(std::move(context), offloadInfo), StreamStub(&mContextInstance, sourceMetadata) {}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp b/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp
new file mode 100644
index 0000000..572bc5a
--- /dev/null
+++ b/audio/aidl/default/tests/AudioPolicyConfigXmlConverterTest.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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 <memory>
+// #include <string>
+// #include <vector>
+
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+#define LOG_TAG "AudioPolicyConfigXmlConverterTest"
+#include <log/log.h>
+
+#include <core-impl/AudioPolicyConfigXmlConverter.h>
+#include <media/AidlConversionCppNdk.h>
+
+using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter;
+using aidl::android::media::audio::common::AudioFormatDescription;
+
+namespace {
+
+void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
+    auto conv = ::aidl::android::aidl2legacy_AudioFormatDescription_audio_format_t(format);
+    ASSERT_TRUE(conv.ok()) << format.toString();
+}
+
+}  // namespace
+
+TEST(AudioPolicyConfigXmlConverterTest, DefaultSurroundSoundConfigIsValid) {
+    auto config = AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig();
+    for (const auto& family : config.formatFamilies) {
+        EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
+        SCOPED_TRACE(family.primaryFormat.toString());
+        for (const auto& sub : family.subFormats) {
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(sub));
+        }
+    }
+}
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
index ecdbd5c..f926e09 100644
--- a/audio/aidl/default/usb/ModuleUsb.cpp
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -14,63 +14,34 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AHAL_ModuleUsb"
-
 #include <vector>
 
+#define LOG_TAG "AHAL_ModuleUsb"
 #include <Utils.h>
 #include <android-base/logging.h>
-#include <tinyalsa/asoundlib.h>
 
 #include "UsbAlsaMixerControl.h"
-#include "UsbAlsaUtils.h"
+#include "alsa/Utils.h"
 #include "core-impl/ModuleUsb.h"
+#include "core-impl/StreamUsb.h"
 
-extern "C" {
-#include "alsa_device_profile.h"
-}
-
-using aidl::android::hardware::audio::common::isUsbInputDeviceType;
-using aidl::android::media::audio::common::AudioChannelLayout;
-using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDeviceDescription;
-using aidl::android::media::audio::common::AudioDeviceType;
-using aidl::android::media::audio::common::AudioFormatDescription;
-using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioOffloadInfo;
 using aidl::android::media::audio::common::AudioPort;
 using aidl::android::media::audio::common::AudioPortConfig;
 using aidl::android::media::audio::common::AudioPortExt;
-using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::MicrophoneInfo;
 
 namespace aidl::android::hardware::audio::core {
 
 namespace {
 
-std::vector<AudioChannelLayout> populateChannelMasksFromProfile(const alsa_device_profile* profile,
-                                                                bool isInput) {
-    std::vector<AudioChannelLayout> channels;
-    for (size_t i = 0; i < AUDIO_PORT_MAX_CHANNEL_MASKS && profile->channel_counts[i] != 0; ++i) {
-        auto layoutMask =
-                usb::getChannelLayoutMaskFromChannelCount(profile->channel_counts[i], isInput);
-        if (layoutMask.getTag() == AudioChannelLayout::Tag::layoutMask) {
-            channels.push_back(layoutMask);
-        }
-        auto indexMask = usb::getChannelIndexMaskFromChannelCount(profile->channel_counts[i]);
-        if (indexMask.getTag() == AudioChannelLayout::Tag::indexMask) {
-            channels.push_back(indexMask);
-        }
-    }
-    return channels;
-}
-
-std::vector<int> populateSampleRatesFromProfile(const alsa_device_profile* profile) {
-    std::vector<int> sampleRates;
-    for (int i = 0; i < std::min(MAX_PROFILE_SAMPLE_RATES, AUDIO_PORT_MAX_SAMPLING_RATES) &&
-                    profile->sample_rates[i] != 0;
-         i++) {
-        sampleRates.push_back(profile->sample_rates[i]);
-    }
-    return sampleRates;
+bool isUsbDevicePort(const AudioPort& audioPort) {
+    return audioPort.ext.getTag() == AudioPortExt::Tag::device &&
+           audioPort.ext.get<AudioPortExt::Tag::device>().device.type.connection ==
+                   AudioDeviceDescription::CONNECTION_USB;
 }
 
 }  // namespace
@@ -97,56 +68,31 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
-    if (audioPort->ext.getTag() != AudioPortExt::Tag::device) {
-        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a device port";
+ndk::ScopedAStatus ModuleUsb::createInputStream(StreamContext&& context,
+                                                const SinkMetadata& sinkMetadata,
+                                                const std::vector<MicrophoneInfo>& microphones,
+                                                std::shared_ptr<StreamIn>* result) {
+    return createStreamInstance<StreamInUsb>(result, std::move(context), sinkMetadata, microphones);
+}
+
+ndk::ScopedAStatus ModuleUsb::createOutputStream(StreamContext&& context,
+                                                 const SourceMetadata& sourceMetadata,
+                                                 const std::optional<AudioOffloadInfo>& offloadInfo,
+                                                 std::shared_ptr<StreamOut>* result) {
+    if (offloadInfo.has_value()) {
+        LOG(ERROR) << __func__ << ": offload is not supported";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    auto& devicePort = audioPort->ext.get<AudioPortExt::Tag::device>();
-    if (devicePort.device.type.connection != AudioDeviceDescription::CONNECTION_USB) {
+    return createStreamInstance<StreamOutUsb>(result, std::move(context), sourceMetadata,
+                                              offloadInfo);
+}
+
+ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (!isUsbDevicePort(*audioPort)) {
         LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a usb device port";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    if (devicePort.device.address.getTag() != AudioDeviceAddress::Tag::alsa) {
-        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not using alsa address";
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-    }
-    auto& alsaAddress = devicePort.device.address.get<AudioDeviceAddress::Tag::alsa>();
-    if (alsaAddress.size() != 2 || alsaAddress[0] < 0 || alsaAddress[1] < 0) {
-        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " invalid alsa address";
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-    }
-
-    const bool isInput = isUsbInputDeviceType(devicePort.device.type.type);
-    alsa_device_profile profile;
-    profile_init(&profile, isInput ? PCM_IN : PCM_OUT);
-    profile.card = alsaAddress[0];
-    profile.device = alsaAddress[1];
-    if (!profile_read_device_info(&profile)) {
-        LOG(ERROR) << __func__ << ": failed to read device info, card=" << profile.card
-                   << ", device=" << profile.device;
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-    }
-
-    std::vector<AudioChannelLayout> channels = populateChannelMasksFromProfile(&profile, isInput);
-    std::vector<int> sampleRates = populateSampleRatesFromProfile(&profile);
-
-    for (size_t i = 0; i < std::min(MAX_PROFILE_FORMATS, AUDIO_PORT_MAX_AUDIO_PROFILES) &&
-                       profile.formats[i] != PCM_FORMAT_INVALID;
-         ++i) {
-        auto audioFormatDescription =
-                usb::legacy2aidl_pcm_format_AudioFormatDescription(profile.formats[i]);
-        if (audioFormatDescription.type == AudioFormatType::DEFAULT) {
-            LOG(WARNING) << __func__ << ": unknown pcm type=" << profile.formats[i];
-            continue;
-        }
-        AudioProfile audioProfile = {.format = audioFormatDescription,
-                                     .channelMasks = channels,
-                                     .sampleRates = sampleRates};
-        audioPort->profiles.push_back(std::move(audioProfile));
-    }
-
-    return ndk::ScopedAStatus::ok();
+    return ModuleAlsa::populateConnectedDevicePort(audioPort);
 }
 
 ndk::ScopedAStatus ModuleUsb::checkAudioPatchEndpointsMatch(
@@ -167,16 +113,15 @@
 
 void ModuleUsb::onExternalDeviceConnectionChanged(
         const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected) {
-    if (audioPort.ext.getTag() != AudioPortExt::Tag::device) {
+    if (!isUsbDevicePort(audioPort)) {
         return;
     }
-    const auto& address = audioPort.ext.get<AudioPortExt::Tag::device>().device.address;
-    if (address.getTag() != AudioDeviceAddress::alsa) {
+    auto profile = alsa::getDeviceProfile(audioPort);
+    if (!profile.has_value()) {
         return;
     }
-    const int card = address.get<AudioDeviceAddress::alsa>()[0];
-    usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(card, mMasterMute,
-                                                                     mMasterVolume, connected);
+    usb::UsbAlsaMixerControl::getInstance().setDeviceConnectionState(profile->card, getMasterMute(),
+                                                                     getMasterVolume(), connected);
 }
 
 ndk::ScopedAStatus ModuleUsb::onMasterMuteChanged(bool mute) {
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index 5d1d7fe..b60b4fd 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -14,211 +14,75 @@
  * limitations under the License.
  */
 
+#include <limits>
+
 #define LOG_TAG "AHAL_StreamUsb"
 #include <android-base/logging.h>
-
-#include <Utils.h>
+#include <error/expected_utils.h>
 
 #include "UsbAlsaMixerControl.h"
-#include "UsbAlsaUtils.h"
-#include "core-impl/Module.h"
 #include "core-impl/StreamUsb.h"
 
-extern "C" {
-#include "alsa_device_profile.h"
-}
-
-using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDevice;
-using aidl::android::media::audio::common::AudioDeviceAddress;
 using aidl::android::media::audio::common::AudioOffloadInfo;
-using aidl::android::media::audio::common::AudioPortExt;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
-using android::OK;
-using android::status_t;
 
 namespace aidl::android::hardware::audio::core {
 
-DriverUsb::DriverUsb(const StreamContext& context, bool isInput)
-    : mFrameSizeBytes(context.getFrameSize()), mIsInput(isInput) {
-    struct pcm_config config;
-    config.channels = usb::getChannelCountFromChannelMask(context.getChannelLayout(), isInput);
-    if (config.channels == 0) {
-        LOG(ERROR) << __func__ << ": invalid channel=" << context.getChannelLayout().toString();
-        return;
-    }
-    config.format = usb::aidl2legacy_AudioFormatDescription_pcm_format(context.getFormat());
-    if (config.format == PCM_FORMAT_INVALID) {
-        LOG(ERROR) << __func__ << ": invalid format=" << context.getFormat().toString();
-        return;
-    }
-    config.rate = context.getSampleRate();
-    if (config.rate == 0) {
-        LOG(ERROR) << __func__ << ": invalid sample rate=" << config.rate;
-        return;
-    }
-    mConfig = config;
-}
+StreamUsb::StreamUsb(StreamContext* context, const Metadata& metadata)
+    : StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {}
 
-::android::status_t DriverUsb::init() {
-    return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
-}
-
-::android::status_t DriverUsb::setConnectedDevices(
+ndk::ScopedAStatus StreamUsb::setConnectedDevices(
         const std::vector<AudioDevice>& connectedDevices) {
     if (mIsInput && connectedDevices.size() > 1) {
         LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
                    << ") for input stream";
-        return ::android::BAD_VALUE;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
+    std::vector<alsa::DeviceProfile> connectedDeviceProfiles;
     for (const auto& connectedDevice : connectedDevices) {
-        if (connectedDevice.address.getTag() != AudioDeviceAddress::alsa) {
-            LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
-            return ::android::BAD_VALUE;
-        }
-    }
-    std::lock_guard guard(mLock);
-    mAlsaDeviceProxies.clear();
-    mConnectedDevices.clear();
-    for (const auto& connectedDevice : connectedDevices) {
-        mConnectedDevices.push_back(connectedDevice.address);
-    }
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::drain(StreamDescriptor::DrainMode) {
-    usleep(1000);
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::flush() {
-    usleep(1000);
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::pause() {
-    usleep(1000);
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
-                                        int32_t* latencyMs) {
-    if (!mConfig.has_value() || mConnectedDevices.empty()) {
-        LOG(ERROR) << __func__ << ": failed, has config: " << mConfig.has_value()
-                   << ", has connected devices: " << mConnectedDevices.empty();
-        return ::android::NO_INIT;
-    }
-    if (mIsStandby) {
-        if (::android::status_t status = exitStandby(); status != ::android::OK) {
-            LOG(ERROR) << __func__ << ": failed to exit standby, status=" << status;
-            return status;
-        }
-    }
-    std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
-    {
-        std::lock_guard guard(mLock);
-        alsaDeviceProxies = mAlsaDeviceProxies;
-    }
-    const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
-    if (mIsInput) {
-        // For input case, only support single device.
-        proxy_read(alsaDeviceProxies[0].get(), buffer, bytesToTransfer);
-    } else {
-        for (auto& proxy : alsaDeviceProxies) {
-            proxy_write(proxy.get(), buffer, bytesToTransfer);
-        }
-    }
-    *actualFrameCount = frameCount;
-    *latencyMs = Module::kLatencyMs;
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::standby() {
-    if (!mIsStandby) {
-        std::lock_guard guard(mLock);
-        mAlsaDeviceProxies.clear();
-        mIsStandby = true;
-    }
-    return ::android::OK;
-}
-
-::android::status_t DriverUsb::exitStandby() {
-    std::vector<AudioDeviceAddress> connectedDevices;
-    {
-        std::lock_guard guard(mLock);
-        connectedDevices = mConnectedDevices;
-    }
-    std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
-    for (const auto& device : connectedDevices) {
-        alsa_device_profile profile;
-        profile_init(&profile, mIsInput ? PCM_IN : PCM_OUT);
-        profile.card = device.get<AudioDeviceAddress::alsa>()[0];
-        profile.device = device.get<AudioDeviceAddress::alsa>()[1];
-        if (!profile_read_device_info(&profile)) {
+        auto profile = alsa::getDeviceProfile(connectedDevice, mIsInput);
+        if (!profile.has_value()) {
             LOG(ERROR) << __func__
-                       << ": unable to read device info, device address=" << device.toString();
-            return ::android::UNKNOWN_ERROR;
+                       << ": unsupported device address=" << connectedDevice.address.toString();
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
-
-        auto proxy = std::shared_ptr<alsa_device_proxy>(new alsa_device_proxy(),
-                                                        [](alsa_device_proxy* proxy) {
-                                                            proxy_close(proxy);
-                                                            free(proxy);
-                                                        });
-        // Always ask for alsa configure as required since the configuration should be supported
-        // by the connected device. That is guaranteed by `setAudioPortConfig` and
-        // `setAudioPatch`.
-        if (int err =
-                    proxy_prepare(proxy.get(), &profile, &mConfig.value(), true /*is_bit_perfect*/);
-            err != 0) {
-            LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device.toString()
-                       << " error=" << err;
-            return ::android::UNKNOWN_ERROR;
-        }
-        if (int err = proxy_open(proxy.get()); err != 0) {
-            LOG(ERROR) << __func__ << ": failed to open device, address=" << device.toString()
-                       << " error=" << err;
-            return ::android::UNKNOWN_ERROR;
-        }
-        alsaDeviceProxies.push_back(std::move(proxy));
+        connectedDeviceProfiles.push_back(*profile);
     }
-    {
-        std::lock_guard guard(mLock);
-        mAlsaDeviceProxies = alsaDeviceProxies;
-    }
-    mIsStandby = false;
-    return ::android::OK;
-}
-
-// static
-ndk::ScopedAStatus StreamInUsb::createInstance(const SinkMetadata& sinkMetadata,
-                                               StreamContext&& context,
-                                               const std::vector<MicrophoneInfo>& microphones,
-                                               std::shared_ptr<StreamIn>* result) {
-    std::shared_ptr<StreamIn> stream =
-            ndk::SharedRefBase::make<StreamInUsb>(sinkMetadata, std::move(context), microphones);
-    if (auto status = initInstance(stream); !status.isOk()) {
-        return status;
-    }
-    *result = std::move(stream);
+    RETURN_STATUS_IF_ERROR(setConnectedDevices(connectedDevices));
+    std::lock_guard guard(mLock);
+    mConnectedDeviceProfiles = std::move(connectedDeviceProfiles);
+    mConnectedDevicesUpdated.store(true, std::memory_order_release);
     return ndk::ScopedAStatus::ok();
 }
 
-StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
+::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                        int32_t* latencyMs) {
+    if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) {
+        // 'setConnectedDevices' was called. I/O will be restarted.
+        *actualFrameCount = 0;
+        *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
+        return ::android::OK;
+    }
+    return StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs);
+}
+
+std::vector<alsa::DeviceProfile> StreamUsb::getDeviceProfiles() {
+    std::vector<alsa::DeviceProfile> connectedDevices;
+    {
+        std::lock_guard guard(mLock);
+        connectedDevices = mConnectedDeviceProfiles;
+        mConnectedDevicesUpdated.store(false, std::memory_order_release);
+    }
+    return connectedDevices;
+}
+
+StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata,
                          const std::vector<MicrophoneInfo>& microphones)
-    : StreamIn(
-              sinkMetadata, std::move(context),
-              [](const StreamContext& ctx) -> DriverInterface* {
-                  return new DriverUsb(ctx, true /*isInput*/);
-              },
-              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
-                  // The default worker implementation is used.
-                  return new StreamInWorker(ctx, driver);
-              },
-              microphones) {}
+    : StreamIn(std::move(context), microphones), StreamUsb(&mContextInstance, sinkMetadata) {}
 
 ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
         std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -226,59 +90,33 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-// static
-ndk::ScopedAStatus StreamOutUsb::createInstance(const SourceMetadata& sourceMetadata,
-                                                StreamContext&& context,
-                                                const std::optional<AudioOffloadInfo>& offloadInfo,
-                                                std::shared_ptr<StreamOut>* result) {
-    if (offloadInfo.has_value()) {
-        LOG(ERROR) << __func__ << ": offload is not supported";
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-    }
-    std::shared_ptr<StreamOut> stream =
-            ndk::SharedRefBase::make<StreamOutUsb>(sourceMetadata, std::move(context), offloadInfo);
-    if (auto status = initInstance(stream); !status.isOk()) {
-        return status;
-    }
-    *result = std::move(stream);
-    return ndk::ScopedAStatus::ok();
-}
-
-StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
+StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata,
                            const std::optional<AudioOffloadInfo>& offloadInfo)
-    : StreamOut(
-              sourceMetadata, std::move(context),
-              [](const StreamContext& ctx) -> DriverInterface* {
-                  return new DriverUsb(ctx, false /*isInput*/);
-              },
-              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
-                  // The default worker implementation is used.
-                  return new StreamOutWorker(ctx, driver);
-              },
-              offloadInfo) {
-    mChannelCount = getChannelCount(mContext.getChannelLayout());
-}
+    : StreamOut(std::move(context), offloadInfo),
+      StreamUsb(&mContextInstance, sourceMetadata),
+      StreamOutHwVolumeHelper(&mContextInstance) {}
 
 ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
-    *_aidl_return = mHwVolumes;
-    return ndk::ScopedAStatus::ok();
+    return getHwVolumeImpl(_aidl_return);
 }
 
 ndk::ScopedAStatus StreamOutUsb::setHwVolume(const std::vector<float>& in_channelVolumes) {
-    for (const auto& device : mConnectedDevices) {
-        if (device.address.getTag() != AudioDeviceAddress::alsa) {
-            LOG(DEBUG) << __func__ << ": skip as the device address is not alsa";
-            continue;
-        }
-        const int card = device.address.get<AudioDeviceAddress::alsa>()[0];
-        if (auto result =
-                    usb::UsbAlsaMixerControl::getInstance().setVolumes(card, in_channelVolumes);
-            !result.isOk()) {
-            LOG(ERROR) << __func__ << ": failed to set volume for device, card=" << card;
-            return result;
+    auto currentVolumes = mHwVolumes;
+    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
+    // Avoid using mConnectedDeviceProfiles because it requires a lock.
+    for (const auto& device : getConnectedDevices()) {
+        if (auto deviceProfile = alsa::getDeviceProfile(device, mIsInput);
+            deviceProfile.has_value()) {
+            if (auto result = usb::UsbAlsaMixerControl::getInstance().setVolumes(
+                        deviceProfile->card, in_channelVolumes);
+                !result.isOk()) {
+                LOG(ERROR) << __func__
+                           << ": failed to set volume for device address=" << *deviceProfile;
+                mHwVolumes = currentVolumes;
+                return result;
+            }
         }
     }
-    mHwVolumes = in_channelVolumes;
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
index b5337d1..0a49446 100644
--- a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
+++ b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp
@@ -17,151 +17,12 @@
 #define LOG_TAG "AHAL_UsbAlsaMixerControl"
 #include <android-base/logging.h>
 
-#include <cmath>
-#include <string>
-#include <vector>
-
 #include <android/binder_status.h>
 
 #include "UsbAlsaMixerControl.h"
 
 namespace aidl::android::hardware::audio::core::usb {
 
-//-----------------------------------------------------------------------------
-
-MixerControl::MixerControl(struct mixer_ctl* ctl)
-    : mCtl(ctl),
-      mNumValues(mixer_ctl_get_num_values(ctl)),
-      mMinValue(mixer_ctl_get_range_min(ctl)),
-      mMaxValue(mixer_ctl_get_range_max(ctl)) {}
-
-unsigned int MixerControl::getNumValues() const {
-    return mNumValues;
-}
-
-int MixerControl::getMaxValue() const {
-    return mMaxValue;
-}
-
-int MixerControl::getMinValue() const {
-    return mMinValue;
-}
-
-int MixerControl::setArray(const void* array, size_t count) {
-    const std::lock_guard guard(mLock);
-    return mixer_ctl_set_array(mCtl, array, count);
-}
-
-//-----------------------------------------------------------------------------
-
-// static
-const std::map<AlsaMixer::Control, std::vector<AlsaMixer::ControlNamesAndExpectedCtlType>>
-        AlsaMixer::kPossibleControls = {
-                {AlsaMixer::MASTER_SWITCH, {{"Master Playback Switch", MIXER_CTL_TYPE_BOOL}}},
-                {AlsaMixer::MASTER_VOLUME, {{"Master Playback Volume", MIXER_CTL_TYPE_INT}}},
-                {AlsaMixer::HW_VOLUME,
-                 {{"Headphone Playback Volume", MIXER_CTL_TYPE_INT},
-                  {"Headset Playback Volume", MIXER_CTL_TYPE_INT},
-                  {"PCM Playback Volume", MIXER_CTL_TYPE_INT}}}};
-
-// static
-std::map<AlsaMixer::Control, std::shared_ptr<MixerControl>> AlsaMixer::initializeMixerControls(
-        struct mixer* mixer) {
-    std::map<AlsaMixer::Control, std::shared_ptr<MixerControl>> mixerControls;
-    std::string mixerCtlNames;
-    for (const auto& [control, possibleCtls] : kPossibleControls) {
-        for (const auto& [ctlName, expectedCtlType] : possibleCtls) {
-            struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str());
-            if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) {
-                mixerControls.emplace(control, std::make_unique<MixerControl>(ctl));
-                if (!mixerCtlNames.empty()) {
-                    mixerCtlNames += ",";
-                }
-                mixerCtlNames += ctlName;
-                break;
-            }
-        }
-    }
-    LOG(DEBUG) << __func__ << ": available mixer control names=[" << mixerCtlNames << "]";
-    return mixerControls;
-}
-
-AlsaMixer::AlsaMixer(struct mixer* mixer)
-    : mMixer(mixer), mMixerControls(initializeMixerControls(mMixer)) {}
-
-AlsaMixer::~AlsaMixer() {
-    mixer_close(mMixer);
-}
-
-namespace {
-
-int volumeFloatToInteger(float fValue, int maxValue, int minValue) {
-    return minValue + std::ceil((maxValue - minValue) * fValue);
-}
-
-float volumeIntegerToFloat(int iValue, int maxValue, int minValue) {
-    if (iValue > maxValue) {
-        return 1.0f;
-    }
-    if (iValue < minValue) {
-        return 0.0f;
-    }
-    return static_cast<float>(iValue - minValue) / (maxValue - minValue);
-}
-
-}  // namespace
-
-ndk::ScopedAStatus AlsaMixer::setMasterMute(bool muted) {
-    auto it = mMixerControls.find(AlsaMixer::MASTER_SWITCH);
-    if (it == mMixerControls.end()) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    }
-    const int numValues = it->second->getNumValues();
-    std::vector<int> values(numValues, muted ? 0 : 1);
-    if (int err = it->second->setArray(values.data(), numValues); err != 0) {
-        LOG(ERROR) << __func__ << ": failed to set master mute, err=" << err;
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus AlsaMixer::setMasterVolume(float volume) {
-    auto it = mMixerControls.find(AlsaMixer::MASTER_VOLUME);
-    if (it == mMixerControls.end()) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    }
-    const int numValues = it->second->getNumValues();
-    std::vector<int> values(numValues, volumeFloatToInteger(volume, it->second->getMaxValue(),
-                                                            it->second->getMinValue()));
-    if (int err = it->second->setArray(values.data(), numValues); err != 0) {
-        LOG(ERROR) << __func__ << ": failed to set master volume, err=" << err;
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus AlsaMixer::setVolumes(std::vector<float> volumes) {
-    auto it = mMixerControls.find(AlsaMixer::HW_VOLUME);
-    if (it == mMixerControls.end()) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    }
-    const int numValues = it->second->getNumValues();
-    const int maxValue = it->second->getMaxValue();
-    const int minValue = it->second->getMinValue();
-    std::vector<int> values;
-    size_t i = 0;
-    for (; i < numValues && i < values.size(); ++i) {
-        values.emplace_back(volumeFloatToInteger(volumes[i], maxValue, minValue));
-    }
-    if (int err = it->second->setArray(values.data(), values.size()); err != 0) {
-        LOG(ERROR) << __func__ << ": failed to set volume, err=" << err;
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
-//-----------------------------------------------------------------------------
-
 // static
 UsbAlsaMixerControl& UsbAlsaMixerControl::getInstance() {
     static UsbAlsaMixerControl gInstance;
@@ -172,12 +33,10 @@
                                                    bool connected) {
     LOG(DEBUG) << __func__ << ": card=" << card << ", connected=" << connected;
     if (connected) {
-        struct mixer* mixer = mixer_open(card);
-        if (mixer == nullptr) {
-            PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
+        auto alsaMixer = std::make_shared<alsa::Mixer>(card);
+        if (!alsaMixer->isValid()) {
             return;
         }
-        auto alsaMixer = std::make_shared<AlsaMixer>(mixer);
         alsaMixer->setMasterMute(masterMuted);
         alsaMixer->setMasterVolume(masterVolume);
         const std::lock_guard guard(mLock);
@@ -216,7 +75,7 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus UsbAlsaMixerControl::setVolumes(int card, std::vector<float> volumes) {
+ndk::ScopedAStatus UsbAlsaMixerControl::setVolumes(int card, const std::vector<float>& volumes) {
     auto alsaMixer = getAlsaMixer(card);
     if (alsaMixer == nullptr) {
         LOG(ERROR) << __func__ << ": no mixer control found for card=" << card;
@@ -225,13 +84,13 @@
     return alsaMixer->setVolumes(volumes);
 }
 
-std::shared_ptr<AlsaMixer> UsbAlsaMixerControl::getAlsaMixer(int card) {
+std::shared_ptr<alsa::Mixer> UsbAlsaMixerControl::getAlsaMixer(int card) {
     const std::lock_guard guard(mLock);
     const auto it = mMixerControls.find(card);
     return it == mMixerControls.end() ? nullptr : it->second;
 }
 
-std::map<int, std::shared_ptr<AlsaMixer>> UsbAlsaMixerControl::getAlsaMixers() {
+std::map<int, std::shared_ptr<alsa::Mixer>> UsbAlsaMixerControl::getAlsaMixers() {
     const std::lock_guard guard(mLock);
     return mMixerControls;
 }
diff --git a/audio/aidl/default/usb/UsbAlsaMixerControl.h b/audio/aidl/default/usb/UsbAlsaMixerControl.h
index cbcddd8..c3265f8 100644
--- a/audio/aidl/default/usb/UsbAlsaMixerControl.h
+++ b/audio/aidl/default/usb/UsbAlsaMixerControl.h
@@ -19,67 +19,15 @@
 #include <map>
 #include <memory>
 #include <mutex>
-#include <optional>
-#include <string>
 #include <vector>
 
 #include <android-base/thread_annotations.h>
 #include <android/binder_auto_utils.h>
 
-extern "C" {
-#include <tinyalsa/mixer.h>
-}
+#include "alsa/Mixer.h"
 
 namespace aidl::android::hardware::audio::core::usb {
 
-class MixerControl {
-  public:
-    explicit MixerControl(struct mixer_ctl* ctl);
-
-    unsigned int getNumValues() const;
-    int getMaxValue() const;
-    int getMinValue() const;
-    int setArray(const void* array, size_t count);
-
-  private:
-    std::mutex mLock;
-    // The mixer_ctl object is owned by ALSA and will be released when the mixer is closed.
-    struct mixer_ctl* mCtl GUARDED_BY(mLock);
-    const unsigned int mNumValues;
-    const int mMinValue;
-    const int mMaxValue;
-};
-
-class AlsaMixer {
-  public:
-    explicit AlsaMixer(struct mixer* mixer);
-
-    ~AlsaMixer();
-
-    bool isValid() const { return mMixer != nullptr; }
-
-    ndk::ScopedAStatus setMasterMute(bool muted);
-    ndk::ScopedAStatus setMasterVolume(float volume);
-    ndk::ScopedAStatus setVolumes(std::vector<float> volumes);
-
-  private:
-    enum Control {
-        MASTER_SWITCH,
-        MASTER_VOLUME,
-        HW_VOLUME,
-    };
-    using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>;
-    static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
-    static std::map<Control, std::shared_ptr<MixerControl>> initializeMixerControls(
-            struct mixer* mixer);
-
-    // The mixer object is owned by ALSA and will be released when the mixer is closed.
-    struct mixer* mMixer;
-    // `mMixerControls` will only be initialized in constructor. After that, it wil only be
-    // read but not be modified.
-    const std::map<Control, std::shared_ptr<MixerControl>> mMixerControls;
-};
-
 class UsbAlsaMixerControl {
   public:
     static UsbAlsaMixerControl& getInstance();
@@ -91,16 +39,16 @@
     ndk::ScopedAStatus setMasterMute(bool muted);
     ndk::ScopedAStatus setMasterVolume(float volume);
     // The volume settings can be different on sound cards. It is controlled by streams.
-    ndk::ScopedAStatus setVolumes(int card, std::vector<float> volumes);
+    ndk::ScopedAStatus setVolumes(int card, const std::vector<float>& volumes);
 
   private:
-    std::shared_ptr<AlsaMixer> getAlsaMixer(int card);
-    std::map<int, std::shared_ptr<AlsaMixer>> getAlsaMixers();
+    std::shared_ptr<alsa::Mixer> getAlsaMixer(int card);
+    std::map<int, std::shared_ptr<alsa::Mixer>> getAlsaMixers();
 
     std::mutex mLock;
     // A map whose key is the card number and value is a shared pointer to corresponding
     // AlsaMixer object.
-    std::map<int, std::shared_ptr<AlsaMixer>> mMixerControls GUARDED_BY(mLock);
+    std::map<int, std::shared_ptr<alsa::Mixer>> mMixerControls GUARDED_BY(mLock);
 };
 
 }  // namespace aidl::android::hardware::audio::core::usb
diff --git a/audio/aidl/default/usb/UsbAlsaUtils.cpp b/audio/aidl/default/usb/UsbAlsaUtils.cpp
deleted file mode 100644
index 74d9c28..0000000
--- a/audio/aidl/default/usb/UsbAlsaUtils.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2023 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 <map>
-#include <set>
-
-#include <Utils.h>
-#include <aidl/android/media/audio/common/AudioFormatType.h>
-#include <aidl/android/media/audio/common/PcmType.h>
-
-#include "UsbAlsaUtils.h"
-#include "core-impl/utils.h"
-
-using aidl::android::hardware::audio::common::getChannelCount;
-using aidl::android::media::audio::common::AudioChannelLayout;
-using aidl::android::media::audio::common::AudioFormatDescription;
-using aidl::android::media::audio::common::AudioFormatType;
-using aidl::android::media::audio::common::PcmType;
-
-namespace aidl::android::hardware::audio::core::usb {
-
-namespace {
-
-using AudioChannelCountToMaskMap = std::map<unsigned int, AudioChannelLayout>;
-using AudioFormatDescToPcmFormatMap = std::map<AudioFormatDescription, enum pcm_format>;
-using PcmFormatToAudioFormatDescMap = std::map<enum pcm_format, AudioFormatDescription>;
-
-static const AudioChannelLayout INVALID_CHANNEL_LAYOUT =
-        AudioChannelLayout::make<AudioChannelLayout::Tag::invalid>(0);
-
-#define DEFINE_CHANNEL_LAYOUT_MASK(n) \
-    AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(AudioChannelLayout::LAYOUT_##n)
-
-static const std::set<AudioChannelLayout> SUPPORTED_OUT_CHANNEL_LAYOUTS = {
-        DEFINE_CHANNEL_LAYOUT_MASK(MONO),          DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
-        DEFINE_CHANNEL_LAYOUT_MASK(2POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(QUAD),
-        DEFINE_CHANNEL_LAYOUT_MASK(PENTA),         DEFINE_CHANNEL_LAYOUT_MASK(5POINT1),
-        DEFINE_CHANNEL_LAYOUT_MASK(6POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(7POINT1),
-        DEFINE_CHANNEL_LAYOUT_MASK(7POINT1POINT4), DEFINE_CHANNEL_LAYOUT_MASK(22POINT2),
-};
-
-static const std::set<AudioChannelLayout> SUPPORTED_IN_CHANNEL_LAYOUTS = {
-        DEFINE_CHANNEL_LAYOUT_MASK(MONO),
-        DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
-};
-
-#define DEFINE_CHANNEL_INDEX_MASK(n) \
-    AudioChannelLayout::make<AudioChannelLayout::Tag::indexMask>(AudioChannelLayout::INDEX_MASK_##n)
-
-static const std::set<AudioChannelLayout> SUPPORTED_INDEX_CHANNEL_LAYOUTS = {
-        DEFINE_CHANNEL_INDEX_MASK(1),  DEFINE_CHANNEL_INDEX_MASK(2),  DEFINE_CHANNEL_INDEX_MASK(3),
-        DEFINE_CHANNEL_INDEX_MASK(4),  DEFINE_CHANNEL_INDEX_MASK(5),  DEFINE_CHANNEL_INDEX_MASK(6),
-        DEFINE_CHANNEL_INDEX_MASK(7),  DEFINE_CHANNEL_INDEX_MASK(8),  DEFINE_CHANNEL_INDEX_MASK(9),
-        DEFINE_CHANNEL_INDEX_MASK(10), DEFINE_CHANNEL_INDEX_MASK(11), DEFINE_CHANNEL_INDEX_MASK(12),
-        DEFINE_CHANNEL_INDEX_MASK(13), DEFINE_CHANNEL_INDEX_MASK(14), DEFINE_CHANNEL_INDEX_MASK(15),
-        DEFINE_CHANNEL_INDEX_MASK(16), DEFINE_CHANNEL_INDEX_MASK(17), DEFINE_CHANNEL_INDEX_MASK(18),
-        DEFINE_CHANNEL_INDEX_MASK(19), DEFINE_CHANNEL_INDEX_MASK(20), DEFINE_CHANNEL_INDEX_MASK(21),
-        DEFINE_CHANNEL_INDEX_MASK(22), DEFINE_CHANNEL_INDEX_MASK(23), DEFINE_CHANNEL_INDEX_MASK(24),
-};
-
-static AudioChannelCountToMaskMap make_ChannelCountToMaskMap(
-        const std::set<AudioChannelLayout>& channelMasks) {
-    AudioChannelCountToMaskMap channelMaskToCountMap;
-    for (const auto& channelMask : channelMasks) {
-        channelMaskToCountMap.emplace(getChannelCount(channelMask), channelMask);
-    }
-    return channelMaskToCountMap;
-}
-
-const AudioChannelCountToMaskMap& getSupportedChannelOutLayoutMap() {
-    static const AudioChannelCountToMaskMap outLayouts =
-            make_ChannelCountToMaskMap(SUPPORTED_OUT_CHANNEL_LAYOUTS);
-    return outLayouts;
-}
-
-const AudioChannelCountToMaskMap& getSupportedChannelInLayoutMap() {
-    static const AudioChannelCountToMaskMap inLayouts =
-            make_ChannelCountToMaskMap(SUPPORTED_IN_CHANNEL_LAYOUTS);
-    return inLayouts;
-}
-
-const AudioChannelCountToMaskMap& getSupportedChannelIndexLayoutMap() {
-    static const AudioChannelCountToMaskMap indexLayouts =
-            make_ChannelCountToMaskMap(SUPPORTED_INDEX_CHANNEL_LAYOUTS);
-    return indexLayouts;
-}
-
-AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
-    AudioFormatDescription result;
-    result.type = type;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
-    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
-    result.pcm = pcm;
-    return result;
-}
-
-const AudioFormatDescToPcmFormatMap& getAudioFormatDescriptorToPcmFormatMap() {
-    static const AudioFormatDescToPcmFormatMap formatDescToPcmFormatMap = {
-            {make_AudioFormatDescription(PcmType::UINT_8_BIT), PCM_FORMAT_S8},
-            {make_AudioFormatDescription(PcmType::INT_16_BIT), PCM_FORMAT_S16_LE},
-            {make_AudioFormatDescription(PcmType::FIXED_Q_8_24), PCM_FORMAT_S24_LE},
-            {make_AudioFormatDescription(PcmType::INT_24_BIT), PCM_FORMAT_S24_3LE},
-            {make_AudioFormatDescription(PcmType::INT_32_BIT), PCM_FORMAT_S32_LE},
-            {make_AudioFormatDescription(PcmType::FLOAT_32_BIT), PCM_FORMAT_FLOAT_LE},
-    };
-    return formatDescToPcmFormatMap;
-}
-
-static PcmFormatToAudioFormatDescMap make_PcmFormatToAudioFormatDescMap(
-        const AudioFormatDescToPcmFormatMap& formatDescToPcmFormatMap) {
-    PcmFormatToAudioFormatDescMap result;
-    for (const auto& formatPair : formatDescToPcmFormatMap) {
-        result.emplace(formatPair.second, formatPair.first);
-    }
-    return result;
-}
-
-const PcmFormatToAudioFormatDescMap& getPcmFormatToAudioFormatDescMap() {
-    static const PcmFormatToAudioFormatDescMap pcmFormatToFormatDescMap =
-            make_PcmFormatToAudioFormatDescMap(getAudioFormatDescriptorToPcmFormatMap());
-    return pcmFormatToFormatDescMap;
-}
-
-}  // namespace
-
-AudioChannelLayout getChannelLayoutMaskFromChannelCount(unsigned int channelCount, int isInput) {
-    return findValueOrDefault(
-            isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
-            channelCount, INVALID_CHANNEL_LAYOUT);
-}
-
-AudioChannelLayout getChannelIndexMaskFromChannelCount(unsigned int channelCount) {
-    return findValueOrDefault(getSupportedChannelIndexLayoutMap(), channelCount,
-                              INVALID_CHANNEL_LAYOUT);
-}
-
-unsigned int getChannelCountFromChannelMask(const AudioChannelLayout& channelMask, bool isInput) {
-    switch (channelMask.getTag()) {
-        case AudioChannelLayout::Tag::layoutMask: {
-            return findKeyOrDefault(
-                    isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
-                    (unsigned int)getChannelCount(channelMask), 0u /*defaultValue*/);
-        }
-        case AudioChannelLayout::Tag::indexMask: {
-            return findKeyOrDefault(getSupportedChannelIndexLayoutMap(),
-                                    (unsigned int)getChannelCount(channelMask),
-                                    0u /*defaultValue*/);
-        }
-        case AudioChannelLayout::Tag::none:
-        case AudioChannelLayout::Tag::invalid:
-        case AudioChannelLayout::Tag::voiceMask:
-        default:
-            return 0;
-    }
-}
-
-AudioFormatDescription legacy2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy) {
-    return findValueOrDefault(getPcmFormatToAudioFormatDescMap(), legacy, AudioFormatDescription());
-}
-
-pcm_format aidl2legacy_AudioFormatDescription_pcm_format(const AudioFormatDescription& aidl) {
-    return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
-}
-
-}  // namespace aidl::android::hardware::audio::core::usb
diff --git a/audio/aidl/default/usb/UsbAlsaUtils.h b/audio/aidl/default/usb/UsbAlsaUtils.h
deleted file mode 100644
index 2d2f0f4..0000000
--- a/audio/aidl/default/usb/UsbAlsaUtils.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2023 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.
- */
-
-#pragma once
-
-#include <aidl/android/media/audio/common/AudioChannelLayout.h>
-#include <aidl/android/media/audio/common/AudioFormatDescription.h>
-
-extern "C" {
-#include <tinyalsa/pcm.h>
-}
-
-namespace aidl::android::hardware::audio::core::usb {
-
-::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
-        unsigned int channelCount, int isInput);
-::aidl::android::media::audio::common::AudioChannelLayout getChannelIndexMaskFromChannelCount(
-        unsigned int channelCount);
-unsigned int getChannelCountFromChannelMask(
-        const ::aidl::android::media::audio::common::AudioChannelLayout& channelMask, bool isInput);
-::aidl::android::media::audio::common::AudioFormatDescription
-legacy2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy);
-pcm_format aidl2legacy_AudioFormatDescription_pcm_format(
-        const ::aidl::android::media::audio::common::AudioFormatDescription& aidl);
-
-}  // namespace aidl::android::hardware::audio::core::usb
\ No newline at end of file
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 852255d..f7cf4ce 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -55,6 +55,7 @@
         "VtsHalAudioCoreConfigTargetTest.cpp",
         "VtsHalAudioCoreModuleTargetTest.cpp",
     ],
+    test_config: "VtsHalAudioCoreTargetTest.xml",
 }
 
 cc_test {
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 4e84f6b..2c8edf2 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -30,6 +30,7 @@
 #include <android/binder_auto_utils.h>
 #include <fmq/AidlMessageQueue.h>
 #include <gtest/gtest.h>
+#include <system/audio_aidl_utils.h>
 #include <system/audio_effects/aidl_effects_utils.h>
 #include <system/audio_effects/effect_uuid.h>
 
@@ -51,6 +52,7 @@
 using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioUuid;
 using aidl::android::media::audio::common::PcmType;
+using ::android::audio::utils::toString;
 using ::android::hardware::EventFlag;
 
 const AudioFormatDescription kDefaultFormatDescription = {
@@ -63,6 +65,12 @@
                                     ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
         DataMQ;
 
+static inline std::string getPrefix(Descriptor& descriptor) {
+    std::string prefix = "Implementor_" + descriptor.common.implementor + "_name_" +
+                         descriptor.common.name + "_UUID_" + toString(descriptor.common.id.uuid);
+    return prefix;
+}
+
 class EffectHelper {
   public:
     static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
@@ -71,7 +79,7 @@
         auto& id = desc.common.id;
         ASSERT_STATUS(status, factory->createEffect(id.uuid, &effect));
         if (status == EX_NONE) {
-            ASSERT_NE(effect, nullptr) << id.uuid.toString();
+            ASSERT_NE(effect, nullptr) << toString(id.uuid);
         }
     }
 
@@ -242,11 +250,11 @@
                    maxLimit = std::numeric_limits<S>::max();
         if (s.size()) {
             const auto min = *s.begin(), max = *s.rbegin();
-            s.insert(min + (max - min) / 2);
-            if (min != minLimit) {
+            s.insert((min & max) + ((min ^ max) >> 1));
+            if (min > minLimit + 1) {
                 s.insert(min - 1);
             }
-            if (max != maxLimit) {
+            if (max < maxLimit - 1) {
                 s.insert(max + 1);
             }
         }
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index 8c448a8..7213034 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -30,6 +30,7 @@
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceDescription;
 using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioEncapsulationMode;
 using aidl::android::media::audio::common::AudioFormatDescription;
@@ -96,7 +97,10 @@
             } else {
                 mAttachedSinkDevicePorts.insert(port.id);
             }
-        } else if (port.profiles.empty()) {
+        } else if (devicePort.device.type.connection != AudioDeviceDescription::CONNECTION_VIRTUAL
+                   // The "virtual" connection is used for remote submix which is a dynamic
+                   // device but it can be connected and used w/o external hardware.
+                   && port.profiles.empty()) {
             mExternalDevicePorts.insert(port.id);
         }
     }
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index 72ca56f..10c2fc6 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -77,3 +77,10 @@
 #define EXPECT_STATUS(expected, ret)                                                       \
     EXPECT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
                         expected, ret)
+
+#define SKIP_TEST_IF_DATA_UNSUPPORTED(flags)                                                  \
+    ({                                                                                        \
+        if ((flags).hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL || (flags).bypass) {  \
+            GTEST_SKIP() << "Skip data path for offload";                                     \
+        }                                                                                     \
+    })
\ No newline at end of file
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 8828c41..0354e3c 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -51,7 +51,7 @@
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
-        Parameter::Specific specific = getDefaultParamSpecific();
+        auto specific = getDefaultParamSpecific();
         Parameter::Common common = EffectHelper::createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
                 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
@@ -65,8 +65,13 @@
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
     }
 
-    Parameter::Specific getDefaultParamSpecific() {
-        AcousticEchoCanceler aec = AcousticEchoCanceler::make<AcousticEchoCanceler::echoDelayUs>(0);
+    std::optional<Parameter::Specific> getDefaultParamSpecific() {
+        auto aec = AcousticEchoCanceler::make<AcousticEchoCanceler::echoDelayUs>(0);
+        if (!isParameterValid<AcousticEchoCanceler, Range::acousticEchoCanceler>(aec,
+                                                                                 mDescriptor)) {
+            return std::nullopt;
+        }
+
         Parameter::Specific specific =
                 Parameter::Specific::make<Parameter::Specific::acousticEchoCanceler>(aec);
         return specific;
@@ -162,10 +167,8 @@
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string echoDelay = std::to_string(std::get<PARAM_ECHO_DELAY>(info.param));
             std::string mobileMode = std::get<PARAM_MOBILE_MODE>(info.param) ? "true" : "false";
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_EchoDelay_" + echoDelay +
-                               "_MobileMode_" + mobileMode;
+            std::string name =
+                    getPrefix(descriptor) + "_EchoDelay_" + echoDelay + "_MobileMode_" + mobileMode;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index edfcdf6..65c6a8f 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -177,11 +177,9 @@
                     std::to_string(std::get<PARAM_MAX_COMPRESSION_GAIN>(info.param));
             std::string enableLimiter = std::to_string(std::get<PARAM_ENABLE_LIMITER>(info.param));
 
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_target_peak_level_" +
-                               targetPeakLevel + "_max_compression_gain_" + maxCompressionGain +
-                               "_enable_limiter_" + enableLimiter;
+            std::string name = getPrefix(descriptor) + "_target_peak_level_" + targetPeakLevel +
+                               "_max_compression_gain_" + maxCompressionGain + "_enable_limiter_" +
+                               enableLimiter;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 8ba8e45..46a569e 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -183,9 +183,7 @@
             std::string margin =
                     std::to_string(static_cast<int>(std::get<PARAM_SATURATION_MARGIN>(info.param)));
 
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_digital_gain_" + gain +
+            std::string name = getPrefix(descriptor) + "_digital_gain_" + gain +
                                "_level_estimator_" + estimator + "_margin_" + margin;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index e5e06eb..f82e8e5 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -20,21 +20,27 @@
 #include <unordered_set>
 #include <vector>
 
+#define LOG_TAG "VtsHalAudioCore.Config"
+
+#include <Utils.h>
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
 #include <aidl/android/hardware/audio/core/IConfig.h>
 #include <aidl/android/media/audio/common/AudioFlag.h>
 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
-#define LOG_TAG "VtsHalAudioCore.Config"
 #include <android-base/logging.h>
 
 #include "AudioHalBinderServiceUtil.h"
 #include "TestUtils.h"
 
 using namespace android;
+using aidl::android::hardware::audio::common::isDefaultAudioFormat;
 using aidl::android::hardware::audio::core::IConfig;
+using aidl::android::hardware::audio::core::SurroundSoundConfig;
 using aidl::android::media::audio::common::AudioAttributes;
 using aidl::android::media::audio::common::AudioFlag;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioHalAttributesGroup;
 using aidl::android::media::audio::common::AudioHalCapCriterion;
 using aidl::android::media::audio::common::AudioHalCapCriterionType;
@@ -46,6 +52,7 @@
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::PcmType;
 
 class AudioCoreConfig : public testing::TestWithParam<std::string> {
   public:
@@ -58,6 +65,7 @@
     void RestartService() {
         ASSERT_NE(mConfig, nullptr);
         mEngineConfig.reset();
+        mSurroundSoundConfig.reset();
         mConfig = IConfig::fromBinder(mBinderUtil.restartService());
         ASSERT_NE(mConfig, nullptr);
     }
@@ -70,6 +78,14 @@
         }
     }
 
+    void SetUpSurroundSoundConfig() {
+        if (mSurroundSoundConfig == nullptr) {
+            auto tempConfig = std::make_unique<SurroundSoundConfig>();
+            ASSERT_IS_OK(mConfig->getSurroundSoundConfig(tempConfig.get()));
+            mSurroundSoundConfig = std::move(tempConfig);
+        }
+    }
+
     static bool IsProductStrategyTypeReservedForSystemUse(const AudioProductStrategyType& pst) {
         switch (pst) {
             case AudioProductStrategyType::SYS_RESERVED_NONE:
@@ -325,9 +341,41 @@
         }
     }
 
+    void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
+        EXPECT_NE(AudioFormatType::SYS_RESERVED_INVALID, format.type);
+        if (format.type == AudioFormatType::PCM) {
+            EXPECT_NE(PcmType::DEFAULT, format.pcm);
+            EXPECT_TRUE(format.encoding.empty()) << format.encoding;
+        } else {
+            EXPECT_FALSE(format.encoding.empty());
+        }
+    }
+
+    /**
+     * Verify that the surround sound configuration is not empty.
+     * Verify each of the formatFamilies has a non-empty primaryFormat.
+     * Verify that each format only appears once.
+     */
+    void ValidateSurroundSoundConfig() {
+        EXPECT_FALSE(mSurroundSoundConfig->formatFamilies.empty());
+        std::set<AudioFormatDescription> formatSet;
+        for (const SurroundSoundConfig::SurroundFormatFamily& family :
+             mSurroundSoundConfig->formatFamilies) {
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
+            EXPECT_FALSE(isDefaultAudioFormat(family.primaryFormat));
+            EXPECT_TRUE(formatSet.insert(family.primaryFormat).second);
+            for (const AudioFormatDescription& subformat : family.subFormats) {
+                EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(subformat));
+                EXPECT_FALSE(isDefaultAudioFormat(subformat));
+                EXPECT_TRUE(formatSet.insert(subformat).second);
+            }
+        }
+    }
+
   private:
     std::shared_ptr<IConfig> mConfig;
     std::unique_ptr<AudioHalEngineConfig> mEngineConfig;
+    std::unique_ptr<SurroundSoundConfig> mSurroundSoundConfig;
     AudioHalBinderServiceUtil mBinderUtil;
 };
 
@@ -344,6 +392,11 @@
     EXPECT_NO_FATAL_FAILURE(ValidateAudioHalEngineConfig());
 }
 
+TEST_P(AudioCoreConfig, GetSurroundSoundConfigIsValid) {
+    ASSERT_NO_FATAL_FAILURE(SetUpSurroundSoundConfig());
+    EXPECT_NO_FATAL_FAILURE(ValidateSurroundSoundConfig());
+}
+
 INSTANTIATE_TEST_SUITE_P(AudioCoreConfigTest, AudioCoreConfig,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IConfig::descriptor)),
                          android::PrintInstanceNameToString);
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 825b865..8a8998e 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -1379,7 +1379,7 @@
                     << "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
                     << " and " << port.id;
             primaryMixPort = port.id;
-            EXPECT_EQ(1, mixPort.maxOpenStreamCount)
+            EXPECT_GE(mixPort.maxOpenStreamCount, 0)
                     << "Primary mix port " << port.id << " can not have maxOpenStreamCount "
                     << mixPort.maxOpenStreamCount;
         }
@@ -1627,14 +1627,17 @@
     if (ports.empty()) {
         GTEST_SKIP() << "No external devices in the module.";
     }
-    AudioPort ignored;
     WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(*debug);
     doNotSimulateConnections.flags().simulateDeviceConnections = false;
     ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
     for (const auto& port : ports) {
-        AudioPort portWithData = GenerateUniqueDeviceAddress(port);
-        EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
-                << "static port " << portWithData.toString();
+        AudioPort portWithData = GenerateUniqueDeviceAddress(port), connectedPort;
+        ScopedAStatus status = module->connectExternalDevice(portWithData, &connectedPort);
+        EXPECT_STATUS(EX_ILLEGAL_STATE, status) << "static port " << portWithData.toString();
+        if (status.isOk()) {
+            EXPECT_IS_OK(module->disconnectExternalDevice(connectedPort.id))
+                    << "when disconnecting device port ID " << connectedPort.id;
+        }
     }
 }
 
@@ -2763,6 +2766,7 @@
             ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
             std::vector<MicrophoneDynamicInfo> activeMics;
             EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+            EXPECT_FALSE(activeMics.empty());
             for (const auto& mic : activeMics) {
                 EXPECT_NE(micInfos.end(),
                           std::find_if(micInfos.begin(), micInfos.end(),
@@ -3188,10 +3192,17 @@
     std::string mUnexpectedTransition;
 };
 
-enum { NAMED_CMD_NAME, NAMED_CMD_DELAY_MS, NAMED_CMD_STREAM_TYPE, NAMED_CMD_CMDS };
+enum {
+    NAMED_CMD_NAME,
+    NAMED_CMD_DELAY_MS,
+    NAMED_CMD_STREAM_TYPE,
+    NAMED_CMD_CMDS,
+    NAMED_CMD_VALIDATE_POS_INCREASE
+};
 enum class StreamTypeFilter { ANY, SYNC, ASYNC };
 using NamedCommandSequence =
-        std::tuple<std::string, int, StreamTypeFilter, std::shared_ptr<StateSequence>>;
+        std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
+                   std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
 enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
 using StreamIoTestParameters =
         std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
@@ -3235,10 +3246,14 @@
             ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
             const auto& commandsAndStates =
                     std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
+            const bool validatePositionIncrease =
+                    std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
             if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
             } else {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
             }
             if (isNonBlocking) {
                 // Also try running the same sequence with "aosp.forceTransientBurst" set.
@@ -3249,11 +3264,11 @@
                 if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     } else {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     }
                 }
             } else if (!IOTraits<Stream>::is_input) {
@@ -3266,11 +3281,11 @@
                 if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     } else {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     }
                 }
             }
@@ -3284,11 +3299,13 @@
 
     // Set up a patch first, then open a stream.
     void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
-                                     std::shared_ptr<StateSequence> commandsAndStates) {
+                                     std::shared_ptr<StateSequence> commandsAndStates,
+                                     bool validatePositionIncrease) {
         auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
                 IOTraits<Stream>::is_input, portConfig);
         ASSERT_FALSE(devicePorts.empty());
         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        SCOPED_TRACE(devicePortConfig.toString());
         WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
 
@@ -3306,14 +3323,17 @@
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
         if (ValidateObservablePosition(devicePortConfig)) {
-            EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            if (validatePositionIncrease) {
+                EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            }
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
     }
 
     // Open a stream, then set up a patch for it.
     void RunStreamIoCommandsImplSeq2(const AudioPortConfig& portConfig,
-                                     std::shared_ptr<StateSequence> commandsAndStates) {
+                                     std::shared_ptr<StateSequence> commandsAndStates,
+                                     bool validatePositionIncrease) {
         WithStream<Stream> stream(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
         StreamLogicDefaultDriver driver(commandsAndStates,
@@ -3325,6 +3345,7 @@
                 IOTraits<Stream>::is_input, portConfig);
         ASSERT_FALSE(devicePorts.empty());
         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        SCOPED_TRACE(devicePortConfig.toString());
         WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
 
@@ -3335,7 +3356,9 @@
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
         if (ValidateObservablePosition(devicePortConfig)) {
-            EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            if (validatePositionIncrease) {
+                EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            }
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
     }
@@ -3672,22 +3695,28 @@
     using State = StreamDescriptor::State;
     auto d = std::make_unique<StateDag>();
     StateDag::Node last = d->makeFinalNode(State::ACTIVE);
-    StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, last);
+    // Use a couple of bursts to ensure that the driver starts reporting the position.
+    StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
+    StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, active2);
     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
     if (!isSync) {
         // Allow optional routing via the TRANSFERRING state on bursts.
-        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+        active2.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active2));
         idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
     }
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kReadSeq =
-        std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true));
+        std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
+                        true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteSyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true));
+        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
+                        true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteAsyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false));
+        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
+                        true /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
     using State = StreamDescriptor::State;
@@ -3715,11 +3744,12 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kWriteDrainAsyncSeq =
-        std::make_tuple(std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false));
-static const NamedCommandSequence kDrainInSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::ANY, makeAsyncDrainCommands(true));
+static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
+        std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainInSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
+                        makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3739,10 +3769,12 @@
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kDrainOutSyncSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true));
-static const NamedCommandSequence kDrainOutAsyncSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::ASYNC, makeDrainOutCommands(false));
+static const NamedCommandSequence kDrainOutSyncSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
+                        false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainOutAsyncSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
+                        makeDrainOutCommands(false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3763,12 +3795,12 @@
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kDrainPauseOutSyncSeq =
-        std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::SYNC, makeDrainPauseOutCommands(true));
-static const NamedCommandSequence kDrainPauseOutAsyncSeq =
-        std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeDrainPauseOutCommands(false));
+static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
+        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
+        makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
+        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
 
 // This sequence also verifies that the capture / presentation position is not reset on standby.
 std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
@@ -3809,13 +3841,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kStandbyInSeq = std::make_tuple(
-        std::string("Standby"), 0, StreamTypeFilter::ANY, makeStandbyCommands(true, false));
-static const NamedCommandSequence kStandbyOutSyncSeq = std::make_tuple(
-        std::string("Standby"), 0, StreamTypeFilter::SYNC, makeStandbyCommands(false, true));
-static const NamedCommandSequence kStandbyOutAsyncSeq =
-        std::make_tuple(std::string("Standby"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeStandbyCommands(false, false));
+static const NamedCommandSequence kStandbyInSeq =
+        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
+                        makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutSyncSeq =
+        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
+                        makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
+        std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -3850,13 +3884,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kPauseInSeq = std::make_tuple(
-        std::string("Pause"), 0, StreamTypeFilter::ANY, makePauseCommands(true, false));
-static const NamedCommandSequence kPauseOutSyncSeq = std::make_tuple(
-        std::string("Pause"), 0, StreamTypeFilter::SYNC, makePauseCommands(false, true));
-static const NamedCommandSequence kPauseOutAsyncSeq =
-        std::make_tuple(std::string("Pause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makePauseCommands(false, false));
+static const NamedCommandSequence kPauseInSeq =
+        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
+                        makePauseCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutSyncSeq =
+        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
+                        makePauseCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
+        std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makePauseCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -3883,13 +3919,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kFlushInSeq = std::make_tuple(
-        std::string("Flush"), 0, StreamTypeFilter::ANY, makeFlushCommands(true, false));
-static const NamedCommandSequence kFlushOutSyncSeq = std::make_tuple(
-        std::string("Flush"), 0, StreamTypeFilter::SYNC, makeFlushCommands(false, true));
-static const NamedCommandSequence kFlushOutAsyncSeq =
-        std::make_tuple(std::string("Flush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeFlushCommands(false, false));
+static const NamedCommandSequence kFlushInSeq =
+        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
+                        makeFlushCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutSyncSeq =
+        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
+                        makeFlushCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
+        std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeFlushCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3910,10 +3948,12 @@
 }
 static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true));
+                        StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
+                        false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false));
+                        StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
+                        false /*validatePositionIncrease*/);
 
 // Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
 std::string PrintStreamFilterToString(StreamTypeFilter filter) {
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
index dfc1039..9d3adc1 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
@@ -25,6 +25,11 @@
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalAudioCoreTargetTest->/data/local/tmp/VtsHalAudioCoreTargetTest" />
+    </target_preparer>
+
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalAudioCoreTargetTest" />
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 9cd6c22..225640e 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -36,6 +36,11 @@
 #include "EffectFactoryHelper.h"
 #include "TestUtils.h"
 
+#include <system/audio_aidl_utils.h>
+
+using namespace android;
+using ::android::audio::utils::toString;
+
 using namespace android;
 
 using aidl::android::hardware::audio::effect::Descriptor;
@@ -93,7 +98,7 @@
             std::shared_ptr<IEffect> effect;
             EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(uuid, &effect));
             if (expectStatus == EX_NONE) {
-                EXPECT_NE(effect, nullptr) << " null effect with uuid: " << uuid.toString();
+                EXPECT_NE(effect, nullptr) << " null effect with uuid: " << toString(uuid);
                 effects.push_back(std::move(effect));
             }
         }
@@ -129,17 +134,18 @@
 /**
  * @brief Check at least support list of effect must be supported by aosp:
  * https://developer.android.com/reference/android/media/audiofx/AudioEffect
+ *
+ * For Android 13, they are: Equalizer, LoudnessEnhancer, Visualizer, and DynamicsProcessing.
+ * https://source.android.com/docs/compatibility/13/android-13-cdd#552_audio_effects
  */
-TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
+TEST_P(EffectFactoryTest, SupportMandatoryEffectTypes) {
     std::vector<Descriptor> descs;
-    std::set<AudioUuid> typeUuidSet(
-            {aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator(),
-             aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()});
+    std::set<AudioUuid> typeUuidSet({
+            aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
+            aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
+            aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer(),
+            aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer(),
+    });
 
     EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
     EXPECT_TRUE(descs.size() >= typeUuidSet.size());
@@ -148,7 +154,7 @@
     }
     std::string msg = " missing type UUID:\n";
     for (const auto& uuid : typeUuidSet) {
-        msg += (uuid.toString() + "\n");
+        msg += (toString(uuid) + "\n");
     }
     SCOPED_TRACE(msg);
     EXPECT_EQ(0UL, typeUuidSet.size());
@@ -300,4 +306,4 @@
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 436f2a3..3011a5e 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -46,6 +46,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::Flags;
 using aidl::android::media::audio::common::AudioDeviceDescription;
 using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioMode;
@@ -85,6 +86,14 @@
     }
 };
 
+class AudioEffectDataPathTest : public AudioEffectTest {
+    public:
+        void SetUp() override {
+            AudioEffectTest::SetUp();
+            SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        }
+};
+
 TEST_P(AudioEffectTest, SetupAndTearDown) {
     // Intentionally empty test body.
 }
@@ -577,7 +586,8 @@
 
 /// Data processing test
 // Send data to effects and expect it to be consumed by checking statusMQ.
-TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataInProcessingState) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -610,7 +620,8 @@
 }
 
 // Send data to effects and expect it to be consumed after effect restart.
-TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataAfterRestart) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -649,7 +660,8 @@
 }
 
 // Send data to IDLE effects and expect it to be consumed after effect start.
-TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, SendDataAtIdleAndConsumeDataInProcessing) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -682,7 +694,8 @@
 }
 
 // Send data multiple times.
-TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ProcessDataMultipleTimes) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -721,7 +734,8 @@
 }
 
 // Send data to processing state effects, stop, and restart.
-TEST_P(AudioEffectTest, ConsumeDataAndRestart) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataAndRestart) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -762,7 +776,8 @@
 }
 
 // Send data to closed effects and expect it not be consumed.
-TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, NotConsumeDataByClosedEffect) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
     Parameter::Common common = EffectHelper::createParamCommon(
@@ -788,7 +803,8 @@
 }
 
 // Send data to multiple effects.
-TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
+// Effects exposing bypass flags or operating in offload mode will be skipped.
+TEST_P(AudioEffectDataPathTest, ConsumeDataMultipleEffects) {
     std::shared_ptr<IEffect> effect1, effect2;
     ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
     ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
@@ -848,16 +864,27 @@
                 EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
         [](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_TYPE_" +
-                               descriptor.common.id.type.toString() + "_UUID_" +
-                               descriptor.common.id.uuid.toString();
+            std::string name = getPrefix(descriptor);
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
 
+INSTANTIATE_TEST_SUITE_P(
+        SingleEffectInstanceTest, AudioEffectDataPathTest,
+        ::testing::Combine(testing::ValuesIn(
+                EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
+        [](const testing::TestParamInfo<AudioEffectDataPathTest::ParamType>& info) {
+            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+            std::string name = getPrefix(descriptor);
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectDataPathTest);
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
     ABinderProcess_setThreadPoolMaxThreadCount(1);
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 9cfdc50..afddb84 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -145,9 +145,7 @@
         [](const testing::TestParamInfo<BassBoostParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_strength_" + strength;
+            std::string name = getPrefix(descriptor) + "_strength_" + strength;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index 5aeebde..7a2f31b 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -126,9 +126,7 @@
         [](const testing::TestParamInfo<DownmixParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string type = std::to_string(static_cast<int>(std::get<PARAM_TYPE>(info.param)));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_type" + type;
+            std::string name = getPrefix(descriptor) + "_type" + type;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 033e3b5..5509c76 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -513,9 +513,7 @@
             auto descriptor = std::get<ENGINE_TEST_INSTANCE_NAME>(info.param).second;
             DynamicsProcessing::EngineArchitecture cfg;
             fillEngineArchConfig(cfg, info.param);
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_Cfg_" + cfg.toString();
+            std::string name = getPrefix(descriptor) + "_Cfg_" + cfg.toString();
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 05c2c5b..f2ef185 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -209,9 +209,7 @@
             auto descriptor = std::get<0>(info.param).second;
             std::string roomLevel = std::to_string(std::get<1>(info.param));
 
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_roomLevel" + roomLevel;
+            std::string name = getPrefix(descriptor) + "_roomLevel" + roomLevel;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 716a2c6..37e7c0a 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -209,9 +209,7 @@
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string bandLevel =
                     ::android::internal::ToString(std::get<PARAM_BAND_LEVEL>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_preset_" +
+            std::string name = getPrefix(descriptor) + "_preset_" +
                                std::to_string(std::get<PARAM_PRESET>(info.param)) + "_bandLevel_" +
                                bandLevel;
             std::replace_if(
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index 7c79d1b..b33234b 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -195,12 +195,10 @@
                     std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
             std::string maxAmplitude =
                     std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_hapticScaleId" +
-                               hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
-                               "_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
-                               "_maxAmplitude" + maxAmplitude;
+            std::string name = getPrefix(descriptor) + "_hapticScaleId" + hapticScaleID +
+                               "_hapticScaleVibScale" + hapticScaleVibScale + "_resonantFrequency" +
+                               resonantFrequency + "_qFactor" + qFactor + "_maxAmplitude" +
+                               maxAmplitude;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
@@ -210,7 +208,7 @@
         HapticGeneratorInvalidTest, HapticGeneratorParamTest,
         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                    IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
-                           testing::Values(MIN_ID - 1),
+                           testing::Values(MIN_ID),
                            testing::Values(HapticGenerator::VibratorScale::NONE),
                            testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
                            testing::Values(MIN_FLOAT)),
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 96b048e..cbb80a9 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -131,9 +131,7 @@
         [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_gainMb_" + gainMb;
+            std::string name = getPrefix(descriptor) + "_gainMb_" + gainMb;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index 5525c80..624d5d2 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -48,7 +48,7 @@
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
-        Parameter::Specific specific = getDefaultParamSpecific();
+        std::optional<Parameter::Specific> specific = getDefaultParamSpecific();
         Parameter::Common common = EffectHelper::createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
                 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
@@ -62,9 +62,13 @@
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
     }
 
-    Parameter::Specific getDefaultParamSpecific() {
+    std::optional<Parameter::Specific> getDefaultParamSpecific() {
         NoiseSuppression ns =
                 NoiseSuppression::make<NoiseSuppression::level>(NoiseSuppression::Level::MEDIUM);
+        if (!isParameterValid<NoiseSuppression, Range::noiseSuppression>(ns, mDescriptor)) {
+            return std::nullopt;
+        }
+
         Parameter::Specific specific =
                 Parameter::Specific::make<Parameter::Specific::noiseSuppression>(ns);
         return specific;
@@ -85,7 +89,9 @@
             // validate parameter
             Descriptor desc;
             ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
-            const binder_exception_t expected = EX_NONE;
+            const bool valid =
+                    isParameterValid<NoiseSuppression, Range::noiseSuppression>(ns, desc);
+            const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
 
             // set parameter
             Parameter expectParam;
@@ -155,10 +161,7 @@
                     std::get<PARAM_LEVEL>(info.param));
             std::string type = aidl::android::hardware::audio::effect::toString(
                     std::get<PARAM_TYPE>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_level_" + level + "_type_" +
-                               type;
+            std::string name = getPrefix(descriptor) + "_level_" + level + "_type_" + type;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 8fb4ebf..3056c6c 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -137,9 +137,7 @@
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string preset =
                     std::to_string(static_cast<int>(std::get<PARAM_PRESETS>(info.param)));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_preset" + preset;
+            std::string name = getPrefix(descriptor) + "_preset" + preset;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index 6b1da63..07a9fa4 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -141,9 +141,7 @@
         [](const testing::TestParamInfo<VirtualizerParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_strength" + strength;
+            std::string name = getPrefix(descriptor) + "_strength" + strength;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index f41ba30..903ba69 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -195,9 +195,7 @@
                     std::get<PARAM_MEASUREMENT_MODE>(info.param));
             std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
 
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_captureSize" + captureSize +
+            std::string name = getPrefix(descriptor) + "_captureSize" + captureSize +
                                "_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
                                "_latency" + latency;
             std::replace_if(
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 90b7f37..0b5b9fc 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -149,10 +149,7 @@
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string level = std::to_string(std::get<PARAM_LEVEL>(info.param));
             std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_level" + level + "_mute" +
-                               mute;
+            std::string name = getPrefix(descriptor) + "_level" + level + "_mute" + mute;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/common/all-versions/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
index 757f8a8..c6a3963 100644
--- a/audio/common/all-versions/test/utility/Android.bp
+++ b/audio/common/all-versions/test/utility/Android.bp
@@ -62,6 +62,5 @@
         "libxml2",
         "liblog",
     ],
-    static_libs: ["libgtest"],
     test_suites: ["general-tests"],
 }
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index e21eff2..4d8a208 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -51,7 +51,7 @@
     Result retval = getParam(name, &halValue);
     *value = false;
     if (retval == Result::OK) {
-        if (halValue.empty()) {
+        if (halValue.length() == 0) {
             return Result::NOT_SUPPORTED;
         }
         *value = !(halValue == AudioParameter::valueOff);
@@ -97,17 +97,17 @@
             retval = getHalStatusToResult(status);
             break;
         }
-        result[i].key = halKey.string();
-        result[i].value = halValue.string();
+        result[i].key = halKey.c_str();
+        result[i].value = halValue.c_str();
     }
     cb(retval, result);
 }
 
 std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
     String8 paramsAndValues;
-    char* halValues = halGetParameters(keys.keysToString().string());
+    char* halValues = halGetParameters(keys.keysToString().c_str());
     if (halValues != NULL) {
-        paramsAndValues.setTo(halValues);
+        paramsAndValues = halValues;
         free(halValues);
     } else {
         paramsAndValues.clear();
@@ -163,7 +163,7 @@
 }
 
 Result ParametersUtil::setParams(const AudioParameter& param) {
-    int halStatus = halSetParameters(param.toString().string());
+    int halStatus = halSetParameters(param.toString().c_str());
     return util::analyzeStatus(halStatus);
 }
 
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 8e85a8b..c11b675 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -114,7 +114,7 @@
     SampleRateSet halSampleRates;
     if (result == Result::OK) {
         halSampleRates =
-            samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
+                samplingRatesFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
         sampleRates = hidl_vec<uint32_t>(halSampleRates.begin(), halSampleRates.end());
         // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
         // Note that this method must succeed (non empty list) if the format is supported.
@@ -140,7 +140,7 @@
     ChannelMaskSet halChannelMasks;
     if (result == Result::OK) {
         halChannelMasks =
-            channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
+                channelMasksFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
         channelMasks.resize(halChannelMasks.size());
         size_t i = 0;
         for (auto channelMask : halChannelMasks) {
@@ -182,7 +182,7 @@
     hidl_vec<AudioFormat> formats;
     FormatVector halFormats;
     if (result == Result::OK) {
-        halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
+        halFormats = formatsFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
         formats.resize(halFormats.size());
         for (size_t i = 0; i < halFormats.size(); ++i) {
             formats[i] = AudioFormat(halFormats[i]);
@@ -226,7 +226,7 @@
     // Ensure that the separator is one character, despite that it's defined as a C string.
     static_assert(sizeof(AUDIO_PARAMETER_VALUE_LIST_SEPARATOR) == 2);
     std::vector<std::string> halFormats =
-            splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+            splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
     hidl_vec<AudioFormat> formats;
     (void)HidlUtils::audioFormatsFromHal(halFormats, &formats);
     std::vector<AudioProfile> tempProfiles;
@@ -241,7 +241,7 @@
         result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
         if (result != Result::OK) break;
         std::vector<std::string> halSampleRates =
-                splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+                splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
         hidl_vec<uint32_t> sampleRates;
         sampleRates.resize(halSampleRates.size());
         for (size_t i = 0; i < sampleRates.size(); ++i) {
@@ -251,7 +251,7 @@
         result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
         if (result != Result::OK) break;
         std::vector<std::string> halChannelMasks =
-                splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+                splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
         hidl_vec<AudioChannelMask> channelMasks;
         (void)HidlUtils::audioChannelMasksFromHal(halChannelMasks, &channelMasks);
         // Create a profile.
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 5aecd32..4a9e144 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -315,7 +315,7 @@
 
 Effect::~Effect() {
     ATRACE_CALL();
-    (void)close();
+    auto [_, handle] = closeImpl();
     if (mProcessThread.get()) {
         ATRACE_NAME("mProcessThread->join");
         status_t status = mProcessThread->join();
@@ -328,11 +328,10 @@
     mInBuffer.clear();
     mOutBuffer.clear();
 #if MAJOR_VERSION <= 5
-    int status = EffectRelease(mHandle);
-    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+    int status = EffectRelease(handle);
+    ALOGW_IF(status, "Error releasing effect %p: %s", handle, strerror(-status));
 #endif
-    EffectMap::getInstance().remove(mHandle);
-    mHandle = 0;
+    EffectMap::getInstance().remove(handle);
 }
 
 // static
@@ -459,7 +458,19 @@
     }
 }
 
-void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
+#define RETURN_IF_EFFECT_CLOSED()          \
+    if (mHandle == kInvalidEffectHandle) { \
+        return Result::INVALID_STATE;      \
+    }
+#define RETURN_RESULT_IF_EFFECT_CLOSED(result)   \
+    if (mHandle == kInvalidEffectHandle) {       \
+        _hidl_cb(Result::INVALID_STATE, result); \
+        return Void();                           \
+    }
+
+Return<void> Effect::getConfigImpl(int commandCode, const char* commandName,
+                                   GetConfigCallback _hidl_cb) {
+    RETURN_RESULT_IF_EFFECT_CLOSED(EffectConfig());
     uint32_t halResultSize = sizeof(effect_config_t);
     effect_config_t halConfig{};
     status_t status =
@@ -468,7 +479,8 @@
     if (status == OK) {
         status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
     }
-    cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+    _hidl_cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+    return Void();
 }
 
 Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
@@ -530,6 +542,7 @@
 }
 
 Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
     status_t status;
     // Create message queue.
     if (mStatusMQ) {
@@ -576,6 +589,7 @@
 
 Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
                                          const AudioBuffer& outBuffer) {
+    RETURN_IF_EFFECT_CLOSED();
     AudioBufferManager& manager = AudioBufferManager::getInstance();
     sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
     if (!manager.wrap(inBuffer, &tempInBuffer)) {
@@ -600,6 +614,7 @@
 }
 
 Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
+    RETURN_IF_EFFECT_CLOSED();
     status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
     return analyzeCommandStatus(commandName, sContextCallToCommand, status);
 }
@@ -611,6 +626,7 @@
 
 Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
                                         void* data, uint32_t* replySize, void* replyData) {
+    RETURN_IF_EFFECT_CLOSED();
     uint32_t expectedReplySize = *replySize;
     status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
     if (status == OK && *replySize != expectedReplySize) {
@@ -635,6 +651,7 @@
                                                  uint32_t size, void* data, uint32_t* replySize,
                                                  void* replyData, uint32_t minReplySize,
                                                  CommandSuccessCallback onSuccess) {
+    RETURN_IF_EFFECT_CLOSED();
     status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
     Result retval;
     if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
@@ -792,13 +809,11 @@
 }
 
 Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
-    getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
-    return Void();
+    return getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
 }
 
 Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
-    getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
-    return Void();
+    return getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
 }
 
 Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
@@ -845,6 +860,7 @@
 }
 
 Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    RETURN_RESULT_IF_EFFECT_CLOSED(EffectDescriptor());
     effect_descriptor_t halDescriptor;
     memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
     status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
@@ -858,6 +874,10 @@
 
 Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
                              uint32_t resultMaxSize, command_cb _hidl_cb) {
+    if (mHandle == kInvalidEffectHandle) {
+        _hidl_cb(-ENODATA, hidl_vec<uint8_t>());
+        return Void();
+    }
     uint32_t halDataSize;
     std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
     uint32_t halResultSize = resultMaxSize;
@@ -942,26 +962,33 @@
                                       halCmd.size(), &halCmd[0]);
 }
 
-Return<Result> Effect::close() {
+std::tuple<Result, effect_handle_t> Effect::closeImpl() {
     if (mStopProcessThread.load(std::memory_order_relaxed)) {  // only this thread modifies
-        return Result::INVALID_STATE;
+        return {Result::INVALID_STATE, kInvalidEffectHandle};
     }
     mStopProcessThread.store(true, std::memory_order_release);
     if (mEfGroup) {
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
     }
+    effect_handle_t handle = mHandle;
+    mHandle = kInvalidEffectHandle;
 #if MAJOR_VERSION <= 5
-    return Result::OK;
+    return {Result::OK, handle};
 #elif MAJOR_VERSION >= 6
     // No need to join the processing thread, it is part of the API contract that the client
     // must finish processing before closing the effect.
-    Result retval =
-            analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(mHandle));
-    EffectMap::getInstance().remove(mHandle);
-    return retval;
+    Result retval = analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(handle));
+    EffectMap::getInstance().remove(handle);
+    return {retval, handle};
 #endif
 }
 
+Return<Result> Effect::close() {
+    RETURN_IF_EFFECT_CLOSED();
+    auto [result, _] = closeImpl();
+    return result;
+}
+
 Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
         uint32_t cmdData = fd->data[0];
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 5d8dccc..2bcecec 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -23,6 +23,7 @@
 
 #include <atomic>
 #include <memory>
+#include <tuple>
 #include <vector>
 
 #include <fmq/EventFlag.h>
@@ -186,6 +187,7 @@
 
     // Sets the limit on the maximum size of vendor-provided data structures.
     static constexpr size_t kMaxDataSize = 1 << 20;
+    static constexpr effect_handle_t kInvalidEffectHandle = nullptr;
 
     static const char* sContextResultOfCommand;
     static const char* sContextCallToCommand;
@@ -208,6 +210,7 @@
     static size_t alignedSizeIn(size_t s);
     template <typename T>
     std::unique_ptr<uint8_t[]> hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize);
+    std::tuple<Result, effect_handle_t> closeImpl();
     void effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
                                         EffectAuxChannelsConfig* config);
     static void effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
@@ -218,7 +221,8 @@
                                const void** valueData, std::vector<uint8_t>* halParamBuffer);
 
     Result analyzeCommandStatus(const char* commandName, const char* context, status_t status);
-    void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
+    Return<void> getConfigImpl(int commandCode, const char* commandName,
+                               GetConfigCallback _hidl_cb);
     Result getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
                                 GetCurrentConfigSuccessCallback onSuccess);
     Result getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index d95bb06..ff84f9d 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -169,13 +169,15 @@
     0xfe3199be, 0xaed0, 0x413f, 0x87bb,
     std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}};
 
-enum { PARAM_FACTORY_NAME, PARAM_EFFECT_UUID };
-using EffectParameter = std::tuple<std::string, Uuid>;
+enum { PARAM_FACTORY_NAME, PARAM_EFFECT_UUID, PARAM_USE_AFTER_CLOSE };
+using EffectParameter = std::tuple<std::string, Uuid, bool>;
 
 static inline std::string EffectParameterToString(
         const ::testing::TestParamInfo<EffectParameter>& info) {
-    return ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
-            std::get<PARAM_FACTORY_NAME>(info.param), info.index});
+    std::string prefix = std::get<PARAM_USE_AFTER_CLOSE>(info.param) ? "UseAfterClose_" : "";
+    return prefix.append(
+            ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
+                    std::get<PARAM_FACTORY_NAME>(info.param), info.index}));
 }
 
 // The main test class for Audio Effect HIDL HAL.
@@ -191,6 +193,13 @@
         Return<Result> ret = effect->init();
         ASSERT_TRUE(ret.isOk());
         ASSERT_EQ(Result::OK, ret);
+
+        useAfterClose = std::get<PARAM_USE_AFTER_CLOSE>(GetParam());
+        if (useAfterClose) {
+            Return<Result> ret = effect->close();
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Result::OK, ret);
+        }
     }
 
     void TearDown() override {
@@ -205,14 +214,34 @@
 
     Uuid getEffectType() const { return std::get<PARAM_EFFECT_UUID>(GetParam()); }
 
+    void checkResult(const Result& result);
+    void checkResultForUseAfterClose(const Result& result);
     void findAndCreateEffect(const Uuid& type);
     void findEffectInstance(const Uuid& type, Uuid* uuid);
     void getChannelCount(uint32_t* channelCount);
 
     sp<IEffectsFactory> effectsFactory;
     sp<IEffect> effect;
+    bool useAfterClose;
 };
 
+void AudioEffectHidlTest::checkResult(const Result& result) {
+    if (!useAfterClose) {
+        ASSERT_EQ(Result::OK, result);
+    } else {
+        ASSERT_NO_FATAL_FAILURE(checkResultForUseAfterClose(result));
+    }
+}
+
+void AudioEffectHidlTest::checkResultForUseAfterClose(const Result& result) {
+    if (useAfterClose) {
+        // The actual error does not matter. It's important that the effect did not crash
+        // while executing any command after a call to "close", and that the returned status
+        // is not OK.
+        ASSERT_NE(Result::OK, result);
+    }
+}
+
 void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
     Uuid effectUuid;
     ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
@@ -257,7 +286,11 @@
         }
     });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) {
+        *channelCount = 1;
+        return;
+    }
 #if MAJOR_VERSION <= 6
     ASSERT_TRUE(audio_channel_mask_is_valid(
         static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
@@ -276,7 +309,7 @@
     description("Verify that an effect can be closed");
     Return<Result> ret = effect->close();
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    ASSERT_NO_FATAL_FAILURE(checkResult(ret));
 }
 
 TEST_P(AudioEffectHidlTest, GetDescriptor) {
@@ -290,7 +323,8 @@
         }
     });
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) return;
     EXPECT_EQ(getEffectType(), actualType);
 }
 
@@ -307,7 +341,8 @@
         }
     });
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, retval);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) return;
     Return<Result> ret2 = effect->setConfig(currentConfig, nullptr, nullptr);
     EXPECT_TRUE(ret2.isOk());
     EXPECT_EQ(Result::OK, ret2);
@@ -336,7 +371,8 @@
         }
     });
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, retval);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) return;
     for (const auto& invalidInputCfg : generateInvalidConfigs(currentConfig.inputCfg)) {
         EffectConfig invalidConfig = currentConfig;
         invalidConfig.inputCfg = invalidInputCfg;
@@ -356,27 +392,35 @@
 
 TEST_P(AudioEffectHidlTest, GetConfigReverse) {
     description("Verify that GetConfigReverse does not crash");
-    Return<void> ret = effect->getConfigReverse([&](Result, const EffectConfig&) {});
+    Result retval = Result::OK;
+    Return<void> ret = effect->getConfigReverse([&](Result r, const EffectConfig&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
 }
 
 TEST_P(AudioEffectHidlTest, GetSupportedAuxChannelsConfigs) {
     description("Verify that GetSupportedAuxChannelsConfigs does not crash");
+    Result retval = Result::OK;
     Return<void> ret = effect->getSupportedAuxChannelsConfigs(
-        0, [&](Result, const hidl_vec<EffectAuxChannelsConfig>&) {});
+            0, [&](Result r, const hidl_vec<EffectAuxChannelsConfig>&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
 }
 
 TEST_P(AudioEffectHidlTest, GetAuxChannelsConfig) {
     description("Verify that GetAuxChannelsConfig does not crash");
-    Return<void> ret = effect->getAuxChannelsConfig([&](Result, const EffectAuxChannelsConfig&) {});
+    Result retval = Result::OK;
+    Return<void> ret = effect->getAuxChannelsConfig(
+            [&](Result r, const EffectAuxChannelsConfig&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
 }
 
 TEST_P(AudioEffectHidlTest, SetAuxChannelsConfig) {
     description("Verify that SetAuxChannelsConfig does not crash");
     Return<Result> ret = effect->setAuxChannelsConfig(EffectAuxChannelsConfig());
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 // Not generated automatically because AudioBuffer contains
@@ -427,45 +471,56 @@
     description("Verify that Reset preserves effect configuration");
     Result retval = Result::NOT_INITIALIZED;
     EffectConfig originalConfig;
-    Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
-        retval = r;
-        if (r == Result::OK) {
-            originalConfig = conf;
-        }
-    });
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    if (!useAfterClose) {
+        Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+            retval = r;
+            if (r == Result::OK) {
+                originalConfig = conf;
+            }
+        });
+        ASSERT_TRUE(ret.isOk());
+        ASSERT_EQ(Result::OK, retval);
+    }
     Return<Result> ret2 = effect->reset();
     EXPECT_TRUE(ret2.isOk());
-    EXPECT_EQ(Result::OK, ret2);
-    EffectConfig configAfterReset;
-    ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
-        retval = r;
-        if (r == Result::OK) {
-            configAfterReset = conf;
-        }
-    });
-    EXPECT_EQ(originalConfig, configAfterReset);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret2));
+    if (!useAfterClose) {
+        EffectConfig configAfterReset;
+        Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+            retval = r;
+            if (r == Result::OK) {
+                configAfterReset = conf;
+            }
+        });
+        EXPECT_EQ(originalConfig, configAfterReset);
+    }
 }
 
 TEST_P(AudioEffectHidlTest, DisableEnableDisable) {
     description("Verify Disable -> Enable -> Disable sequence for an effect");
     Return<Result> ret = effect->disable();
     EXPECT_TRUE(ret.isOk());
-    // Note: some legacy effects may return -EINVAL (INVALID_ARGUMENTS),
-    //       more canonical is to return -ENOSYS (NOT_SUPPORTED)
-    EXPECT_TRUE(ret == Result::NOT_SUPPORTED || ret == Result::INVALID_ARGUMENTS);
+    if (!useAfterClose) {
+        // Note: some legacy effects may return -EINVAL (INVALID_ARGUMENTS),
+        //       more canonical is to return -ENOSYS (NOT_SUPPORTED)
+        EXPECT_TRUE(ret == Result::NOT_SUPPORTED || ret == Result::INVALID_ARGUMENTS);
+    } else {
+        EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
+    }
     ret = effect->enable();
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
     ret = effect->disable();
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
 }
 
 #if MAJOR_VERSION >= 7
 TEST_P(AudioEffectHidlTest, SetDeviceInvalidDeviceAddress) {
     description("Verify that invalid device address is rejected by SetDevice");
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     DeviceAddress device{.deviceType = "random_string"};
     Return<Result> ret = effect->setDevice(device);
     EXPECT_TRUE(ret.isOk());
@@ -482,13 +537,13 @@
     Return<Result> ret = effect->setDevice(device);
 #endif
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
 }
 
 TEST_P(AudioEffectHidlTest, SetAndGetVolume) {
     description("Verify that SetAndGetVolume method works for an effect");
     uint32_t channelCount;
-    getChannelCount(&channelCount);
+    ASSERT_NO_FATAL_FAILURE(getChannelCount(&channelCount));
     hidl_vec<uint32_t> volumes;
     volumes.resize(channelCount);
     for (uint32_t i = 0; i < channelCount; ++i) {
@@ -498,13 +553,13 @@
     Return<void> ret =
         effect->setAndGetVolume(volumes, [&](Result r, const hidl_vec<uint32_t>&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, retval);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
 }
 
 TEST_P(AudioEffectHidlTest, VolumeChangeNotification) {
     description("Verify that effect accepts VolumeChangeNotification");
     uint32_t channelCount;
-    getChannelCount(&channelCount);
+    ASSERT_NO_FATAL_FAILURE(getChannelCount(&channelCount));
     hidl_vec<uint32_t> volumes;
     volumes.resize(channelCount);
     for (uint32_t i = 0; i < channelCount; ++i) {
@@ -512,25 +567,29 @@
     }
     Return<Result> ret = effect->volumeChangeNotification(volumes);
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
 }
 
 TEST_P(AudioEffectHidlTest, SetAudioMode) {
     description("Verify that SetAudioMode works for an effect");
     Return<Result> ret = effect->setAudioMode(AudioMode::NORMAL);
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
 }
 
 TEST_P(AudioEffectHidlTest, SetConfigReverse) {
     description("Verify that SetConfigReverse does not crash");
     Return<Result> ret = effect->setConfigReverse(EffectConfig(), nullptr, nullptr);
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 #if MAJOR_VERSION >= 7
 TEST_P(AudioEffectHidlTest, SetInputDeviceInvalidDeviceAddress) {
     description("Verify that invalid device address is rejected by SetInputDevice");
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     DeviceAddress device{.deviceType = "random_string"};
     Return<Result> ret = effect->setInputDevice(device);
     EXPECT_TRUE(ret.isOk());
@@ -548,11 +607,15 @@
     Return<Result> ret = effect->setInputDevice(device);
 #endif
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 #if MAJOR_VERSION >= 7
 TEST_P(AudioEffectHidlTest, SetInvalidAudioSource) {
     description("Verify that an invalid audio source is rejected by SetAudioSource");
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     Return<Result> ret = effect->setAudioSource("random_string");
     ASSERT_TRUE(ret.isOk());
     EXPECT_TRUE(ret == Result::INVALID_ARGUMENTS || ret == Result::NOT_SUPPORTED)
@@ -568,12 +631,14 @@
     Return<Result> ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
 #endif
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 TEST_P(AudioEffectHidlTest, Offload) {
     description("Verify that calling Offload method does not crash");
     Return<Result> ret = effect->offload(EffectOffloadParameter{});
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 TEST_P(AudioEffectHidlTest, PrepareForProcessing) {
@@ -582,7 +647,7 @@
     Return<void> ret = effect->prepareForProcessing(
         [&](Result r, const MQDescriptorSync<Result>&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, retval);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
 }
 
 TEST_P(AudioEffectHidlTest, SetProcessBuffers) {
@@ -601,7 +666,7 @@
     ASSERT_TRUE(success);
     Return<Result> ret2 = effect->setProcessBuffers(buffer, buffer);
     EXPECT_TRUE(ret2.isOk());
-    EXPECT_EQ(Result::OK, ret2);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret2));
 }
 
 TEST_P(AudioEffectHidlTest, Command) {
@@ -615,6 +680,7 @@
     description("Verify that SetParameter does not crash");
     Return<Result> ret = effect->setParameter(hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
 }
 
 TEST_P(AudioEffectHidlTest, GetParameter) {
@@ -630,6 +696,9 @@
     if (!isNewDeviceLaunchingOnTPlus) {
         GTEST_SKIP() << "The test only applies to devices launching on T or later";
     }
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     // Use a non-empty parameter to avoid being rejected by any earlier checks.
     hidl_vec<uint8_t> parameter;
     parameter.resize(16);
@@ -647,16 +716,20 @@
 
 TEST_P(AudioEffectHidlTest, GetSupportedConfigsForFeature) {
     description("Verify that GetSupportedConfigsForFeature does not crash");
+    Result retval = Result::OK;
     Return<void> ret = effect->getSupportedConfigsForFeature(
-        0, 0, 0, [&](Result, uint32_t, const hidl_vec<uint8_t>&) {});
+            0, 0, 0, [&](Result r, uint32_t, const hidl_vec<uint8_t>&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
 }
 
 TEST_P(AudioEffectHidlTest, GetCurrentConfigForFeature) {
     description("Verify that GetCurrentConfigForFeature does not crash");
-    Return<void> ret =
-        effect->getCurrentConfigForFeature(0, 0, [&](Result, const hidl_vec<uint8_t>&) {});
+    Result retval = Result::OK;
+    Return<void> ret = effect->getCurrentConfigForFeature(
+            0, 0, [&](Result r, const hidl_vec<uint8_t>&) { retval = r; });
     EXPECT_TRUE(ret.isOk());
+    EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
 }
 
 TEST_P(AudioEffectHidlTest, SetCurrentConfigForFeature) {
@@ -671,6 +744,9 @@
     if (!isNewDeviceLaunchingOnTPlus) {
         GTEST_SKIP() << "The test only applies to devices launching on T or later";
     }
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     // Use very large size to ensure that the service does not crash.
     const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
     Result retval = Result::OK;
@@ -687,6 +763,9 @@
     if (!isNewDeviceLaunchingOnTPlus) {
         GTEST_SKIP() << "The test only applies to devices launching on T or later";
     }
+    if (useAfterClose) {
+        GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+    }
     // Use very large size to ensure that the service does not crash.
     const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
     Result retval = Result::OK;
@@ -729,7 +808,8 @@
         }
     });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) *numBands = 1;
 }
 
 void EqualizerAudioEffectHidlTest::getLevelRange(int16_t* minLevel, int16_t* maxLevel) {
@@ -742,7 +822,11 @@
         }
     });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) {
+        *minLevel = 0;
+        *maxLevel = 255;
+    }
 }
 
 void EqualizerAudioEffectHidlTest::getBandFrequencyRange(uint16_t band, uint32_t* minFreq,
@@ -757,7 +841,7 @@
             }
         });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
     ret = equalizer->getBandCenterFrequency(band, [&](Result r, uint32_t center) {
         retval = r;
         if (retval == Result::OK) {
@@ -765,7 +849,12 @@
         }
     });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) {
+        *minFreq = 20;
+        *centerFreq = 10000;
+        *maxFreq = 20000;
+    }
 }
 
 void EqualizerAudioEffectHidlTest::getPresetCount(size_t* count) {
@@ -777,37 +866,38 @@
         }
     });
     ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(Result::OK, retval);
+    ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+    if (useAfterClose) *count = 1;
 }
 
 TEST_P(EqualizerAudioEffectHidlTest, GetNumBands) {
     description("Verify that Equalizer effect reports at least one band");
     uint16_t numBands = 0;
-    getNumBands(&numBands);
+    ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
     EXPECT_GT(numBands, 0);
 }
 
 TEST_P(EqualizerAudioEffectHidlTest, GetLevelRange) {
     description("Verify that Equalizer effect reports adequate band level range");
     int16_t minLevel = 0x7fff, maxLevel = 0;
-    getLevelRange(&minLevel, &maxLevel);
+    ASSERT_NO_FATAL_FAILURE(getLevelRange(&minLevel, &maxLevel));
     EXPECT_GT(maxLevel, minLevel);
 }
 
 TEST_P(EqualizerAudioEffectHidlTest, GetSetBandLevel) {
     description("Verify that manipulating band levels works for Equalizer effect");
     uint16_t numBands = 0;
-    getNumBands(&numBands);
+    ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
     ASSERT_GT(numBands, 0);
     int16_t levels[3]{0x7fff, 0, 0};
-    getLevelRange(&levels[0], &levels[2]);
+    ASSERT_NO_FATAL_FAILURE(getLevelRange(&levels[0], &levels[2]));
     ASSERT_GT(levels[2], levels[0]);
     levels[1] = (levels[2] + levels[0]) / 2;
     for (uint16_t i = 0; i < numBands; ++i) {
         for (size_t j = 0; j < ARRAY_SIZE(levels); ++j) {
             Return<Result> ret = equalizer->setBandLevel(i, levels[j]);
             EXPECT_TRUE(ret.isOk());
-            EXPECT_EQ(Result::OK, ret);
+            EXPECT_NO_FATAL_FAILURE(checkResult(ret));
             Result retval = Result::NOT_INITIALIZED;
             int16_t actualLevel;
             Return<void> ret2 = equalizer->getBandLevel(i, [&](Result r, int16_t l) {
@@ -817,8 +907,10 @@
                 }
             });
             EXPECT_TRUE(ret2.isOk());
-            EXPECT_EQ(Result::OK, retval);
-            EXPECT_EQ(levels[j], actualLevel);
+            EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+            if (!useAfterClose) {
+                EXPECT_EQ(levels[j], actualLevel);
+            }
         }
     }
 }
@@ -826,11 +918,11 @@
 TEST_P(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) {
     description("Verify that Equalizer effect reports adequate band frequency range");
     uint16_t numBands = 0;
-    getNumBands(&numBands);
+    ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
     ASSERT_GT(numBands, 0);
     for (uint16_t i = 0; i < numBands; ++i) {
         uint32_t minFreq = 0xffffffff, centerFreq = 0xffffffff, maxFreq = 0xffffffff;
-        getBandFrequencyRange(i, &minFreq, &centerFreq, &maxFreq);
+        ASSERT_NO_FATAL_FAILURE(getBandFrequencyRange(i, &minFreq, &centerFreq, &maxFreq));
         // Note: NXP legacy implementation reports "1" as upper bound for last band,
         // so this check fails.
         EXPECT_GE(maxFreq, centerFreq);
@@ -841,7 +933,7 @@
 TEST_P(EqualizerAudioEffectHidlTest, GetBandForFrequency) {
     description("Verify that Equalizer effect supports GetBandForFrequency correctly");
     uint16_t numBands = 0;
-    getNumBands(&numBands);
+    ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
     ASSERT_GT(numBands, 0);
     for (uint16_t i = 0; i < numBands; ++i) {
         uint32_t freqs[3]{0, 0, 0};
@@ -861,8 +953,10 @@
                 }
             });
             EXPECT_TRUE(ret.isOk());
-            EXPECT_EQ(Result::OK, retval);
-            EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+            EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+            if (!useAfterClose) {
+                EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+            }
         }
     }
 }
@@ -870,19 +964,19 @@
 TEST_P(EqualizerAudioEffectHidlTest, GetPresetNames) {
     description("Verify that Equalizer effect reports at least one preset");
     size_t presetCount;
-    getPresetCount(&presetCount);
+    ASSERT_NO_FATAL_FAILURE(getPresetCount(&presetCount));
     EXPECT_GT(presetCount, 0u);
 }
 
 TEST_P(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) {
     description("Verify that manipulating the current preset for Equalizer effect");
     size_t presetCount;
-    getPresetCount(&presetCount);
+    ASSERT_NO_FATAL_FAILURE(getPresetCount(&presetCount));
     ASSERT_GT(presetCount, 0u);
     for (uint16_t i = 0; i < presetCount; ++i) {
         Return<Result> ret = equalizer->setCurrentPreset(i);
         EXPECT_TRUE(ret.isOk());
-        EXPECT_EQ(Result::OK, ret);
+        EXPECT_NO_FATAL_FAILURE(checkResult(ret));
         Result retval = Result::NOT_INITIALIZED;
         uint16_t actualPreset = 0xffff;
         Return<void> ret2 = equalizer->getCurrentPreset([&](Result r, uint16_t p) {
@@ -892,8 +986,10 @@
             }
         });
         EXPECT_TRUE(ret2.isOk());
-        EXPECT_EQ(Result::OK, retval);
-        EXPECT_EQ(i, actualPreset);
+        EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+        if (!useAfterClose) {
+            EXPECT_EQ(i, actualPreset);
+        }
     }
 }
 
@@ -904,7 +1000,7 @@
     using AllProperties =
         ::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect::AllProperties;
     uint16_t numBands = 0;
-    getNumBands(&numBands);
+    ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
     ASSERT_GT(numBands, 0);
     AllProperties props;
     props.bandLevels.resize(numBands);
@@ -919,7 +1015,7 @@
     props.curPreset = -1;
     Return<Result> ret = equalizer->setAllProperties(props);
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
     Return<void> ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
         retval = r;
         if (retval == Result::OK) {
@@ -927,14 +1023,16 @@
         }
     });
     EXPECT_TRUE(ret2.isOk());
-    EXPECT_EQ(Result::OK, retval);
-    EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+    if (!useAfterClose) {
+        EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+    }
 
     // Verify setting of the current preset via properties.
     props.curPreset = 0;  // Assuming there is at least one preset.
     ret = equalizer->setAllProperties(props);
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
     ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
         retval = r;
         if (retval == Result::OK) {
@@ -942,8 +1040,10 @@
         }
     });
     EXPECT_TRUE(ret2.isOk());
-    EXPECT_EQ(Result::OK, retval);
-    EXPECT_EQ(props.curPreset, actualProps.curPreset);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+    if (!useAfterClose) {
+        EXPECT_EQ(props.curPreset, actualProps.curPreset);
+    }
 }
 
 // The main test class for Equalizer Audio Effect HIDL HAL.
@@ -971,7 +1071,7 @@
     const int32_t gain = 100;
     Return<Result> ret = enhancer->setTargetGain(gain);
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::OK, ret);
+    EXPECT_NO_FATAL_FAILURE(checkResult(ret));
     int32_t actualGain = 0;
     Result retval;
     Return<void> ret2 = enhancer->getTargetGain([&](Result r, int32_t g) {
@@ -981,8 +1081,10 @@
         }
     });
     EXPECT_TRUE(ret2.isOk());
-    EXPECT_EQ(Result::OK, retval);
-    EXPECT_EQ(gain, actualGain);
+    EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+    if (!useAfterClose) {
+        EXPECT_EQ(gain, actualGain);
+    }
 }
 
 INSTANTIATE_TEST_SUITE_P(EffectsFactory, AudioEffectsFactoryHidlTest,
@@ -993,25 +1095,29 @@
         Equalizer_IEffect, AudioEffectHidlTest,
         ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
                                    IEffectsFactory::descriptor)),
-                           ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+                           ::testing::Values(EQUALIZER_EFFECT_TYPE),
+                           ::testing::Values(false, true) /*useAfterClose*/),
         EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
         LoudnessEnhancer_IEffect, AudioEffectHidlTest,
         ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
                                    IEffectsFactory::descriptor)),
-                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE),
+                           ::testing::Values(false, true) /*useAfterClose*/),
         EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
         Equalizer, EqualizerAudioEffectHidlTest,
         ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
                                    IEffectsFactory::descriptor)),
-                           ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+                           ::testing::Values(EQUALIZER_EFFECT_TYPE),
+                           ::testing::Values(false, true) /*useAfterClose*/),
         EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
         LoudnessEnhancer, LoudnessEnhancerAudioEffectHidlTest,
         ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
                                    IEffectsFactory::descriptor)),
-                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE),
+                           ::testing::Values(false, true) /*useAfterClose*/),
         EffectParameterToString);
 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
 // list is empty, this isn't a problem.
diff --git a/audio/policy/1.0/xml/pfw_schemas/Android.bp b/audio/policy/1.0/xml/pfw_schemas/Android.bp
index 5d669c2..225c065 100644
--- a/audio/policy/1.0/xml/pfw_schemas/Android.bp
+++ b/audio/policy/1.0/xml/pfw_schemas/Android.bp
@@ -11,6 +11,7 @@
     name: "audio_policy_engine_configurable_configuration_V1_0",
     srcs: ["AllSchemas.xsd"],
     package_name: "audio.policy.configurable.V1_0",
+    root_elements: ["ParameterFrameworkConfiguration"],
 }
 
 // Unfortunately, all rules only have a single output, thus
diff --git a/audio/policy/1.0/xml/pfw_schemas/api/current.txt b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
index c2fb6fc..2b83e60 100644
--- a/audio/policy/1.0/xml/pfw_schemas/api/current.txt
+++ b/audio/policy/1.0/xml/pfw_schemas/api/current.txt
@@ -470,23 +470,7 @@
 
   public class XmlParser {
     ctor public XmlParser();
-    method public static audio.policy.configurable.V1_0.BitParameterBlock readBitParameterBlock(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.BooleanParameter readBooleanParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.ComponentTypeSetType readComponentTypeSetType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.ConfigurableDomainType readConfigurableDomainType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.ConfigurableDomains readConfigurableDomains(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.EnumParameterType readEnumParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.FixedPointParameterType readFixedPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.FloatingPointParameterType readFloatingPointParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.IntegerParameterType readIntegerParameterType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.LinearAdaptationType readLinearAdaptationType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.LogarithmicAdaptation readLogarithmicAdaptation(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static audio.policy.configurable.V1_0.ParameterFrameworkConfiguration readParameterFrameworkConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.StringParameter readStringParameter(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.SubsystemPlugins readSubsystemPlugins(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.SubsystemType readSubsystemType(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static audio.policy.configurable.V1_0.SystemClass readSystemClass(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
   }
diff --git a/authsecret/aidl/default/Android.bp b/authsecret/aidl/default/Android.bp
index 7ce83fd..7e6e48b 100644
--- a/authsecret/aidl/default/Android.bp
+++ b/authsecret/aidl/default/Android.bp
@@ -26,16 +26,60 @@
 cc_binary {
     name: "android.hardware.authsecret-service.example",
     relative_install_path: "hw",
-    init_rc: ["android.hardware.authsecret-service.example.rc"],
-    vintf_fragments: ["android.hardware.authsecret-service.example.xml"],
     vendor: true,
     srcs: [
         "service.cpp",
         "AuthSecret.cpp",
     ],
     shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+    ],
+    static_libs: [
         "android.hardware.authsecret-V1-ndk",
         "libbase",
-        "libbinder_ndk",
+    ],
+    stl: "c++_static",
+}
+
+prebuilt_etc {
+    name: "android.hardware.authsecret-service.example.rc",
+    src: "android.hardware.authsecret-service.example.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "android.hardware.authsecret-service.example.xml",
+    src: "android.hardware.authsecret-service.example.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex_key {
+    name: "com.android.hardware.authsecret.key",
+    public_key: "com.android.hardware.authsecret.avbpubkey",
+    private_key: "com.android.hardware.authsecret.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.authsecret.certificate",
+    certificate: "com.android.hardware.authsecret",
+}
+
+apex {
+    name: "com.android.hardware.authsecret",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.authsecret.key",
+    certificate: ":com.android.hardware.authsecret.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.authsecret-service.example",
+    ],
+    prebuilts: [
+        "android.hardware.authsecret-service.example.rc", // init_rc
+        "android.hardware.authsecret-service.example.xml", // vintf_fragments
     ],
 }
diff --git a/authsecret/aidl/default/android.hardware.authsecret-service.example.rc b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
index fef6e24..9f51837 100644
--- a/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
+++ b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
@@ -1,4 +1,4 @@
-service vendor.authsecret_default /vendor/bin/hw/android.hardware.authsecret-service.example
+service vendor.authsecret_default /apex/com.android.hardware.authsecret/bin/hw/android.hardware.authsecret-service.example
     class hal
     user hsm
     group hsm
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey b/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
new file mode 100644
index 0000000..2fb5f0b
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pem b/authsecret/aidl/default/com.android.hardware.authsecret.pem
new file mode 100644
index 0000000..644868c
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCkkrpV5StewKq6
+HOog0IkbBRAtuChTsQjE1yQY6VXF/f/QWc2L0++pe0PTNzuKJZuqD05tgLYBxsFl
+QSLMKoUnGkQshVHxFLCls0CQo/umgygydxyVNW5cTdDDbl0VHrYcJJSWBobfy/hh
+dizJVET6HMQLY0shKM9CcdFDRqvM+WB6ceBxcFsxwm8r5qcB6CCeIDsPuBBo5Mpa
+NlVbaMBc/qrSRFLqLiVph6Goycg0Zk5+i1A4VBTJoHlOQwgX4uMdlNoAnaf1rLIm
+Qn2zNfcfeZ3BoiwKv8qMsvLNotaN+oIYLi4t21JcPsroByI+Ps5Gia17BhQvbbXx
+3eRShBn6/YcxcMQmCPoN5JbqeyzcE9f0grh3I8ubf1+ZAW0dL2r6QRM6uo6T4Jf7
+BFiMVB0RjTzfo8ngwgPLIm/aXU2O8IG8sILO1s1iOaQb23E2PveF1B7EOmFzW8x3
+xSQQLwn83zY+V+BTZs/Dfgv+M3omctsLS7lgGuvSx9KHV+EnbRMoIYa/2fx5KUxP
+kC3rGpR2BRHZibm3tBlHmdkzOsaHaoQy2fLtqK39Au+cL05O5VpOYObBN2wOlKUO
+iWLS79YoaWAKUZtZKwQNu1jpmK0OMgCeC13QSTz2AuPgL6XEuCUpcmblX3KMsu5w
+MK79Yke/V61cQ71e5qI0vr3IXjcjywIDAQABAoICAAYZ0GGNyNFO6CVVHBLSWDrR
+sbtYJ9qOZgpSBWsM/1qDI4AYTCfiV/Ca+rUyR3lEEqS3w4sIqfaf5Rx5US5rZxs/
+fIZ//L0orLG/1uVlxtbx5sQUKVGYtPokAli0VywIwuyBKKb1H/vc5lzKkjd2ccYp
+2dSoPilBB4npiT3quUS0e/CeFxltdlv+XrusZcWK0ua5wCbBho406RF2ESz90Z/A
+6xk3YjF/O3DRj9sfe9YBcuh7BqLH7ytYURbnIj4scYnvsjMypP7VA5eqgFlr5zjZ
++9CpT+OoH3yex6R65GRIBJmb4KdfiYqU41W9qfXPwzrXMMCuRYJKmWOZe7TZY9Mc
+V46jaDgLgKxe+mI4CLi2auKFE4KL8x68KSqa22y2dEjWwBPiT7If6v0ZL4CiAy9n
+SNHFaceMY3l485vaZEtXxusRB/UGDZnAXr9NqBVm4YVAfOaEnJNDSqvYefM5iyOG
+yQZ7dCXS9Ey4JvVlceA6mybj2JSx20QS2wN/tcyZjWsjM0f/sIHAJRS6KhEqCIfX
+4L8d5nXJ1wvnBFvcfboSERkPOTQsuipsvn9uj8Zs9QWNYYRSyleptL+ce8fBqed6
+9ryErCuB9lpVTjUsOiaIibtGdePleQb10club1B/4vsgPl5wvTPRNCTmpOCP3pSf
+Rei2x4z1VGFOBwd3MiTtAoIBAQDiQCsK87Zs8E5cwc0CqeMWstWHvJLTkj2B42OI
+Zrbr6ByRixuLpWgVWtJJLKbLXPN83wl8eksv3+Ba+yi17uafhXX7M1O5RlOzvTHt
+bbFPeysB3KEmNt96dRDRKYY3z0KHJxCRWKKZjZjp8Usf3TuKi9Xbque8o2n1LKKB
+KANRC4xtHmUesl6d4S4iAfIkq5/nA4ocuJ2qd/2t3nc6yhPPRrP9+4sUPYdqBEUz
+ds9isqt5erUybstCoHRgsEwWo/9ew8Dyj1TCIDTSqRt1/0QnEVm77bgBrA8P66HI
+KKFVoo/MLQSw5V+CDZwTJNlPQwrG9tyrSkcMFgLSRzi+7d/3AoIBAQC6Nm5Ztiad
+zm/1jM89uHmvedimKCKKG6+Eom5D96PduP76uRr65s6Usn0QCZ4Jvou0xnbtCP1K
+lzVI1+v6EiIQyWX0y1bd0UJDdyYo4Ck2nqOh0vgw+cBO70faV50J5QA2mS/wFdw0
+PvykQpPYGiIfv1MMHWA+rPDzMtf1uUQ18vzzN7RaZll88pletC7mc7qgBaucQVvB
+/qzOZSwhiaSSvXS1sFKfkqLqpJ3x9748D74MIwDD2i3fRxxfqPcgrG3B7xxIKVgd
+CYoFjeC9inZbnwvPmtaKzROJknsuJA21s/ckkSiWJJbjbyymVc1hWNhoMbtSPopa
+OOJ7u695Ls3NAoIBADtRE3fVmXhKMGFFNhiCrdTfoffqSpxJdPK+yPOT6lVDD2ph
+DCG6heVDYGpq2HfssLGGUBhgf6HXkhyISI4aSkB8Xwgy1rp2Y6915McYwSnTYt0k
+GOPJ8yFJ29TajCPJpOmGJmPU1xxm8TY0WrvJ5rhWHQVwcz0Tos3ym9A8y1HOM0zQ
+cTZxETlXNh8YX4GZtVx9oxIQnNV6i/mvn5a8MCFhqgLmlfoCf6Qd5n6toYWAzlAV
+CbhlL8kSBDDtR6WP7X3M2KM/TLtwcijgySBQgm+zrtEEa/+UOoa0AkBV1qZ67jRb
+gSVXnYidRNQIDykmrIapZgVKfgH/K1Ix9gCooNUCggEAeSMzwnS2xm4nc2w43YQG
+1VrEz8LIRWQhWH16kgilt3XDmkOVA6fmt+EtbqNzBg/JPr7lWupALKgVZ9/fiX0G
+YDlEdG1bg03Ad7cpQeohpYCqHnnqL6IpsrAC5E2ewXMSInKhNuRhrjNTk2AkYa8O
+h+ylD/qERAGpdeybhSUS9K2wVGDmmPCAQsJnd65r3EtpGvTVYP87vAX7UQGMJf0u
+7K8HH7Mm7Nwt08tnXKO4Q8ZR8f9LXh2vPdM66Bg5PC4v8LumgGM1CR7NhTN5ApTy
+zkO3IUUvUHh8v0BlleyqZow+uLEd4B7Jcgc+2q5yv2NW1OGVZLl+s5bR74B3dLQ3
++QKCAQBtxqTUKaRE/g+paQByORt0mFuXhO5UyfEBpg6l7+aUS4wTGMeKKDCFjTME
+lDjEK7eiAAOgN3AJYQ+r6831pm3hg6DG5lpxTKUuz2eMqMHk3LVlDFkH6BZF3Jxg
+XxWP1Abi88hK3nnbuGrt6rlUxvJRdWaJcF5nXybJzPMpvzPcDjAg5fCT11vZQsRl
+piAO6NjAECwUOaBHSHPvIXO9fWu4zY03rhg9px+dkutydSJ/6B3jq33q1CzHDQMd
+bklkBBrLu9inpuvETbhVK6IWP2zMHzdViR58M+xd5rg2E3GBQePyd6mjOB+7p7Gd
+hUHo4XX1/r2CDceZTmOjaZP/MQOJ
+-----END PRIVATE KEY-----
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pk8 b/authsecret/aidl/default/com.android.hardware.authsecret.pk8
new file mode 100644
index 0000000..1453366
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.pk8
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem b/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
new file mode 100644
index 0000000..71fe854
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF4zCCA8sCFH8r8uUt7ZiBGNZm/OxNbzMI34N3MA0GCSqGSIb3DQEBCwUAMIGs
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEoMCYGA1UEAwwfY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYXV0aHNlY3JldDAgFw0yMzA4MTgwNzA3MDFaGA80
+NzYxMDcxNDA3MDcwMVowgawxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
+bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
+DgYDVQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQu
+Y29tMSgwJgYDVQQDDB9jb20uYW5kcm9pZC5oYXJkd2FyZS5hdXRoc2VjcmV0MIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1+ml99ip2TVpYdJXxqVnizLg
+/DAnOUy5rZE+mCpjua1zyHl7GFFnseq6GO5wftptWekcC9fVSPxg1YS+RVduRcNz
+rt3mCsJ60DexaHrElITc1GCC1vzyt9cg6UtmdYg+OXSPlfWZE2T7OLfGWrhU56El
+IFt1eQDu5RDBOHZ2/N30KmKXv3yhpdl5un/kaC6q6p1PPih0aYXT2PrHsyN17wBl
+smhhpWNg/OAzFhWKwFcSTLMCOAI+pjqWKqXmjQ1awBly+lLAtHEBxxEUDMD6Z4lv
+2OGftL9bdseb1Wbj2bgj22bkfwWj5Yu77ilz5H27aLxQouQsmSfBkVgLq6seQMzd
+ovg+MOFb9iyWgcWkGg7eKdSzjfzCKQ/d2GOxEqwGofEYUOxYM1+a0Fnb7vUtgT/v
+I4tJCgXxAMFtsYGySC+gBhNx7vqLfo/8gtcZjJL6PRtRJ2V7hF9x3xKFa2/6qOLn
+UD/R5z+uwzaEqom+AmmmKNdWtn58nBns7EGq/3KVPcb7CSi9Xf6CCJiV+AmRaBSx
+2CtLt1fBX46LM3bV+iw7ZFAYAAXE3j6FgpM/PlozQjl61TuomHQP1ILmu/988tiF
+FMbuRH6mI0u4VOkDBUg9lxmjr0uAVmysWmzkRrAKydzedsuG5WG6hy2ZcD+lCV05
+JzvE6pB65OaIEPB5cMECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAozFo1vOIy/Js
+/EU5oRtSGSIoWCNIn7EYQ68jVHQk2ZhklVH2jW+6WVGmreOjPz5iWeDb0fC4KVtH
+MPXJ1Vd+GfvDysrnW5mDBzlI1O2xv/BWYeHt+RFWghhH/NFHaTQqDJpdOZXMZM4F
+dwFefxLchcXftE9jihHJXJ4k0cxC03Kpd0caZE7b67W1YQdJhU9mZx6CP1A3MdWU
+f48QIsmHgejkihtGNDRheBRzNdpHPhdOjYIWhOeAHh/xnm7PVZBMXmZeNW7MrAS0
++lN99r7Xj3eqtSdrMrrob845PWYsATA/a8ouUuTT7812fl8tZx69xb8wV5hNztDj
+srOxxJbjt1uwcSp67f2K91D97CQuMMPnOt1oFEXT+5QtLEiybXKfkshwO7VVDoIg
+owMLoKIiA2Xr+rZn7CEBeTrqQuRJfJEI+k/49zg2zWQIKGQAz8iaO0l95Hk5kPTE
+A5i9qxhn0UqC6a4Dkj8ybQOACzVA06IsbbYdprfzURQHjcUiSrEzjrwWxkkX/9El
+Z0CJAtkXx4pMxo5s6zt26ZPC3cxWB7aageWSC4xDbKuQP5VCNVg1nWymg6nF4Xk9
+d7n7yvSNH6fAZrpmZo7o7CBxCb4QN8j7TpyuaPd7nzyCyR6aGbh7fz8xksukvj6w
+ZSbAAy5uw4hyUwTTpyPyw+qQxI7O/PU=
+-----END CERTIFICATE-----
diff --git a/authsecret/aidl/default/file_contexts b/authsecret/aidl/default/file_contexts
new file mode 100644
index 0000000..8e79f26
--- /dev/null
+++ b/authsecret/aidl/default/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/etc(/.*)?                                                  u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.authsecret-service\.example      u:object_r:hal_authsecret_default_exec:s0
\ No newline at end of file
diff --git a/authsecret/aidl/default/manifest.json b/authsecret/aidl/default/manifest.json
new file mode 100644
index 0000000..ad5a45b
--- /dev/null
+++ b/authsecret/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.authsecret",
+    "version": 1
+}
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
index 15de48f..4787f0b 100644
--- a/automotive/evs/OWNERS
+++ b/automotive/evs/OWNERS
@@ -1,2 +1,2 @@
 ankitarora@google.com
-jwhpryor@google.com
+changyeon@google.com
diff --git a/automotive/evs/aidl/impl/default/Android.bp b/automotive/evs/aidl/impl/default/Android.bp
index 70c523b..79ee956 100644
--- a/automotive/evs/aidl/impl/default/Android.bp
+++ b/automotive/evs/aidl/impl/default/Android.bp
@@ -60,12 +60,15 @@
         "libyuv",
     ],
     static_libs: [
-        "android.frameworks.automotive.display-V1-ndk",
+        "android.frameworks.automotive.display-V2-ndk",
         "android.hardware.automotive.evs-V2-ndk",
         "android.hardware.common-V2-ndk",
         "libaidlcommonsupport",
         "libcutils",
     ],
+    header_libs: [
+        "libgui_aidl_headers",
+    ],
     local_include_dirs: ["include"],
     include_dirs: ["frameworks/native/include/"],
     required: ["evs_mock_hal_configuration.xml"],
diff --git a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h b/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
index 259c266..3897b4e 100644
--- a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
+++ b/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
@@ -27,6 +27,7 @@
 #include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
 #include <aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.h>
 #include <aidl/android/hardware/automotive/evs/Stream.h>
+#include <android-base/thread_annotations.h>
 #include <utils/Thread.h>
 
 #include <atomic>
diff --git a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h b/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
index ceabd9e..0865a04 100644
--- a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
+++ b/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
@@ -23,6 +23,7 @@
 #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
 #include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
 #include <aidl/android/hardware/automotive/evs/DisplayState.h>
+#include <android-base/thread_annotations.h>
 
 #include <thread>
 
diff --git a/automotive/evs/aidl/impl/default/include/GlWrapper.h b/automotive/evs/aidl/impl/default/include/GlWrapper.h
index adb250c..7ff6104 100644
--- a/automotive/evs/aidl/impl/default/include/GlWrapper.h
+++ b/automotive/evs/aidl/impl/default/include/GlWrapper.h
@@ -25,7 +25,7 @@
 #include <aidl/android/frameworks/automotive/display/ICarDisplayProxy.h>
 #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
 #include <android-base/logging.h>
-#include <bufferqueueconverter/BufferQueueConverter.h>
+#include <cutils/native_handle.h>
 
 namespace aidl::android::hardware::automotive::evs::implementation {
 
@@ -33,7 +33,6 @@
 
 class GlWrapper {
   public:
-    GlWrapper() : mSurfaceHolder(::android::SurfaceHolderUniquePtr(nullptr, nullptr)) {}
     bool initialize(const std::shared_ptr<automotivedisplay::ICarDisplayProxy>& svc,
                     uint64_t displayId);
     void shutdown();
@@ -53,9 +52,6 @@
     unsigned getHeight() { return mHeight; };
 
   private:
-    ::android::sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
-            mGfxBufferProducer;
-
     EGLDisplay mDisplay;
     EGLSurface mSurface;
     EGLContext mContext;
@@ -71,9 +67,6 @@
     // Opaque handle for a native hardware buffer defined in
     // frameworks/native/opengl/include/EGL/eglplatform.h
     ANativeWindow* mWindow;
-
-    // Pointer to a Surface wrapper.
-    ::android::SurfaceHolderUniquePtr mSurfaceHolder;
 };
 
 }  // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
index e5f8e4c..5b5cbcc 100644
--- a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
@@ -352,8 +352,8 @@
     BufferDesc bufferDescToSend = {
             .buffer =
                     {
-                            .handle = std::move(::android::dupToAidl(mBuffer.handle)),
                             .description = mBuffer.description,
+                            .handle = std::move(::android::dupToAidl(mBuffer.handle)),
                     },
             .pixelSizeBytes = 4,  // RGBA_8888 is 4-byte-per-pixel format
             .bufferId = mBuffer.fingerprint,
diff --git a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp b/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
index 0ee5ecb..a9d0213 100644
--- a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
+++ b/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
@@ -19,6 +19,7 @@
 #include <aidl/android/frameworks/automotive/display/DisplayDesc.h>
 #include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
 #include <aidlcommonsupport/NativeHandle.h>
+#include <gui/view/Surface.h>
 #include <ui/DisplayMode.h>
 #include <ui/DisplayState.h>
 #include <ui/GraphicBuffer.h>
@@ -183,20 +184,6 @@
     return program;
 }
 
-::android::sp<HGraphicBufferProducer> convertNativeHandleToHGBP(const NativeHandle& aidlHandle) {
-    native_handle_t* handle = ::android::dupFromAidl(aidlHandle);
-    if (handle->numFds != 0 || handle->numInts < std::ceil(sizeof(size_t) / sizeof(int))) {
-        LOG(ERROR) << "Invalid native handle";
-        return nullptr;
-    }
-    ::android::hardware::hidl_vec<uint8_t> halToken;
-    halToken.setToExternal(reinterpret_cast<uint8_t*>(const_cast<int*>(&(handle->data[1]))),
-                           handle->data[0]);
-    ::android::sp<HGraphicBufferProducer> hgbp =
-            HGraphicBufferProducer::castFrom(::android::retrieveHalInterface(halToken));
-    return std::move(hgbp);
-}
-
 }  // namespace
 
 namespace aidl::android::hardware::automotive::evs::implementation {
@@ -226,30 +213,19 @@
     }
     LOG(INFO) << "Display resolution is " << mWidth << "x" << mHeight;
 
-    NativeHandle aidlHandle;
-    status = pWindowProxy->getHGraphicBufferProducer(displayId, &aidlHandle);
+    aidl::android::view::Surface shimSurface;
+    status = pWindowProxy->getSurface(displayId, &shimSurface);
     if (!status.isOk()) {
-        LOG(ERROR) << "Failed to get IGraphicBufferProducer from ICarDisplayProxy.";
+        LOG(ERROR) << "Failed to obtain the surface.";
         return false;
     }
 
-    mGfxBufferProducer = convertNativeHandleToHGBP(aidlHandle);
-    if (!mGfxBufferProducer) {
-        LOG(ERROR) << "Failed to convert a NativeHandle to HGBP.";
-        return false;
-    }
-
-    mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer);
-    if (mSurfaceHolder == nullptr) {
-        LOG(ERROR) << "Failed to get a Surface from HGBP.";
-        return false;
-    }
-
-    mWindow = getNativeWindow(mSurfaceHolder.get());
+    mWindow = shimSurface.get();
     if (mWindow == nullptr) {
         LOG(ERROR) << "Failed to get a native window from Surface.";
         return false;
     }
+    ANativeWindow_acquire(mWindow);
 
     // Set up our OpenGL ES context associated with the default display
     mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -350,7 +326,12 @@
     mDisplay = EGL_NO_DISPLAY;
 
     // Release the window
-    mSurfaceHolder = nullptr;
+    if (mWindow == nullptr) {
+        return;
+    }
+
+    ANativeWindow_release(mWindow);
+    mWindow = nullptr;
 }
 
 void GlWrapper::showWindow(const std::shared_ptr<ICarDisplayProxy>& pWindowProxy, uint64_t id) {
diff --git a/automotive/remoteaccess/hal/default/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
index 0155667..48a7309 100644
--- a/automotive/remoteaccess/hal/default/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -53,7 +53,7 @@
     vintf_fragments: ["remoteaccess-default-service.xml"],
     init_rc: ["remoteaccess-default-service.rc"],
     cflags: [
-        "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+        "-DGRPC_SERVICE_ADDRESS=\"10.0.2.2:50051\"",
     ],
 }
 
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
index b091162..d4ba864 100644
--- a/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
@@ -30,12 +30,12 @@
 constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default";
 
 int main(int /* argc */, char* /* argv */[]) {
-    LOG(INFO) << "Registering RemoteAccessService as service...";
-
 #ifndef GRPC_SERVICE_ADDRESS
     LOG(ERROR) << "GRPC_SERVICE_ADDRESS is not defined, exiting";
     exit(1);
 #endif
+    LOG(INFO) << "Registering RemoteAccessService as service, server: " << GRPC_SERVICE_ADDRESS
+              << "...";
     grpc::ChannelArguments grpcargs = {};
 
 #ifdef GRPC_SERVICE_IFNAME
@@ -48,8 +48,7 @@
                                 android::netdevice::WaitCondition::PRESENT_AND_UP);
     LOG(INFO) << "Waiting for interface: " << GRPC_SERVICE_IFNAME << " done";
 #endif
-    auto channel = grpc::CreateCustomChannel(GRPC_SERVICE_ADDRESS,
-                                             grpc::InsecureChannelCredentials(), grpcargs);
+    auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials());
     auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);
     auto service = ndk::SharedRefBase::make<
             android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get());
diff --git a/automotive/remoteaccess/test_grpc_server/impl/Android.bp b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
index 152b528..74c810e 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
@@ -38,6 +38,26 @@
     ],
     cflags: [
         "-Wno-unused-parameter",
-        "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+        "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"",
+    ],
+}
+
+cc_binary_host {
+    name: "TestWakeupClientServerHost",
+    srcs: ["src/*.cpp"],
+    local_include_dirs: ["include"],
+    shared_libs: [
+        "libbase",
+        "libutils",
+        "libgrpc++",
+        "libprotobuf-cpp-full",
+    ],
+    whole_static_libs: [
+        "wakeup_client_protos",
+    ],
+    cflags: [
+        "-Wno-unused-parameter",
+        "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"",
+        "-DHOST",
     ],
 }
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
index 6b86b35..4159e83 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -34,11 +34,9 @@
 // implementation, the task should come from remote task server. This class is thread-safe.
 class FakeTaskGenerator final {
   public:
-    GetRemoteTasksResponse generateTask();
+    GetRemoteTasksResponse generateTask(const std::string& clientId);
 
   private:
-    // Simulates the client ID for each task.
-    std::atomic<int> mCurrentClientId = 0;
     constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef};
 };
 
@@ -99,7 +97,7 @@
     void waitForTaskWithLock(std::unique_lock<std::mutex>& lock);
 };
 
-class TestWakeupClientServiceImpl final : public WakeupClient::Service {
+class TestWakeupClientServiceImpl : public WakeupClient::Service {
   public:
     TestWakeupClientServiceImpl();
 
@@ -112,25 +110,57 @@
                                       const NotifyWakeupRequiredRequest* request,
                                       NotifyWakeupRequiredResponse* response) override;
 
+    /**
+     * Starts generating fake tasks for the specific client repeatedly.
+     *
+     * The fake task will have {0xDE 0xAD 0xBE 0xEF} as payload. A new fake task will be sent
+     * to the client every 5s.
+     */
+    void startGeneratingFakeTask(const std::string& clientId);
+    /**
+     * stops generating fake tasks.
+     */
+    void stopGeneratingFakeTask();
+    /**
+     * Returns whether we need to wakeup the target device to send remote tasks.
+     */
+    bool isWakeupRequired();
+    /**
+     * Returns whether we have an active connection with the target device.
+     */
+    bool isRemoteTaskConnectionAlive();
+    /**
+     * Injects a fake task with taskData to be sent to the specific client.
+     */
+    void injectTask(const std::string& taskData, const std::string& clientId);
+    /**
+     * Wakes up the target device.
+     *
+     * This must be implemented by child class and contains device specific logic. E.g. this might
+     * be sending QEMU commands for the emulator device.
+     */
+    virtual void wakeupApplicationProcessor() = 0;
+
   private:
     // This is a thread for communicating with remote wakeup server (via network) and receive tasks
     // from it.
     std::thread mThread;
     // A variable to notify server is stopping.
-    std::condition_variable mServerStoppedCv;
+    std::condition_variable mTaskLoopStoppedCv;
     // Whether wakeup AP is required for executing tasks.
     std::atomic<bool> mWakeupRequired = true;
+    // Whether we currently have an active long-live connection to deliver remote tasks.
+    std::atomic<bool> mRemoteTaskConnectionAlive = false;
     std::mutex mLock;
-    bool mServerStopped GUARDED_BY(mLock);
+    bool mGeneratingFakeTask GUARDED_BY(mLock);
 
     // Thread-safe. For test impl only.
     FakeTaskGenerator mFakeTaskGenerator;
     // Thread-sfae.
     TaskQueue mTaskQueue;
 
-    void fakeTaskGenerateLoop();
-
-    void wakeupApplicationProcessor();
+    void fakeTaskGenerateLoop(const std::string& clientId);
+    void injectTaskResponse(const GetRemoteTasksResponse& response);
 };
 
 }  // namespace remoteaccess
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
index 7dcd31e..eb3871b 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -16,8 +16,6 @@
 
 #include "TestWakeupClientServiceImpl.h"
 
-#include "ApPowerControl.h"
-
 #include <android-base/stringprintf.h>
 #include <inttypes.h>
 #include <utils/Looper.h>
@@ -44,12 +42,10 @@
 
 }  // namespace
 
-GetRemoteTasksResponse FakeTaskGenerator::generateTask() {
-    int clientId = mCurrentClientId++;
+GetRemoteTasksResponse FakeTaskGenerator::generateTask(const std::string& clientId) {
     GetRemoteTasksResponse response;
-    response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA)));
-    std::string clientIdStr = StringPrintf("%d", clientId);
-    response.set_clientid(clientIdStr);
+    response.set_data(reinterpret_cast<const char*>(DATA), sizeof(DATA));
+    response.set_clientid(clientId);
     return response;
 }
 
@@ -165,38 +161,68 @@
     }
 }
 
-TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {
-    mThread = std::thread([this] { fakeTaskGenerateLoop(); });
-}
+TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {}
 
 TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() {
+    { std::lock_guard<std::mutex> lockGuard(mLock); }
+    mTaskQueue.stopWait();
+    stopGeneratingFakeTask();
+}
+
+void TestWakeupClientServiceImpl::injectTask(const std::string& taskData,
+                                             const std::string& clientId) {
+    GetRemoteTasksResponse response;
+    response.set_data(taskData);
+    response.set_clientid(clientId);
+    injectTaskResponse(response);
+}
+
+void TestWakeupClientServiceImpl::injectTaskResponse(const GetRemoteTasksResponse& response) {
+    printf("Received a new task\n");
+    mTaskQueue.add(response);
+    if (mWakeupRequired) {
+        wakeupApplicationProcessor();
+    }
+}
+
+void TestWakeupClientServiceImpl::startGeneratingFakeTask(const std::string& clientId) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+    if (mGeneratingFakeTask) {
+        printf("Fake task is already being generated\n");
+        return;
+    }
+    mGeneratingFakeTask = true;
+    mThread = std::thread([this, clientId] { fakeTaskGenerateLoop(clientId); });
+    printf("Started generating fake tasks\n");
+}
+
+void TestWakeupClientServiceImpl::stopGeneratingFakeTask() {
     {
         std::lock_guard<std::mutex> lockGuard(mLock);
-        mServerStopped = true;
-        mServerStoppedCv.notify_all();
+        if (!mGeneratingFakeTask) {
+            printf("Fake task is not being generated, do nothing\n");
+            return;
+        }
+        mTaskLoopStoppedCv.notify_all();
+        mGeneratingFakeTask = false;
     }
-    mTaskQueue.stopWait();
     if (mThread.joinable()) {
         mThread.join();
     }
+    printf("Stopped generating fake tasks\n");
 }
 
-void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() {
+void TestWakeupClientServiceImpl::fakeTaskGenerateLoop(const std::string& clientId) {
     // In actual implementation, this should communicate with the remote server and receives tasks
     // from it. Here we simulate receiving one remote task every {kTaskIntervalInMs}ms.
     while (true) {
-        mTaskQueue.add(mFakeTaskGenerator.generateTask());
-        printf("Received a new task\n");
-        if (mWakeupRequired) {
-            wakeupApplicationProcessor();
-        }
-
+        injectTaskResponse(mFakeTaskGenerator.generateTask(clientId));
         printf("Sleeping for %d seconds until next task\n", kTaskIntervalInMs);
 
         std::unique_lock lk(mLock);
-        if (mServerStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] {
+        if (mTaskLoopStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] {
                 ScopedLockAssertion lockAssertion(mLock);
-                return mServerStopped;
+                return !mGeneratingFakeTask;
             })) {
             // If the stopped flag is set, we are quitting, exit the loop.
             return;
@@ -208,6 +234,7 @@
                                                    const GetRemoteTasksRequest* request,
                                                    ServerWriter<GetRemoteTasksResponse>* writer) {
     printf("GetRemoteTasks called\n");
+    mRemoteTaskConnectionAlive = true;
     while (true) {
         mTaskQueue.waitForTask();
 
@@ -226,16 +253,19 @@
                 // The task failed to be sent, add it back to the queue. The order might change, but
                 // it is okay.
                 mTaskQueue.add(response);
+                mRemoteTaskConnectionAlive = false;
                 return Status::CANCELLED;
             }
         }
     }
+    mRemoteTaskConnectionAlive = false;
     return Status::OK;
 }
 
 Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context,
                                                          const NotifyWakeupRequiredRequest* request,
                                                          NotifyWakeupRequiredResponse* response) {
+    printf("NotifyWakeupRequired called\n");
     if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue.isEmpty()) {
         // If wakeup is now required and previously not required, this means we have finished
         // shutting down the device. If there are still pending tasks, try waking up AP again
@@ -243,11 +273,20 @@
         wakeupApplicationProcessor();
     }
     mWakeupRequired = request->iswakeuprequired();
+    if (mWakeupRequired) {
+        // We won't know the connection is down unless we try to send a task over. If wakeup is
+        // required, the connection is very likely already down.
+        mRemoteTaskConnectionAlive = false;
+    }
     return Status::OK;
 }
 
-void TestWakeupClientServiceImpl::wakeupApplicationProcessor() {
-    wakeupAp();
+bool TestWakeupClientServiceImpl::isWakeupRequired() {
+    return mWakeupRequired;
+}
+
+bool TestWakeupClientServiceImpl::isRemoteTaskConnectionAlive() {
+    return mRemoteTaskConnectionAlive;
 }
 
 }  // namespace remoteaccess
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
index d3f519c..be285a8 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -14,7 +14,17 @@
  * limitations under the License.
  */
 
+#include <signal.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <iostream>
+#include <sstream>
 #include <string>
+#include <thread>
+
+#ifndef HOST
+#include "ApPowerControl.h"
+#endif  // #ifndef HOST
 
 #include "TestWakeupClientServiceImpl.h"
 
@@ -28,10 +38,18 @@
 using ::grpc::ServerBuilder;
 using ::grpc::ServerWriter;
 
-void RunServer(const std::string& serviceAddr) {
-    std::shared_ptr<TestWakeupClientServiceImpl> service =
-            std::make_unique<TestWakeupClientServiceImpl>();
+constexpr int SHUTDOWN_REQUEST = 289410889;
+constexpr int VEHICLE_IN_USE = 287313738;
+const char* COMMAND_RUN_EMU = "source ~/.aae-toolbox/bin/bashrc && aae emulator run";
+const char* COMMAND_SET_VHAL_PROP =
+        "adb -s emulator-5554 wait-for-device && adb -s emulator-5554 root "
+        "&& sleep 1 && adb -s emulator-5554 wait-for-device && adb -s emulator-5554 shell "
+        "dumpsys android.hardware.automotive.vehicle.IVehicle/default --set %d -i %d";
 
+pid_t emuPid = 0;
+
+void RunServer(const std::string& serviceAddr,
+               std::shared_ptr<TestWakeupClientServiceImpl> service) {
     ServerBuilder builder;
     builder.AddListeningPort(serviceAddr, grpc::InsecureServerCredentials());
     builder.RegisterService(service.get());
@@ -40,11 +58,224 @@
     server->Wait();
 }
 
+pid_t runCommand(const char* bashCommand) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        // In child process. Put it into a separate process group so we can kill it.
+        setpgid(0, 0);
+        execl("/bin/bash", "bash", "-c", bashCommand, /*terminateArg=*/nullptr);
+        exit(0);
+    } else {
+        return pid;
+    }
+}
+
+void updateEmuStatus() {
+    if (emuPid == 0) {
+        return;
+    }
+    pid_t pid = waitpid(emuPid, nullptr, WNOHANG);
+    if (pid == emuPid) {
+        // Emu process already exited. If Emu process is still running, pid will be 0.
+        emuPid = 0;
+    }
+}
+
+bool powerOnEmu() {
+    updateEmuStatus();
+    if (emuPid != 0) {
+        printf("The emulator is already running\n");
+        return false;
+    }
+    emuPid = runCommand(COMMAND_RUN_EMU);
+    printf("Emulator started in process: %d\n", emuPid);
+    return true;
+}
+
+bool powerOn() {
+#ifdef HOST
+    return powerOnEmu();
+#else
+    printf("power on is only supported on host\n");
+    return false;
+#endif
+}
+
+const char* getSetPropCommand(int propId) {
+    int size = snprintf(nullptr, 0, COMMAND_SET_VHAL_PROP, propId, 1);
+    char* command = new char[size + 1];
+    snprintf(command, size + 1, COMMAND_SET_VHAL_PROP, propId, 1);
+    return command;
+}
+
+void powerOffEmu() {
+    updateEmuStatus();
+    if (emuPid == 0) {
+        printf("The emulator is not running\n");
+        return;
+    }
+    const char* command = getSetPropCommand(SHUTDOWN_REQUEST);
+    runCommand(command);
+    delete[] command;
+    waitpid(emuPid, nullptr, /*options=*/0);
+    emuPid = 0;
+}
+
+void powerOff() {
+#ifdef HOST
+    powerOffEmu();
+#else
+    printf("power off is only supported on host\n");
+#endif
+}
+
+void setVehicleInUse(bool vehicleInUse) {
+#ifdef HOST
+    printf("Set vehicleInUse to %d\n", vehicleInUse);
+    int value = 0;
+    if (vehicleInUse) {
+        value = 1;
+    }
+    const char* command = getSetPropCommand(VEHICLE_IN_USE);
+    runCommand(command);
+    delete[] command;
+#else
+    printf("set vehicleInUse is only supported on host\n");
+#endif
+}
+
+void help() {
+    std::cout << "Remote Access Host Test Utility" << std::endl
+              << "help:\t"
+              << "Print out this help info" << std::endl
+              << "genFakeTask start [clientID]:\t"
+              << "Start generating a fake task every 5s" << std::endl
+              << "genFakeTask stop:\t"
+              << "Stop the fake task generation" << std::endl
+              << "status:\t"
+              << "Print current status" << std::endl
+              << "power on:\t"
+              << "Power on the emulator, simulate user enters vehicle while AP is off"
+              << " (only supported on host)" << std::endl
+              << "power off:\t"
+              << "Power off the emulator, simulate user leaves vehicle"
+              << " (only supported on host)" << std::endl
+              << "inject task [clientID] [taskData]:\t"
+              << "Inject a remote task" << std::endl
+              << "set vehicleInUse:\t"
+              << "Set vehicle in use, simulate user enter vehicle while boot up for remote task "
+              << "(only supported on host)" << std::endl;
+}
+
+void parseCommand(const std::string& userInput,
+                  std::shared_ptr<TestWakeupClientServiceImpl> service) {
+    if (userInput == "") {
+        // ignore empty line.
+    } else if (userInput == "help") {
+        help();
+    } else if (userInput.rfind("genFakeTask start", 0) == 0) {
+        std::string clientId;
+        std::stringstream ss;
+        ss << userInput;
+        int i = 0;
+        while (std::getline(ss, clientId, ' ')) {
+            i++;
+            if (i == 3) {
+                break;
+            }
+        }
+        if (i != 3) {
+            printf("Missing clientId, see 'help'\n");
+            return;
+        }
+        service->startGeneratingFakeTask(clientId);
+    } else if (userInput == "genFakeTask stop") {
+        service->stopGeneratingFakeTask();
+    } else if (userInput == "status") {
+        printf("isWakeupRequired: %B, isRemoteTaskConnectionAlive: %B\n",
+               service->isWakeupRequired(), service->isRemoteTaskConnectionAlive());
+    } else if (userInput == "power on") {
+        powerOn();
+    } else if (userInput == "power off") {
+        powerOff();
+    } else if (userInput.rfind("inject task", 0) == 0) {
+        std::stringstream ss;
+        ss << userInput;
+        std::string data;
+        std::string taskData;
+        std::string clientId;
+        int i = 0;
+        while (std::getline(ss, data, ' ')) {
+            i++;
+            if (i == 3) {
+                clientId = data;
+            }
+            if (i == 4) {
+                taskData = data;
+            }
+        }
+        if (taskData == "" || clientId == "") {
+            printf("Missing taskData or clientId, see 'help'\n");
+            return;
+        }
+        service->injectTask(taskData, clientId);
+        printf("Remote task with client ID: %s, data: %s injected\n", clientId.c_str(),
+               taskData.c_str());
+    } else if (userInput == "set vehicleInUse") {
+        setVehicleInUse(true);
+    } else {
+        printf("Unknown command, see 'help'\n");
+    }
+}
+
+void saHandler(int signum) {
+    if (emuPid != 0) {
+        kill(-emuPid, signum);
+        waitpid(emuPid, nullptr, /*options=*/0);
+        // Sleep for 1 seconds to allow emulator to print out logs.
+        sleep(1);
+    }
+    exit(-1);
+}
+
+class MyTestWakeupClientServiceImpl final : public TestWakeupClientServiceImpl {
+  public:
+    void wakeupApplicationProcessor() override {
+#ifdef HOST
+        if (powerOnEmu()) {
+            // If we wake up AP to execute remote task, vehicle in use should be false.
+            setVehicleInUse(false);
+        }
+#else
+        wakeupAp();
+#endif
+    };
+};
+
 int main(int argc, char** argv) {
     std::string serviceAddr = GRPC_SERVICE_ADDRESS;
     if (argc > 1) {
         serviceAddr = argv[1];
     }
-    RunServer(serviceAddr);
+    // Let the server thread run, we will force kill the server when we exit the program.
+    std::shared_ptr<TestWakeupClientServiceImpl> service =
+            std::make_shared<MyTestWakeupClientServiceImpl>();
+    std::thread serverThread([serviceAddr, service] { RunServer(serviceAddr, service); });
+
+    // Register the signal handler for SIGTERM and SIGINT so that we can stop the emulator before
+    // exit.
+    struct sigaction sa = {};
+    sigemptyset(&sa.sa_mask);
+    sa.sa_handler = saHandler;
+    sigaction(SIGTERM, &sa, nullptr);
+    sigaction(SIGINT, &sa, nullptr);
+
+    // Start processing the user inputs.
+    std::string userInput;
+    while (true) {
+        std::cout << ">>> ";
+        std::getline(std::cin, userInput);
+        parseCommand(userInput, service);
+    }
     return 0;
 }
diff --git a/automotive/remoteaccess/test_grpc_server/lib/Android.bp b/automotive/remoteaccess/test_grpc_server/lib/Android.bp
index 7e95f53..8391018 100644
--- a/automotive/remoteaccess/test_grpc_server/lib/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/lib/Android.bp
@@ -26,7 +26,7 @@
 cc_library_shared {
     name: "ApPowerControlLib",
     vendor: true,
-    srcs: ["*.cpp"],
+    srcs: ["ApPowerControl.cpp"],
     local_include_dirs: ["."],
     export_include_dirs: ["."],
 }
diff --git a/automotive/vehicle/aidl/impl/utils/test/Android.bp b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControlHost.cpp
similarity index 66%
copy from automotive/vehicle/aidl/impl/utils/test/Android.bp
copy to automotive/remoteaccess/test_grpc_server/lib/ApPowerControlHost.cpp
index ad9954f..a475b00 100644
--- a/automotive/vehicle/aidl/impl/utils/test/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControlHost.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,13 +14,10 @@
  * limitations under the License.
  */
 
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
+#include "ApPowerControl.h"
 
-cc_library_headers {
-    name: "VehicleHalTestUtilHeaders",
-    vendor: true,
-    header_libs: ["VehicleHalUtilHeaders"],
-    export_include_dirs: ["include"],
+#include <cstdio>
+
+void wakeupAp() {
+    printf("Waking up application processor...\n");
 }
diff --git a/automotive/vehicle/2.0/default/TEST_MAPPING b/automotive/vehicle/2.0/default/TEST_MAPPING
index bb58700..63ea3d5 100644
--- a/automotive/vehicle/2.0/default/TEST_MAPPING
+++ b/automotive/vehicle/2.0/default/TEST_MAPPING
@@ -2,7 +2,9 @@
   "presubmit": [
     {
       "name": "android.hardware.automotive.vehicle@2.0-manager-unit-tests"
-    },
+    }
+  ],
+  "postsubmit": [
     {
       "name": "android.hardware.automotive.vehicle@2.0-default-impl-unit-tests"
     }
diff --git a/automotive/vehicle/Android.bp b/automotive/vehicle/Android.bp
index c0d71d7..f0abbcf 100644
--- a/automotive/vehicle/Android.bp
+++ b/automotive/vehicle/Android.bp
@@ -22,6 +22,6 @@
     name: "VehicleHalInterfaceDefaults",
     static_libs: [
         "android.hardware.automotive.vehicle-V2-ndk",
-        "android.hardware.automotive.vehicle.property-V2-ndk",
+        "android.hardware.automotive.vehicle.property-V3-ndk",
     ],
 }
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index da8416c..02ad8bb 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -43,6 +43,14 @@
   "auto-presubmit": [
     {
       "name": "VtsHalAutomotiveVehicle_TargetTest"
+    },
+    {
+      "name": "CarServiceUnitTest",
+      "options" : [
+        {
+          "include-filter": "com.android.car.hal.fakevhal.FakeVehicleStubUnitTest"
+        }
+      ]
     }
   ]
 }
diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp
index 44d7445..79ac309 100644
--- a/automotive/vehicle/aidl/aidl_test/Android.bp
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -52,7 +52,7 @@
     ],
     static_libs: [
         "android.hardware.automotive.vehicle-V2-java",
-        "android.hardware.automotive.vehicle.property-V2-java",
+        "android.hardware.automotive.vehicle.property-V3-java",
         "androidx.test.runner",
         "truth-prebuilt",
     ],
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
index 6984d5e..75a3541 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
@@ -35,14 +35,17 @@
 cc_library {
     name: "VehicleHalJsonConfigLoaderEnableTestProperties",
     vendor: true,
-    srcs: ["src/*.cpp"],
+    srcs: [
+        "src/*.cpp",
+        ":VhalTestVendorProperties",
+    ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
     defaults: ["VehicleHalDefaults"],
     static_libs: ["VehicleHalUtils"],
     header_libs: [
-        "VehicleHalTestUtilHeaders",
         "IVehicleGeneratedHeaders",
+        "libbinder_headers",
     ],
     cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
     shared_libs: ["libjsoncpp"],
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
index 0a1f904..39ce10e 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -21,7 +21,7 @@
 #include <PropertyUtils.h>
 
 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
-#include <TestPropertyUtils.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
 #endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
 
 #include <android-base/strings.h>
@@ -91,10 +91,6 @@
         {"HVAC_ALL", HVAC_ALL},
         {"HVAC_LEFT", HVAC_LEFT},
         {"HVAC_RIGHT", HVAC_RIGHT},
-        {"VENDOR_EXTENSION_INT_PROPERTY", VENDOR_EXTENSION_INT_PROPERTY},
-        {"VENDOR_EXTENSION_BOOLEAN_PROPERTY", VENDOR_EXTENSION_BOOLEAN_PROPERTY},
-        {"VENDOR_EXTENSION_STRING_PROPERTY", VENDOR_EXTENSION_STRING_PROPERTY},
-        {"VENDOR_EXTENSION_FLOAT_PROPERTY", VENDOR_EXTENSION_FLOAT_PROPERTY},
         {"WINDOW_1_LEFT", WINDOW_1_LEFT},
         {"WINDOW_1_RIGHT", WINDOW_1_RIGHT},
         {"WINDOW_2_LEFT", WINDOW_2_LEFT},
@@ -133,24 +129,9 @@
         {"EV_STOPPING_MODE_HOLD", EV_STOPPING_MODE_HOLD},
         {"MIRROR_DRIVER_LEFT_RIGHT",
          toInt(VehicleAreaMirror::DRIVER_LEFT) | toInt(VehicleAreaMirror::DRIVER_RIGHT)},
-#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
-        // Following are test properties:
-        {"ECHO_REVERSE_BYTES", ECHO_REVERSE_BYTES},
-        {"VENDOR_PROPERTY_ID", VENDOR_PROPERTY_ID},
-        {"kMixedTypePropertyForTest", kMixedTypePropertyForTest},
-        {"VENDOR_CLUSTER_NAVIGATION_STATE", VENDOR_CLUSTER_NAVIGATION_STATE},
-        {"VENDOR_CLUSTER_REQUEST_DISPLAY", VENDOR_CLUSTER_REQUEST_DISPLAY},
-        {"VENDOR_CLUSTER_SWITCH_UI", VENDOR_CLUSTER_SWITCH_UI},
-        {"VENDOR_CLUSTER_DISPLAY_STATE", VENDOR_CLUSTER_DISPLAY_STATE},
-        {"VENDOR_CLUSTER_REPORT_STATE", VENDOR_CLUSTER_REPORT_STATE},
-        {"PLACEHOLDER_PROPERTY_INT", PLACEHOLDER_PROPERTY_INT},
-        {"PLACEHOLDER_PROPERTY_FLOAT", PLACEHOLDER_PROPERTY_FLOAT},
-        {"PLACEHOLDER_PROPERTY_BOOLEAN", PLACEHOLDER_PROPERTY_BOOLEAN},
-        {"PLACEHOLDER_PROPERTY_STRING", PLACEHOLDER_PROPERTY_STRING}
-#endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
 };
 
-// A class to parse constant values for type T.
+// A class to parse constant values for type T where T is defined as an enum in NDK AIDL backend.
 template <class T>
 class ConstantParser final : public ConstantParserInterface {
   public:
@@ -181,6 +162,33 @@
     std::unordered_map<std::string, int> mValueByName;
 };
 
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+// A class to parse constant values for type T where T is defined as an enum in CPP AIDL backend.
+template <class T>
+class CppConstantParser final : public ConstantParserInterface {
+  public:
+    CppConstantParser() {
+        for (const T& v : android::enum_range<T>()) {
+            std::string name = android::hardware::automotive::vehicle::toString(v);
+            mValueByName[name] = toInt(v);
+        }
+    }
+
+    ~CppConstantParser() = default;
+
+    Result<int> parseValue(const std::string& name) const override {
+        auto it = mValueByName.find(name);
+        if (it == mValueByName.end()) {
+            return Error() << "Constant name: " << name << " is not defined";
+        }
+        return it->second;
+    }
+
+  private:
+    std::unordered_map<std::string, int> mValueByName;
+};
+#endif
+
 // A class to parse constant values defined in CONSTANTS_BY_NAME map.
 class LocalVariableParser final : public ConstantParserInterface {
   public:
@@ -260,6 +268,10 @@
     mConstantParsersByType["LaneCenteringAssistState"] =
             std::make_unique<ConstantParser<LaneCenteringAssistState>>();
     mConstantParsersByType["Constants"] = std::make_unique<LocalVariableParser>();
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+    mConstantParsersByType["TestVendorProperty"] =
+            std::make_unique<CppConstantParser<TestVendorProperty>>();
+#endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
 }
 
 template <>
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 5503de2..b9f784b 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -3387,7 +3387,7 @@
             "property": "VehicleProperty::CRUISE_CONTROL_TYPE",
             "defaultValue": {
                 "int32Values": [
-                    "CruiseControlType::STANDARD"
+                    "CruiseControlType::ADAPTIVE"
                 ]
             },
             "areas": [
@@ -3629,6 +3629,17 @@
             }
         },
         {
+            "property": "VehicleProperty::SHUTDOWN_REQUEST"
+        },
+        {
+            "property": "VehicleProperty::VEHICLE_IN_USE",
+            "defaultValue": {
+                "int32Values": [
+                    1
+                ]
+            }
+        },
+        {
             "property": "VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
             "defaultValue": {
                 "int32Values": [
diff --git a/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json b/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json
index fd4b002..73e4d44 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json
@@ -1,7 +1,7 @@
 {
     "properties": [
         {
-            "property": "Constants::kMixedTypePropertyForTest",
+            "property": "TestVendorProperty::MIXED_TYPE_PROPERTY_FOR_TEST",
             "defaultValue": {
                 "floatValues": [
                     4.5
@@ -28,7 +28,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_EXTENSION_BOOLEAN_PROPERTY",
+            "property": "TestVendorProperty::VENDOR_EXTENSION_BOOLEAN_PROPERTY",
             "areas": [
                 {
                     "defaultValue": {
@@ -67,7 +67,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_EXTENSION_FLOAT_PROPERTY",
+            "property": "TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY",
             "areas": [
                 {
                     "defaultValue": {
@@ -94,7 +94,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_EXTENSION_INT_PROPERTY",
+            "property": "TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY",
             "areas": [
                 {
                     "defaultValue": {
@@ -131,7 +131,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_EXTENSION_STRING_PROPERTY",
+            "property": "TestVendorProperty::VENDOR_EXTENSION_STRING_PROPERTY",
             "defaultValue": {
                 "stringValue": "Vendor String Property"
             },
@@ -139,7 +139,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::PLACEHOLDER_PROPERTY_INT",
+            "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_INT",
             "defaultValue": {
                 "int32Values": [
                     0
@@ -149,7 +149,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::PLACEHOLDER_PROPERTY_FLOAT",
+            "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_FLOAT",
             "defaultValue": {
                 "floatValues": [
                     0.0
@@ -159,7 +159,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::PLACEHOLDER_PROPERTY_BOOLEAN",
+            "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_BOOLEAN",
             "defaultValue": {
                 "int32Values": [
                     0
@@ -169,7 +169,7 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::PLACEHOLDER_PROPERTY_STRING",
+            "property": "TestVendorProperty::PLACEHOLDER_PROPERTY_STRING",
             "defaultValue": {
                 "stringValue": "Test"
             },
@@ -177,12 +177,12 @@
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::ECHO_REVERSE_BYTES",
+            "property": "TestVendorProperty::ECHO_REVERSE_BYTES",
             "access": "VehiclePropertyAccess::READ_WRITE",
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_PROPERTY_ID",
+            "property": "TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING",
             "access": "VehiclePropertyAccess::READ_WRITE",
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
@@ -194,13 +194,13 @@
                 ]
             },
             "configArray": [
-                "Constants::kMixedTypePropertyForTest",
+                "TestVendorProperty::MIXED_TYPE_PROPERTY_FOR_TEST",
                 "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_INFO",
                 "VehicleVendorPermission::PERMISSION_SET_VENDOR_CATEGORY_INFO",
-                "Constants::VENDOR_EXTENSION_INT_PROPERTY",
+                "TestVendorProperty::VENDOR_EXTENSION_INT_PROPERTY",
                 "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_SEAT",
                 "VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE",
-                "Constants::VENDOR_EXTENSION_FLOAT_PROPERTY",
+                "TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY",
                 "VehicleVendorPermission::PERMISSION_DEFAULT",
                 "VehicleVendorPermission::PERMISSION_DEFAULT"
             ]
diff --git a/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json b/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
index 3a1a783..8c2bc93 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
@@ -1,17 +1,17 @@
 {
     "properties": [
         {
-            "property": "Constants::VENDOR_CLUSTER_SWITCH_UI",
+            "property": "TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI",
             "access": "VehiclePropertyAccess::WRITE",
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_CLUSTER_DISPLAY_STATE",
+            "property": "TestVendorProperty::VENDOR_CLUSTER_DISPLAY_STATE",
             "access": "VehiclePropertyAccess::WRITE",
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         },
         {
-            "property": "Constants::VENDOR_CLUSTER_REPORT_STATE",
+            "property": "TestVendorProperty::VENDOR_CLUSTER_REPORT_STATE",
             "defaultValue": {
                 "int32Values": [
                     0,
@@ -44,7 +44,7 @@
                     "Value means 0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, -1, -1 /* Insets */, 0 /* ClusterHome */, -1 /* ClusterNone */"
         },
         {
-            "property": "Constants::VENDOR_CLUSTER_REQUEST_DISPLAY",
+            "property": "TestVendorProperty::VENDOR_CLUSTER_REQUEST_DISPLAY",
             "defaultValue": {
                 "int32Values": [
                     0
@@ -55,7 +55,7 @@
             "comment": "0 means ClusterHome"
         },
         {
-            "property": "Constants::VENDOR_CLUSTER_NAVIGATION_STATE",
+            "property": "TestVendorProperty::VENDOR_CLUSTER_NAVIGATION_STATE",
             "access": "VehiclePropertyAccess::READ",
             "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
         }
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
index d2b701d..2378676 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
@@ -57,7 +57,7 @@
         float dispersion;    //  Defines minimum and maximum value based on initial value.
         float increment;     //  Value that we will be added to currentValue with each timer tick.
         int64_t interval;
-        long lastEventTimestamp;
+        int64_t lastEventTimestamp;
     };
 
     GeneratorCfg mGenCfg;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
index 9133144..fe08dcf 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
@@ -86,7 +86,7 @@
     if (mGenCfg.lastEventTimestamp == 0) {
         mGenCfg.lastEventTimestamp = elapsedRealtimeNano();
     } else {
-        long nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval;
+        int64_t nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval;
         // Prevent overflow.
         assert(nextEventTime > mGenCfg.lastEventTimestamp);
         mGenCfg.lastEventTimestamp = nextEventTime;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
index 4c17cde..e75f648 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
@@ -21,7 +21,10 @@
 cc_library {
     name: "FakeVehicleHardware",
     vendor: true,
-    srcs: ["src/*.cpp"],
+    srcs: [
+        "src/*.cpp",
+        ":VhalTestVendorProperties",
+    ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
     cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
@@ -35,7 +38,7 @@
     name: "FakeVehicleHardwareDefaults",
     header_libs: [
         "IVehicleHardware",
-        "VehicleHalTestUtilHeaders",
+        "libbinder_headers",
     ],
     export_header_lib_headers: ["IVehicleHardware"],
     static_libs: [
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index c3ebd3b..f130fa4 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -189,11 +189,14 @@
     VhalResult<void> maybeSetSpecialValue(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
             bool* isSpecialValue);
+    VhalResult<bool> isCruiseControlTypeStandard() const;
     ValueResultType maybeGetSpecialValue(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
             bool* isSpecialValue) const;
     VhalResult<void> setApPowerStateReport(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+    VhalResult<void> setApPowerStateReqShutdown(
+            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
     VehiclePropValuePool::RecyclableType createApPowerStateReq(
             aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
     VehiclePropValuePool::RecyclableType createAdasStateReq(int32_t propertyId, int32_t areaId,
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 3f5e4c4..82c3ea0 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -24,7 +24,6 @@
 #include <JsonFakeValueGenerator.h>
 #include <LinearFakeValueGenerator.h>
 #include <PropertyUtils.h>
-#include <TestPropertyUtils.h>
 #include <VehicleHalTypes.h>
 #include <VehicleUtils.h>
 
@@ -32,6 +31,7 @@
 #include <android-base/parsedouble.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 #include <utils/Trace.h>
@@ -52,6 +52,8 @@
 
 namespace {
 
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
 using ::aidl::android::hardware::automotive::vehicle::ErrorState;
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
@@ -61,6 +63,7 @@
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
@@ -85,14 +88,12 @@
 //  getPropertiesAsync, and setPropertiesAsync.
 // 0x21403000
 constexpr int32_t STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST =
-        0x3000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+        0x3000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) |
+        toInt(VehiclePropertyType::INT32);
 // 0x21405000
 constexpr int32_t ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST =
-        0x5000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+        0x5000 | toInt(VehiclePropertyGroup::VENDOR) | toInt(VehicleArea::GLOBAL) |
+        toInt(VehiclePropertyType::INT32);
 // The directory for default property configuration file.
 // For config file format, see impl/default_config/config/README.md.
 constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
@@ -103,7 +104,7 @@
 // overwrite the default configs.
 constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override";
 constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
-// The value to be returned if VENDOR_PROPERTY_ID is set as the property
+// The value to be returned if VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING is set as the property
 constexpr int VENDOR_ERROR_CODE = 0x00ab0005;
 // A list of supported options for "--set" command.
 const std::unordered_set<std::string> SET_PROP_OPTIONS = {
@@ -337,6 +338,25 @@
     return req;
 }
 
+VhalResult<void> FakeVehicleHardware::setApPowerStateReqShutdown(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() != 1) {
+        return StatusError(StatusCode::INVALID_ARG)
+               << "Failed to set SHUTDOWN_REQUEST, expect 1 int value: "
+               << "VehicleApPowerStateShutdownParam";
+    }
+    int powerStateShutdownParam = value.value.int32Values[0];
+    auto prop = createApPowerStateReq(VehicleApPowerStateReq::SHUTDOWN_PREPARE);
+    prop->value.int32Values[1] = powerStateShutdownParam;
+    if (auto writeResult = mServerSidePropStore->writeValue(
+                std::move(prop), /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS);
+        !writeResult.ok()) {
+        return StatusError(getErrorCode(writeResult))
+               << "failed to write AP_POWER_STATE_REQ into property store, error: "
+               << getErrorMsg(writeResult);
+    }
+    return {};
+}
+
 VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
     auto updatedValue = mValuePool->obtain(value);
     updatedValue->timestamp = elapsedRealtimeNano();
@@ -592,6 +612,18 @@
     }
 }
 
+VhalResult<bool> FakeVehicleHardware::isCruiseControlTypeStandard() const {
+    auto isCruiseControlTypeAvailableResult =
+            isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_TYPE));
+    if (!isCruiseControlTypeAvailableResult.ok()) {
+        return isCruiseControlTypeAvailableResult.error();
+    }
+    auto cruiseControlTypeValue =
+            mServerSidePropStore->readValue(toInt(VehicleProperty::CRUISE_CONTROL_TYPE));
+    return cruiseControlTypeValue.value()->value.int32Values[0] ==
+           toInt(CruiseControlType::STANDARD);
+}
+
 FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue(
         const VehiclePropValue& value, bool* isSpecialValue) const {
     *isSpecialValue = false;
@@ -619,6 +651,7 @@
         return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
     }
 
+    VhalResult<void> isAdasPropertyAvailableResult;
     switch (propId) {
         case OBD2_FREEZE_FRAME:
             *isSpecialValue = true;
@@ -634,24 +667,41 @@
                 result.value()->timestamp = elapsedRealtimeNano();
             }
             return result;
-        case ECHO_REVERSE_BYTES:
+        case toInt(TestVendorProperty::ECHO_REVERSE_BYTES):
             *isSpecialValue = true;
             return getEchoReverseBytes(value);
-        case VENDOR_PROPERTY_ID:
+        case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING):
             *isSpecialValue = true;
             return StatusError((StatusCode)VENDOR_ERROR_CODE);
         case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED):
-            [[fallthrough]];
-        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
-            [[fallthrough]];
-        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
-            auto isAdasPropertyAvailableResult =
+            isAdasPropertyAvailableResult =
                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
             if (!isAdasPropertyAvailableResult.ok()) {
                 *isSpecialValue = true;
                 return isAdasPropertyAvailableResult.error();
             }
             return nullptr;
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
+            [[fallthrough]];
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
+            isAdasPropertyAvailableResult =
+                    isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+            if (!isAdasPropertyAvailableResult.ok()) {
+                *isSpecialValue = true;
+                return isAdasPropertyAvailableResult.error();
+            }
+            auto isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
+            if (!isCruiseControlTypeStandardResult.ok()) {
+                *isSpecialValue = true;
+                return isCruiseControlTypeStandardResult.error();
+            }
+            if (isCruiseControlTypeStandardResult.value()) {
+                *isSpecialValue = true;
+                return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
+                       << "tried to get target time gap or lead vehicle measured distance value "
+                       << "while on a standard CC setting";
+            }
+            return nullptr;
         }
         default:
             // Do nothing.
@@ -711,7 +761,13 @@
         }
         auto& dependentPropConfig = dependentPropConfigResult.value();
         for (auto& areaConfig : dependentPropConfig->areaConfigs) {
-            auto propValue = createAdasStateReq(dependentPropId, areaConfig.areaId, state);
+            int32_t hardcoded_state = state;
+            // TODO: restore old/initial values here instead of hardcoded value (b/295542701)
+            if (state == 1 && dependentPropId == toInt(VehicleProperty::CRUISE_CONTROL_TYPE)) {
+                hardcoded_state = toInt(CruiseControlType::ADAPTIVE);
+            }
+            auto propValue =
+                    createAdasStateReq(dependentPropId, areaConfig.areaId, hardcoded_state);
             // This will trigger a property change event for the current ADAS property value.
             mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true,
                                              VehiclePropertyStore::EventMode::ALWAYS);
@@ -758,10 +814,18 @@
         }
     }
 
+    VhalResult<void> isAdasPropertyAvailableResult;
+    VhalResult<bool> isCruiseControlTypeStandardResult;
     switch (propId) {
         case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
             *isSpecialValue = true;
             return setApPowerStateReport(value);
+        case toInt(VehicleProperty::SHUTDOWN_REQUEST):
+            // If we receive SHUTDOWN_REQUEST, we should send this to an external component which
+            // should shutdown Android system via sending an AP_POWER_STATE_REQ event. Here we have
+            // no external components to notify, so we just send the event.
+            *isSpecialValue = true;
+            return setApPowerStateReqShutdown(value);
         case toInt(VehicleProperty::VEHICLE_MAP_SERVICE):
             // Placeholder for future implementation of VMS property in the default hal. For
             // now, just returns OK; otherwise, hal clients crash with property not supported.
@@ -770,14 +834,14 @@
         case OBD2_FREEZE_FRAME_CLEAR:
             *isSpecialValue = true;
             return mFakeObd2Frame->clearObd2FreezeFrames(value);
-        case VENDOR_PROPERTY_ID:
+        case toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING):
             *isSpecialValue = true;
             return StatusError((StatusCode)VENDOR_ERROR_CODE);
         case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
             *isSpecialValue = true;
             return setHvacTemperatureValueSuggestion(value);
         case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): {
-            auto isAdasPropertyAvailableResult =
+            isAdasPropertyAvailableResult =
                     isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE));
             if (!isAdasPropertyAvailableResult.ok()) {
                 *isSpecialValue = true;
@@ -785,14 +849,47 @@
             return isAdasPropertyAvailableResult;
         }
         case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND):
-            [[fallthrough]];
-        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
-            auto isAdasPropertyAvailableResult =
+            isAdasPropertyAvailableResult =
                     isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
             if (!isAdasPropertyAvailableResult.ok()) {
                 *isSpecialValue = true;
+                return isAdasPropertyAvailableResult;
             }
-            return isAdasPropertyAvailableResult;
+            isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
+            if (!isCruiseControlTypeStandardResult.ok()) {
+                *isSpecialValue = true;
+                return isCruiseControlTypeStandardResult.error();
+            }
+            if (isCruiseControlTypeStandardResult.value() &&
+                (value.value.int32Values[0] ==
+                         toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP) ||
+                 value.value.int32Values[0] ==
+                         toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP))) {
+                *isSpecialValue = true;
+                return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
+                       << "tried to use a change target time gap command while on a standard CC "
+                       << "setting";
+            }
+            return {};
+        case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
+            isAdasPropertyAvailableResult =
+                    isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+            if (!isAdasPropertyAvailableResult.ok()) {
+                *isSpecialValue = true;
+                return isAdasPropertyAvailableResult;
+            }
+            isCruiseControlTypeStandardResult = isCruiseControlTypeStandard();
+            if (!isCruiseControlTypeStandardResult.ok()) {
+                *isSpecialValue = true;
+                return isCruiseControlTypeStandardResult.error();
+            }
+            if (isCruiseControlTypeStandardResult.value()) {
+                *isSpecialValue = true;
+                return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
+                       << "tried to set target time gap or lead vehicle measured distance value "
+                       << "while on a standard CC setting";
+            }
+            return {};
         }
 
 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
@@ -802,9 +899,9 @@
             [[fallthrough]];
         case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
             [[fallthrough]];
-        case VENDOR_CLUSTER_SWITCH_UI:
+        case toInt(TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI):
             [[fallthrough]];
-        case VENDOR_CLUSTER_DISPLAY_STATE:
+        case toInt(TestVendorProperty::VENDOR_CLUSTER_DISPLAY_STATE):
             *isSpecialValue = true;
             updatedValue = mValuePool->obtain(getPropType(value.prop));
             updatedValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
@@ -1808,6 +1905,7 @@
 
 void FakeVehicleHardware::registerOnPropertySetErrorEvent(
         std::unique_ptr<const PropertySetErrorCallback> callback) {
+    // In FakeVehicleHardware, we will never use mOnPropertySetErrorCallback.
     if (mOnPropertySetErrorCallback != nullptr) {
         ALOGE("registerOnPropertySetErrorEvent must only be called once");
         return;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
index 8d8fcf5..b763d2f 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -21,11 +21,14 @@
 cc_test {
     name: "FakeVehicleHardwareTest",
     vendor: true,
-    srcs: ["*.cpp"],
+    srcs: [
+        "*.cpp",
+        ":VhalTestVendorProperties",
+    ],
     cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
     header_libs: [
         "IVehicleHardware",
-        "VehicleHalTestUtilHeaders",
+        "libbinder_headers",
     ],
     static_libs: [
         "VehicleHalJsonConfigLoaderEnableTestProperties",
@@ -47,7 +50,9 @@
         ":FakeVehicleHardwareTestOverrideJson",
         ":FakeVehicleHardwareTestPropJson",
     ],
-    defaults: ["VehicleHalDefaults"],
+    defaults: [
+        "VehicleHalDefaults",
+    ],
     test_suites: ["device-tests"],
 }
 
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 8d385dd..6cc06bc 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -19,7 +19,9 @@
 #include <FakeObd2Frame.h>
 #include <FakeUserHal.h>
 #include <PropertyUtils.h>
-#include <TestPropertyUtils.h>
+
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.h>
+#include <android/hardware/automotive/vehicle/TestVendorProperty.h>
 
 #include <android-base/expected.h>
 #include <android-base/file.h>
@@ -60,6 +62,8 @@
 namespace fake {
 namespace {
 
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
 using ::aidl::android::hardware::automotive::vehicle::ErrorState;
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
 using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
@@ -69,6 +73,7 @@
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
@@ -424,13 +429,13 @@
             continue;
         }
 
-        if (propId == ECHO_REVERSE_BYTES) {
+        if (propId == toInt(TestVendorProperty::ECHO_REVERSE_BYTES)) {
             // Ignore ECHO_REVERSE_BYTES, it has special logic.
             continue;
         }
 
-        if (propId == VENDOR_PROPERTY_ID) {
-            // Ignore VENDOR_PROPERTY_ID, it has special logic.
+        if (propId == toInt(TestVendorProperty::VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING)) {
+            // Ignore VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING, it has special logic.
             continue;
         }
 
@@ -963,7 +968,8 @@
                     .expectedValuesToGet =
                             {
                                     VehiclePropValue{
-                                            .prop = VENDOR_CLUSTER_REPORT_STATE,
+                                            .prop = toInt(TestVendorProperty::
+                                                                  VENDOR_CLUSTER_REPORT_STATE),
                                             .value.int32Values = {1},
                                     },
                             },
@@ -980,7 +986,8 @@
                     .expectedValuesToGet =
                             {
                                     VehiclePropValue{
-                                            .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
+                                            .prop = toInt(TestVendorProperty::
+                                                                  VENDOR_CLUSTER_REQUEST_DISPLAY),
                                             .value.int32Values = {1},
                                     },
                             },
@@ -998,7 +1005,8 @@
                     .expectedValuesToGet =
                             {
                                     VehiclePropValue{
-                                            .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
+                                            .prop = toInt(TestVendorProperty::
+                                                                  VENDOR_CLUSTER_NAVIGATION_STATE),
                                             .value.byteValues = {0x1},
                                     },
                             },
@@ -1008,7 +1016,8 @@
                     .valuesToSet =
                             {
                                     VehiclePropValue{
-                                            .prop = VENDOR_CLUSTER_SWITCH_UI,
+                                            .prop = toInt(
+                                                    TestVendorProperty::VENDOR_CLUSTER_SWITCH_UI),
                                             .value.int32Values = {1},
                                     },
                             },
@@ -1025,7 +1034,8 @@
                     .valuesToSet =
                             {
                                     VehiclePropValue{
-                                            .prop = VENDOR_CLUSTER_DISPLAY_STATE,
+                                            .prop = toInt(TestVendorProperty::
+                                                                  VENDOR_CLUSTER_DISPLAY_STATE),
                                             .value.int32Values = {1, 2},
                                     },
                             },
@@ -1451,7 +1461,7 @@
                                     },
                                     VehiclePropValue{
                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
-                                            .value.int32Values = {1},
+                                            .value.int32Values = {2},
                                     },
                                     VehiclePropValue{
                                             .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
@@ -1519,6 +1529,33 @@
                                     },
                             },
             },
+            SetSpecialValueTestCase{
+                    .name = "set_shutdown_request",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::SHUTDOWN_REQUEST),
+                                            .value.int32Values =
+                                                    {
+                                                            toInt(VehicleApPowerStateShutdownParam::
+                                                                          SHUTDOWN_ONLY),
+                                                    },
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                                            .value.int32Values =
+                                                    {
+                                                            toInt(VehicleApPowerStateReq::
+                                                                          SHUTDOWN_PREPARE),
+                                                            toInt(VehicleApPowerStateShutdownParam::
+                                                                          SHUTDOWN_ONLY),
+                                                    },
+                                    },
+                            },
+            },
     };
 }
 
@@ -1804,6 +1841,47 @@
     }
 }
 
+TEST_F(FakeVehicleHardwareTest, testGetAccPropertiesOnStandardCc) {
+    std::vector<int32_t> ccTypeDependentProperties = {
+            toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+            toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE),
+    };
+
+    StatusCode status =
+            setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                                      .value.int32Values = {toInt(CruiseControlType::STANDARD)}});
+    EXPECT_EQ(status, StatusCode::OK);
+
+    for (int32_t dependentProp : ccTypeDependentProperties) {
+        auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp});
+        EXPECT_FALSE(getValueResult.ok());
+        EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
+    }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetAccPropertiesOnStandardCc) {
+    std::vector<VehiclePropValue> testVehiclePropValues = {
+            VehiclePropValue{
+                    .prop = toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+                    .value.int32Values = {3}},
+            VehiclePropValue{
+                    .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
+                    .value.int32Values = {toInt(CruiseControlCommand::INCREASE_TARGET_TIME_GAP)}},
+            VehiclePropValue{
+                    .prop = toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
+                    .value.int32Values = {toInt(CruiseControlCommand::DECREASE_TARGET_TIME_GAP)}}};
+
+    StatusCode status =
+            setValue(VehiclePropValue{.prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+                                      .value.int32Values = {toInt(CruiseControlType::STANDARD)}});
+    EXPECT_EQ(status, StatusCode::OK);
+
+    for (auto value : testVehiclePropValues) {
+        status = setValue(value);
+        EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
+    }
+}
+
 TEST_F(FakeVehicleHardwareTest, testSendAdasPropertiesState) {
     std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToAdasPropWithErrorState = {
             // AEB
@@ -2855,7 +2933,7 @@
 
 TEST_F(FakeVehicleHardwareTest, testGetEchoReverseBytes) {
     ASSERT_EQ(setValue(VehiclePropValue{
-                      .prop = ECHO_REVERSE_BYTES,
+                      .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES),
                       .value =
                               {
                                       .byteValues = {0x01, 0x02, 0x03, 0x04},
@@ -2864,7 +2942,7 @@
               StatusCode::OK);
 
     auto result = getValue(VehiclePropValue{
-            .prop = ECHO_REVERSE_BYTES,
+            .prop = toInt(TestVendorProperty::ECHO_REVERSE_BYTES),
     });
 
     ASSERT_TRUE(result.ok()) << "failed to get ECHO_REVERSE_BYTES value: " << getStatus(result);
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index 90588aa..e740da7 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -24,6 +24,8 @@
 #include "VehicleServer.grpc.pb.h"
 #include "VehicleServer.pb.h"
 
+#include <grpc++/grpc++.h>
+
 #include <atomic>
 #include <chrono>
 #include <condition_variable>
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
index 6cbc7e5..6b789bb 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
@@ -73,6 +73,11 @@
         protoACfg->set_max_float_value(areaConfig.maxFloatValue);
         protoACfg->set_min_int32_value(areaConfig.minInt32Value);
         protoACfg->set_max_int32_value(areaConfig.maxInt32Value);
+        if (areaConfig.supportedEnumValues.has_value()) {
+            for (auto& supportedEnumValue : areaConfig.supportedEnumValues.value()) {
+                protoACfg->add_supported_enum_values(supportedEnumValue);
+            }
+        }
     }
 }
 
@@ -87,7 +92,7 @@
     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, config_array, out, configArray);
 
     auto cast_to_acfg = [](const proto::VehicleAreaConfig& protoAcfg) {
-        return aidl_vehicle::VehicleAreaConfig{
+        auto vehicleAreaConfig = aidl_vehicle::VehicleAreaConfig{
                 .areaId = protoAcfg.area_id(),
                 .minInt32Value = protoAcfg.min_int32_value(),
                 .maxInt32Value = protoAcfg.max_int32_value(),
@@ -96,6 +101,9 @@
                 .minFloatValue = protoAcfg.min_float_value(),
                 .maxFloatValue = protoAcfg.max_float_value(),
         };
+        COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoAcfg, supported_enum_values, (&vehicleAreaConfig),
+                                       supportedEnumValues.value());
+        return vehicleAreaConfig;
     };
     CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, area_configs, out, areaConfigs, cast_to_acfg);
 }
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
index 63d7933..95e766a 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
@@ -38,6 +38,37 @@
 
     /* Something unexpected has happened in Vehicle HAL */
     INTERNAL_ERROR = 5;
+
+    /**
+     * For features that are not available because the underlying feature is
+     * disabled.
+     */
+    NOT_AVAILABLE_DISABLED = 6;
+
+    /**
+     * For features that are not available because the vehicle speed is too low.
+     */
+    NOT_AVAILABLE_SPEED_LOW = 7;
+
+    /**
+     * For features that are not available because the vehicle speed is too
+     * high.
+     */
+    NOT_AVAILABLE_SPEED_HIGH = 8;
+
+    /**
+     * For features that are not available because of bad camera or sensor
+     * visibility. Examples might be bird poop blocking the camera or a bumper
+     * cover blocking an ultrasonic sensor.
+     */
+    NOT_AVAILABLE_POOR_VISIBILITY = 9;
+
+    /**
+     * The feature cannot be accessed due to safety reasons. Eg. System could be
+     * in a faulty state, an object or person could be blocking the requested
+     * operation such as closing a trunk door, etc.
+     */
+    NOT_AVAILABLE_SAFETY = 10;
 };
 
 message VehicleHalCallStatus {
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
index b5b7e80..ddc64d9 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehicleAreaConfig.proto
@@ -36,4 +36,11 @@
 
     float min_float_value = 6;
     float max_float_value = 7;
+
+    /**
+     * If the property has a @data_enum, then it is possible to specify a supported subset of the
+     * @data_enum. If the property has a @data_enum and supported_enum_values is null, then it is
+     * assumed all @data_enum values are supported unless specified through another mechanism.
+     */
+    repeated int64 supported_enum_values = 8;
 };
diff --git a/automotive/vehicle/aidl/impl/utils/README.md b/automotive/vehicle/aidl/impl/utils/README.md
index 87bb7e3..255131d 100644
--- a/automotive/vehicle/aidl/impl/utils/README.md
+++ b/automotive/vehicle/aidl/impl/utils/README.md
@@ -57,6 +57,6 @@
 
 Defines many useful utility functions.
 
-## test
+## test_vendor_properties
 
-Defines utility libraries for test only.
+Contains vendor properties used for testing purpose in reference VHAL.
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index 7275ba3..e41ec30 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -77,22 +77,6 @@
 constexpr int SEAT_2_LEFT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_LEFT);
 constexpr int SEAT_2_RIGHT = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_RIGHT);
 constexpr int SEAT_2_CENTER = toInt(propertyutils_impl::VehicleAreaSeat::ROW_2_CENTER);
-constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY =
-        0x101 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(propertyutils_impl::VehiclePropertyType::BOOLEAN) |
-        toInt(propertyutils_impl::VehicleArea::DOOR);
-constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY =
-        0x102 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(propertyutils_impl::VehiclePropertyType::FLOAT) |
-        toInt(propertyutils_impl::VehicleArea::SEAT);
-constexpr int VENDOR_EXTENSION_INT_PROPERTY =
-        0x103 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(propertyutils_impl::VehiclePropertyType::INT32) |
-        toInt(propertyutils_impl::VehicleArea::WINDOW);
-constexpr int VENDOR_EXTENSION_STRING_PROPERTY =
-        0x104 | toInt(propertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(propertyutils_impl::VehiclePropertyType::STRING) |
-        toInt(propertyutils_impl::VehicleArea::GLOBAL);
 constexpr int FUEL_DOOR_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
 constexpr int CHARGE_PORT_FRONT_LEFT = toInt(propertyutils_impl::PortLocationType::FRONT_LEFT);
 constexpr int CHARGE_PORT_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
index 250b331..dd43712 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
@@ -27,7 +27,6 @@
         "libgtest",
         "libgmock",
     ],
-    header_libs: ["VehicleHalTestUtilHeaders"],
     defaults: ["VehicleHalDefaults"],
     test_suites: ["device-tests"],
 }
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
index 141efc1..62046f3 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
@@ -18,6 +18,7 @@
 
 #include <android-base/thread_annotations.h>
 #include <gtest/gtest.h>
+#include <condition_variable>
 
 #include <chrono>
 #include <memory>
@@ -28,6 +29,8 @@
 namespace automotive {
 namespace vehicle {
 
+using ::android::base::ScopedLockAssertion;
+
 class RecurrentTimerTest : public testing::Test {
   public:
     std::shared_ptr<RecurrentTimer::Callback> getCallback(size_t token) {
@@ -35,6 +38,15 @@
             std::scoped_lock<std::mutex> lockGuard(mLock);
 
             mCallbacks.push_back(token);
+            mCond.notify_all();
+        });
+    }
+
+    bool waitForCalledCallbacks(size_t count, size_t timeoutInMs) {
+        std::unique_lock<std::mutex> uniqueLock(mLock);
+        return mCond.wait_for(uniqueLock, std::chrono::milliseconds(timeoutInMs), [this, count] {
+            ScopedLockAssertion lockAssertion(mLock);
+            return mCallbacks.size() >= count;
         });
     }
 
@@ -54,6 +66,7 @@
     }
 
   private:
+    std::condition_variable mCond;
     std::mutex mLock;
     std::vector<size_t> mCallbacks GUARDED_BY(mLock);
 };
@@ -66,12 +79,11 @@
     auto action = getCallback(0);
     timer.registerTimerCallback(interval, action);
 
-    std::this_thread::sleep_for(std::chrono::seconds(1));
+    // Should only takes 1s, use 5s as timeout to be safe.
+    ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+            << "Not enough callbacks called before timeout";
 
     timer.unregisterTimerCallback(action);
-
-    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
-    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
 }
 
 TEST_F(RecurrentTimerTest, testRegisterUnregisterRegister) {
@@ -92,10 +104,11 @@
 
     timer.registerTimerCallback(interval, action);
 
-    std::this_thread::sleep_for(std::chrono::seconds(1));
+    // Should only takes 1s, use 5s as timeout to be safe.
+    ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+            << "Not enough callbacks called before timeout";
 
-    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
-    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+    timer.unregisterTimerCallback(action);
 }
 
 TEST_F(RecurrentTimerTest, testDestroyTimerWithCallback) {
@@ -114,7 +127,9 @@
 
     std::this_thread::sleep_for(std::chrono::milliseconds(200));
 
-    ASSERT_TRUE(getCalledCallbacks().empty());
+    // Should be 0, but in rare cases there might be 1 events in the queue while the timer is
+    // being destroyed.
+    ASSERT_LE(getCalledCallbacks().size(), 1u);
 }
 
 TEST_F(RecurrentTimerTest, testRegisterMultipleCallbacks) {
@@ -132,7 +147,11 @@
     auto action3 = getCallback(3);
     timer.registerTimerCallback(interval3, action3);
 
-    std::this_thread::sleep_for(std::chrono::seconds(1));
+    // In 1s, we should generate 10 + 20 + 33 = 63 events.
+    // Here we are waiting for more events to make sure we receive enough events for each actions.
+    // Use 5s as timeout to be safe.
+    ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 70u, /* timeoutInMs= */ 5000))
+            << "Not enough callbacks called before timeout";
 
     timer.unregisterTimerCallback(action1);
     timer.unregisterTimerCallback(action2);
@@ -152,20 +171,18 @@
             action3Count++;
         }
     }
-    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
-    ASSERT_GE(action1Count, static_cast<size_t>(9));
-    // Theoretically trigger 20 times, but check for at least 15 times to be stable.
-    ASSERT_GE(action2Count, static_cast<size_t>(15));
-    // Theoretically trigger 33 times, but check for at least 25 times to be stable.
-    ASSERT_GE(action3Count, static_cast<size_t>(25));
+
+    ASSERT_GE(action1Count, static_cast<size_t>(10));
+    ASSERT_GE(action2Count, static_cast<size_t>(20));
+    ASSERT_GE(action3Count, static_cast<size_t>(33));
 }
 
 TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) {
     RecurrentTimer timer;
-    // 0.02s
-    int64_t interval1 = 20000000;
-    // 0.01s
-    int64_t interval2 = 10000000;
+    // 0.2s
+    int64_t interval1 = 200'000'000;
+    // 0.1s
+    int64_t interval2 = 100'000'000;
 
     auto action = getCallback(0);
     for (int i = 0; i < 10; i++) {
@@ -175,10 +192,9 @@
 
     clearCalledCallbacks();
 
-    std::this_thread::sleep_for(std::chrono::milliseconds(100));
-
-    // Theoretically trigger 10 times, but check for at least 9 times to be stable.
-    ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+    // Should only takes 1s, use 5s as timeout to be safe.
+    ASSERT_TRUE(waitForCalledCallbacks(/* count= */ 10u, /* timeoutInMs= */ 5000))
+            << "Not enough callbacks called before timeout";
 
     timer.unregisterTimerCallback(action);
 
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index 411539b..9abb2a2 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -16,7 +16,6 @@
 
 #include <ConcurrentQueue.h>
 #include <PropertyUtils.h>
-#include <TestPropertyUtils.h>
 #include <VehicleUtils.h>
 
 #include <gtest/gtest.h>
@@ -56,6 +55,9 @@
 constexpr int32_t int64VecProp = toInt(VehicleProperty::WHEEL_TICK);
 constexpr int32_t floatProp = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE);
 constexpr int32_t floatVecProp = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION);
+constexpr int32_t kMixedTypePropertyForTest = 0x1111 | toInt(VehiclePropertyGroup::VENDOR) |
+                                              toInt(VehicleArea::GLOBAL) |
+                                              toInt(VehiclePropertyType::MIXED);
 
 std::vector<InvalidPropValueTestCase> getInvalidPropValuesTestCases() {
     return std::vector<InvalidPropValueTestCase>(
diff --git a/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h b/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
deleted file mode 100644
index 1400288..0000000
--- a/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
-#define android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
-
-#include <VehicleHalTypes.h>
-#include <VehicleUtils.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-
-namespace testpropertyutils_impl {
-
-// These names are not part of the API since we only expose ints.
-using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
-using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
-
-}  // namespace testpropertyutils_impl
-
-// Converts the system property to the vendor property.
-// WARNING: This is only for the end-to-end testing, Should NOT include in the user build.
-inline constexpr int32_t toVendor(
-        const aidl::android::hardware::automotive::vehicle::VehicleProperty& prop) {
-    return (toInt(prop) & ~toInt(testpropertyutils_impl::VehiclePropertyGroup::MASK)) |
-           toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR);
-}
-
-// These properties are used for the end-to-end testing of ClusterHomeService.
-constexpr int32_t VENDOR_CLUSTER_SWITCH_UI =
-        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_SWITCH_UI);
-constexpr int32_t VENDOR_CLUSTER_DISPLAY_STATE =
-        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_DISPLAY_STATE);
-constexpr int32_t VENDOR_CLUSTER_REPORT_STATE =
-        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_REPORT_STATE);
-constexpr int32_t VENDOR_CLUSTER_REQUEST_DISPLAY =
-        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_REQUEST_DISPLAY);
-constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE =
-        toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_NAVIGATION_STATE);
-
-// These properties are placeholder properties for developers to test new features without
-// implementing a real property.
-constexpr int32_t PLACEHOLDER_PROPERTY_INT =
-        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
-constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
-        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::FLOAT);
-constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
-        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::BOOLEAN);
-constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
-        0x2a11 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::STRING);
-
-// This property is used for testing LargeParcelable marshalling/unmarhsalling end to end.
-// It acts as an regular property that stores the property value when setting and return the value
-// when getting, except that all the byteValues used in the setValue response would be filled in
-// the reverse order.
-// 0x21702a12
-constexpr int32_t ECHO_REVERSE_BYTES = 0x2a12 |
-                                       toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-                                       toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-                                       toInt(testpropertyutils_impl::VehiclePropertyType::BYTES);
-
-// This property is used for testing vendor error codes end to end.
-// 0x21402a13
-constexpr int32_t VENDOR_PROPERTY_ID = 0x2a13 |
-                                       toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-                                       toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-                                       toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
-
-// This property is used for test purpose. End to end tests use this property to test set and get
-// method for MIXED type properties.
-constexpr int32_t kMixedTypePropertyForTest =
-        0x1111 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
-        toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
-        toInt(testpropertyutils_impl::VehiclePropertyType::MIXED);
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_utils_test_include_TestPropertyUtils_H_
diff --git a/automotive/vehicle/aidl/impl/utils/test/Android.bp b/automotive/vehicle/aidl/impl/utils/test_vendor_properties/Android.bp
similarity index 65%
copy from automotive/vehicle/aidl/impl/utils/test/Android.bp
copy to automotive/vehicle/aidl/impl/utils/test_vendor_properties/Android.bp
index ad9954f..f7da7e0 100644
--- a/automotive/vehicle/aidl/impl/utils/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/utils/test_vendor_properties/Android.bp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -18,9 +18,14 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_library_headers {
-    name: "VehicleHalTestUtilHeaders",
-    vendor: true,
-    header_libs: ["VehicleHalUtilHeaders"],
-    export_include_dirs: ["include"],
+filegroup {
+    name: "VhalTestVendorProperties",
+    srcs: [
+        "**/*.aidl",
+    ],
+    visibility: [
+        "//hardware/interfaces/automotive/vehicle/aidl:__subpackages__",
+        "//packages/services/Car:__subpackages__",
+        "//cts/tests/tests/car_permission_tests",
+    ],
 }
diff --git a/automotive/vehicle/aidl/impl/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl b/automotive/vehicle/aidl/impl/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl
new file mode 100644
index 0000000..3c877fa
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/test_vendor_properties/android/hardware/automotive/vehicle/TestVendorProperty.aidl
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Test vendor properties used in reference VHAL implementation.
+ */
+@Backing(type="int")
+enum TestVendorProperty {
+
+    /**
+     * Vendor version of CLUSTER_SWITCH_UI, used for the end-to-end testing of ClusterHomeService.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32,
+     */
+    VENDOR_CLUSTER_SWITCH_UI = 0x0F34 + 0x20000000 + 0x01000000 + 0x00400000,
+
+    /**
+     * Vendor version of CLUSTER_DISPLAY_STATE, used for the end-to-end testing of
+     * ClusterHomeService.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32_VEC
+     */
+    VENDOR_CLUSTER_DISPLAY_STATE = 0x0F35 + 0x20000000 + 0x01000000 + 0x00410000,
+
+    /**
+     * Vendor version of CLUSTER_REPORT_STATE, used for the end-to-end testing of
+     * ClusterHomeService.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.MIXED
+     */
+    VENDOR_CLUSTER_REPORT_STATE = 0x0F36 + 0x20000000 + 0x01000000 + 0x00E00000,
+
+    /**
+     * Vendor version of CLUSTER_REQUEST_DISPLAY, used for the end-to-end testing of
+     * ClusterHomeService.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32
+     */
+    VENDOR_CLUSTER_REQUEST_DISPLAY = 0x0F37 + 0x20000000 + 0x01000000 + 0x00400000,
+
+    /**
+     * Vendor version of CLUSTER_NAVIGATION_STATE, used for the end-to-end testing of
+     * ClusterHomeService.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BYTES
+     */
+    VENDOR_CLUSTER_NAVIGATION_STATE = 0x0F38 + 0x20000000 + 0x01000000 + 0x00700000,
+
+    // These properties are placeholder properties for developers to test new features without
+    // implementing a real property.
+
+    /**
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32
+     */
+    PLACEHOLDER_PROPERTY_INT = 0x2A11 + 0x20000000 + 0x01000000 + 0x00400000,
+
+    /**
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.FLOAT
+     */
+    PLACEHOLDER_PROPERTY_FLOAT = 0x2A11 + 0x20000000 + 0x01000000 + 0x00600000,
+
+    /**
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BOOLEAN
+     */
+    PLACEHOLDER_PROPERTY_BOOLEAN = 0x2A11 + 0x20000000 + 0x01000000 + 0x00200000,
+
+    /**
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.STRING
+     */
+    PLACEHOLDER_PROPERTY_STRING = 0x2A11 + 0x20000000 + 0x01000000 + 0x00100000,
+
+    /**
+     * This property is used for testing LargeParcelable marshalling/unmarhsalling end to end.
+     * It acts as an regular property that stores the property value when setting and return the
+     * value when getting, except that all the byteValues used in the setValue response would be
+     * filled in the reverse order.
+     *
+     * This is used in {@code VehicleHalLargeParcelableTest}.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.BYTES
+     *
+     * 0x21702a12
+     */
+    ECHO_REVERSE_BYTES = 0x2A12 + 0x20000000 + 0x01000000 + 0x00700000,
+
+    /**
+     * This property is used for testing vendor error codes end to end.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32
+     *
+     * 0x21402a13
+     */
+    VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING = 0x2A13 + 0x20000000 + 0x01000000 + 0x00400000,
+
+    /**
+     * This property is used for test purpose. End to end tests use this property to test set and
+     * get method for MIXED type properties.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.MIXED
+     */
+    MIXED_TYPE_PROPERTY_FOR_TEST = 0x1111 + 0x20000000 + 0x01000000 + 0x00E00000,
+
+    /**
+     * Property used for {@code CarVendorPropertyCustomPermissionTest}.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.DOOR | VehiclePropertyGroup.BOOLEAN
+     */
+    VENDOR_EXTENSION_BOOLEAN_PROPERTY = 0x0101 + 0x20000000 + 0x06000000 + 0x00200000,
+
+    /**
+     * Property used for {@code CarVendorPropertyCustomPermissionTest}.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.SEAT | VehiclePropertyGroup.FLOAT
+     */
+    VENDOR_EXTENSION_FLOAT_PROPERTY = 0x102 + 0x20000000 + 0x05000000 + 0x00600000,
+
+    /**
+     * Property used for {@code CarVendorPropertyCustomPermissionTest}.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.WINDOW | VehiclePropertyGroup.INT32
+     */
+    VENDOR_EXTENSION_INT_PROPERTY = 0x103 + 0x20000000 + 0x03000000 + 0x00400000,
+
+    /**
+     * Property used for {@code CarVendorPropertyCustomPermissionTest}.
+     *
+     * VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyGroup.STRING
+     */
+    VENDOR_EXTENSION_STRING_PROPERTY = 0x103 + 0x20000000 + 0x01000000 + 0x00100000,
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
index 2e7298f..addc901 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -99,35 +99,23 @@
     std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
 };
 
-// A class to represent a client that calls {@code IVehicle.subscribe}.
-class SubscriptionClient final : public ConnectedClient {
+class SubscriptionClient {
   public:
-    SubscriptionClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
+    using CallbackType =
+            std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
 
-    // Gets the callback to be called when the request for this client has finished.
-    std::shared_ptr<const IVehicleHardware::GetValuesCallback> getResultCallback();
-
-    // Marshals the updated values into largeParcelable and sents it through {@code onPropertyEvent}
+    // Marshals the updated values into largeParcelable and sends it through {@code onPropertyEvent}
     // callback.
     static void sendUpdatedValues(
             CallbackType callback,
             std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
                     updatedValues);
-
-  protected:
-    // Gets the callback to be called when the request for this client has timeout.
-    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
-
-  private:
-    // The following members are only initialized during construction.
-    std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
-    std::shared_ptr<const IVehicleHardware::GetValuesCallback> mResultCallback;
-    std::shared_ptr<const IVehicleHardware::PropertyChangeCallback> mPropertyChangeCallback;
-
-    static void onGetValueResults(
-            const void* clientId, CallbackType callback,
-            std::shared_ptr<PendingRequestPool> requestPool,
-            std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult> results);
+    // Marshals the set property error events into largeParcelable and sends it through
+    // {@code onPropertySetError} callback.
+    static void sendPropertySetErrors(
+            CallbackType callback,
+            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>&&
+                    vehiclePropErrors);
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 2c2cf1a..419e16b 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -90,39 +90,6 @@
             GetSetValuesClient<aidl::android::hardware::automotive::vehicle::SetValueResult,
                                aidl::android::hardware::automotive::vehicle::SetValueResults>;
 
-    // A thread safe class to maintain an increasing request ID for each subscribe client. This
-    // class is safe to pass to async callbacks.
-    class SubscribeIdByClient {
-      public:
-        int64_t getId(const CallbackType& callback);
-
-      private:
-        std::mutex mLock;
-        std::unordered_map<const AIBinder*, int64_t> mIds GUARDED_BY(mLock);
-    };
-
-    // A thread safe class to store all subscribe clients. This class is safe to pass to async
-    // callbacks.
-    class SubscriptionClients {
-      public:
-        SubscriptionClients(std::shared_ptr<PendingRequestPool> pool) : mPendingRequestPool(pool) {}
-
-        std::shared_ptr<SubscriptionClient> maybeAddClient(const CallbackType& callback);
-
-        std::shared_ptr<SubscriptionClient> getClient(const CallbackType& callback);
-
-        void removeClient(const AIBinder* clientId);
-
-        size_t countClients();
-
-      private:
-        std::mutex mLock;
-        std::unordered_map<const AIBinder*, std::shared_ptr<SubscriptionClient>> mClients
-                GUARDED_BY(mLock);
-        // PendingRequestPool is thread-safe.
-        std::shared_ptr<PendingRequestPool> mPendingRequestPool;
-    };
-
     // A wrapper for binder lifecycle operations to enable stubbing for test.
     class BinderLifecycleInterface {
       public:
@@ -185,8 +152,6 @@
             GUARDED_BY(mLock);
     std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>> mSetValuesClients
             GUARDED_BY(mLock);
-    // SubscriptionClients is thread-safe.
-    std::shared_ptr<SubscriptionClients> mSubscriptionClients;
     // mBinderLifecycleHandler is only going to be changed in test.
     std::unique_ptr<BinderLifecycleInterface> mBinderLifecycleHandler;
 
@@ -242,6 +207,8 @@
     // mBinderEvents.
     void onBinderDiedUnlinkedHandler();
 
+    size_t countSubscribeClients();
+
     // Gets or creates a {@code T} object for the client to or from {@code clients}.
     template <class T>
     static std::shared_ptr<T> getOrCreateClient(
@@ -249,10 +216,14 @@
             const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
 
     static void onPropertyChangeEvent(
-            std::weak_ptr<SubscriptionManager> subscriptionManager,
+            const std::weak_ptr<SubscriptionManager>& subscriptionManager,
             const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
                     updatedValues);
 
+    static void onPropertySetErrorEvent(
+            const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+            const std::vector<SetValueErrorEvent>& errorEvents);
+
     static void checkHealth(IVehicleHardware* hardware,
                             std::weak_ptr<SubscriptionManager> subscriptionManager);
 
diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
index 14799d9..512d906 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
@@ -99,6 +99,15 @@
             const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
                     updatedValues);
 
+    // For a list of set property error events, returns a map that maps clients subscribing to the
+    // properties to a list of errors for each client.
+    std::unordered_map<CallbackType,
+                       std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
+    getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
+
+    // Returns the number of subscribed clients.
+    size_t countClients();
+
     // Checks whether the sample rate is valid.
     static bool checkSampleRateHz(float sampleRateHz);
 
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index 81d231c..35b93d2 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -38,6 +38,8 @@
 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
 using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
 using ::android::base::Result;
@@ -248,36 +250,6 @@
 template class GetSetValuesClient<GetValueResult, GetValueResults>;
 template class GetSetValuesClient<SetValueResult, SetValueResults>;
 
-SubscriptionClient::SubscriptionClient(std::shared_ptr<PendingRequestPool> requestPool,
-                                       std::shared_ptr<IVehicleCallback> callback)
-    : ConnectedClient(requestPool, callback) {
-    mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
-            [](std::unordered_set<int64_t> timeoutIds) {
-                for (int64_t id : timeoutIds) {
-                    ALOGW("subscribe: requests with IDs: %" PRId64
-                          " has timed-out, not client informed, "
-                          "possibly one of recurrent requests for this subscription failed",
-                          id);
-                }
-            });
-    auto requestPoolCopy = mRequestPool;
-    const void* clientId = reinterpret_cast<const void*>(this);
-    mResultCallback = std::make_shared<const IVehicleHardware::GetValuesCallback>(
-            [clientId, callback, requestPoolCopy](std::vector<GetValueResult> results) {
-                onGetValueResults(clientId, callback, requestPoolCopy, results);
-            });
-}
-
-std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>>
-SubscriptionClient::getResultCallback() {
-    return mResultCallback;
-}
-
-std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc>
-SubscriptionClient::getTimeoutCallback() {
-    return mTimeoutCallback;
-}
-
 void SubscriptionClient::sendUpdatedValues(std::shared_ptr<IVehicleCallback> callback,
                                            std::vector<VehiclePropValue>&& updatedValues) {
     if (updatedValues.empty()) {
@@ -300,48 +272,38 @@
     if (ScopedAStatus callbackStatus =
                 callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
         !callbackStatus.isOk()) {
-        ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, "
+        ALOGE("subscribe: failed to call onPropertyEvent callback, client ID: %p, error: %s, "
               "exception: %d, service specific error: %d",
               callback->asBinder().get(), callbackStatus.getMessage(),
               callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
     }
 }
 
-void SubscriptionClient::onGetValueResults(const void* clientId,
-                                           std::shared_ptr<IVehicleCallback> callback,
-                                           std::shared_ptr<PendingRequestPool> requestPool,
-                                           std::vector<GetValueResult> results) {
-    std::unordered_set<int64_t> requestIds;
-    for (const auto& result : results) {
-        requestIds.insert(result.requestId);
+void SubscriptionClient::sendPropertySetErrors(std::shared_ptr<IVehicleCallback> callback,
+                                               std::vector<VehiclePropError>&& vehiclePropErrors) {
+    if (vehiclePropErrors.empty()) {
+        return;
     }
 
-    auto finishedRequests = requestPool->tryFinishRequests(clientId, requestIds);
-    std::vector<VehiclePropValue> propValues;
-    for (auto& result : results) {
-        int64_t requestId = result.requestId;
-        if (finishedRequests.find(requestId) == finishedRequests.end()) {
-            ALOGE("subscribe[%" PRId64
-                  "]: no pending request for the result from hardware, "
-                  "possibly already time-out",
-                  requestId);
-            continue;
-        }
-        if (result.status != StatusCode::OK) {
-            ALOGE("subscribe[%" PRId64
-                  "]: hardware returns non-ok status for getValues, status: "
-                  "%d",
-                  requestId, toInt(result.status));
-            continue;
-        }
-        if (!result.prop.has_value()) {
-            ALOGE("subscribe[%" PRId64 "]: no prop value in getValues result", requestId);
-            continue;
-        }
-        propValues.push_back(std::move(result.prop.value()));
+    VehiclePropErrors vehiclePropErrorsLargeParcelable;
+    ScopedAStatus status = vectorToStableLargeParcelable(std::move(vehiclePropErrors),
+                                                         &vehiclePropErrorsLargeParcelable);
+    if (!status.isOk()) {
+        int statusCode = status.getServiceSpecificError();
+        ALOGE("subscribe: failed to marshal result into large parcelable, error: "
+              "%s, code: %d",
+              status.getMessage(), statusCode);
+        return;
     }
 
-    sendUpdatedValues(callback, std::move(propValues));
+    if (ScopedAStatus callbackStatus =
+                callback->onPropertySetError(vehiclePropErrorsLargeParcelable);
+        !callbackStatus.isOk()) {
+        ALOGE("subscribe: failed to call onPropertySetError callback, client ID: %p, error: %s, "
+              "exception: %d, service specific error: %d",
+              callback->asBinder().get(), callbackStatus.getMessage(),
+              callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
+    }
 }
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 98cfc39..f3eba2e 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -92,39 +92,6 @@
 
 }  // namespace
 
-std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::maybeAddClient(
-        const CallbackType& callback) {
-    std::scoped_lock<std::mutex> lockGuard(mLock);
-    return getOrCreateClient(&mClients, callback, mPendingRequestPool);
-}
-
-std::shared_ptr<SubscriptionClient> DefaultVehicleHal::SubscriptionClients::getClient(
-        const CallbackType& callback) {
-    std::scoped_lock<std::mutex> lockGuard(mLock);
-    const AIBinder* clientId = callback->asBinder().get();
-    if (mClients.find(clientId) == mClients.end()) {
-        return nullptr;
-    }
-    return mClients[clientId];
-}
-
-int64_t DefaultVehicleHal::SubscribeIdByClient::getId(const CallbackType& callback) {
-    std::scoped_lock<std::mutex> lockGuard(mLock);
-    // This would be initialized to 0 if callback does not exist in the map.
-    int64_t subscribeId = (mIds[callback->asBinder().get()])++;
-    return subscribeId;
-}
-
-void DefaultVehicleHal::SubscriptionClients::removeClient(const AIBinder* clientId) {
-    std::scoped_lock<std::mutex> lockGuard(mLock);
-    mClients.erase(clientId);
-}
-
-size_t DefaultVehicleHal::SubscriptionClients::countClients() {
-    std::scoped_lock<std::mutex> lockGuard(mLock);
-    return mClients.size();
-}
-
 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
     : mVehicleHardware(std::move(vehicleHardware)),
       mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
@@ -132,9 +99,6 @@
         return;
     }
 
-    mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
-
-    auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>();
     IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
     mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
 
@@ -144,6 +108,11 @@
                     [subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) {
                         onPropertyChangeEvent(subscriptionManagerCopy, updatedValues);
                     }));
+    mVehicleHardware->registerOnPropertySetErrorEvent(
+            std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
+                    [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
+                        onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
+                    }));
 
     // Register heartbeat event.
     mRecurrentAction = std::make_shared<std::function<void()>>(
@@ -177,7 +146,7 @@
 }
 
 void DefaultVehicleHal::onPropertyChangeEvent(
-        std::weak_ptr<SubscriptionManager> subscriptionManager,
+        const std::weak_ptr<SubscriptionManager>& subscriptionManager,
         const std::vector<VehiclePropValue>& updatedValues) {
     auto manager = subscriptionManager.lock();
     if (manager == nullptr) {
@@ -194,6 +163,20 @@
     }
 }
 
+void DefaultVehicleHal::onPropertySetErrorEvent(
+        const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+        const std::vector<SetValueErrorEvent>& errorEvents) {
+    auto manager = subscriptionManager.lock();
+    if (manager == nullptr) {
+        ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
+        return;
+    }
+    auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
+    for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
+        SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
+    }
+}
+
 template <class T>
 std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
         std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
@@ -243,7 +226,6 @@
     ALOGD("binder died, client ID: %p", clientId);
     mSetValuesClients.erase(clientId);
     mGetValuesClients.erase(clientId);
-    mSubscriptionClients->removeClient(clientId);
     mSubscriptionManager->unsubscribe(clientId);
 }
 
@@ -282,10 +264,6 @@
 DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
         std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>>* clients,
         const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
-template std::shared_ptr<SubscriptionClient>
-DefaultVehicleHal::getOrCreateClient<SubscriptionClient>(
-        std::unordered_map<const AIBinder*, std::shared_ptr<SubscriptionClient>>* clients,
-        const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
 
 void DefaultVehicleHal::setTimeout(int64_t timeoutInNano) {
     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
@@ -689,18 +667,19 @@
                                                                "client died");
         }
 
-        // Create a new SubscriptionClient if there isn't an existing one.
-        mSubscriptionClients->maybeAddClient(callback);
-
-        // Since we have already check the sample rates, the following functions must succeed.
         if (!onChangeSubscriptions.empty()) {
-            return toScopedAStatus(mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
-                                                                   /*isContinuousProperty=*/false));
+            auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
+                                                          /*isContinuousProperty=*/false);
+            if (!result.ok()) {
+                return toScopedAStatus(result);
+            }
         }
         if (!continuousSubscriptions.empty()) {
-            return toScopedAStatus(mSubscriptionManager->subscribe(callback,
-                                                                   continuousSubscriptions,
-                                                                   /*isContinuousProperty=*/true));
+            auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
+                                                          /*isContinuousProperty=*/true);
+            if (!result.ok()) {
+                return toScopedAStatus(result);
+            }
         }
     }
     return ScopedAStatus::ok();
@@ -819,12 +798,15 @@
         dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
-        dprintf(fd, "Currently have %zu subscription clients\n",
-                mSubscriptionClients->countClients());
+        dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
     }
     return STATUS_OK;
 }
 
+size_t DefaultVehicleHal::countSubscribeClients() {
+    return mSubscriptionManager->countClients();
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
index bba730f..17683ae 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -36,6 +36,7 @@
 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
 using ::android::base::Error;
 using ::android::base::Result;
@@ -269,11 +270,42 @@
     return clients;
 }
 
+std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>>
+SubscriptionManager::getSubscribedClientsForErrorEvents(
+        const std::vector<SetValueErrorEvent>& errorEvents) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>> clients;
+
+    for (const auto& errorEvent : errorEvents) {
+        PropIdAreaId propIdAreaId{
+                .propId = errorEvent.propId,
+                .areaId = errorEvent.areaId,
+        };
+        if (mClientsByPropIdArea.find(propIdAreaId) == mClientsByPropIdArea.end()) {
+            continue;
+        }
+
+        for (const auto& [_, client] : mClientsByPropIdArea[propIdAreaId]) {
+            clients[client].push_back({
+                    .propId = errorEvent.propId,
+                    .areaId = errorEvent.areaId,
+                    .errorCode = errorEvent.errorCode,
+            });
+        }
+    }
+    return clients;
+}
+
 bool SubscriptionManager::isEmpty() {
     std::scoped_lock<std::mutex> lockGuard(mLock);
     return mSubscribedPropsByClient.empty() && mClientsByPropIdArea.empty();
 }
 
+size_t SubscriptionManager::countClients() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return mSubscribedPropsByClient.size();
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 05e569a..fb14373 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -62,6 +62,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
@@ -349,7 +350,7 @@
     size_t countClients() {
         std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
         return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size() +
-               mVhal->mSubscriptionClients->countClients();
+               mVhal->countSubscribeClients();
     }
 
     std::shared_ptr<PendingRequestPool> getPool() { return mVhal->mPendingRequestPool; }
@@ -1653,6 +1654,63 @@
     ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos);
 }
 
+TEST_F(DefaultVehicleHalTest, testOnPropertySetErrorEvent) {
+    std::vector<SubscribeOptions> options = {
+            {
+                    .propId = GLOBAL_ON_CHANGE_PROP,
+                    .areaIds = {0},
+            },
+            {
+                    .propId = GLOBAL_CONTINUOUS_PROP,
+                    .areaIds = {0},
+                    .sampleRate = 1,
+            },
+    };
+    auto status = getClient()->subscribe(getCallbackClient(), options, 0);
+    ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
+    std::vector<SetValueErrorEvent> errorEvents = {
+            {
+                    .propId = GLOBAL_ON_CHANGE_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::INTERNAL_ERROR,
+            },
+            {
+                    .propId = GLOBAL_ON_CHANGE_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::ACCESS_DENIED,
+            },
+            {
+                    .propId = GLOBAL_CONTINUOUS_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::INVALID_ARG,
+            },
+    };
+    std::vector<VehiclePropError> expectedResults = {
+            {
+                    .propId = GLOBAL_ON_CHANGE_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::INTERNAL_ERROR,
+            },
+            {
+                    .propId = GLOBAL_ON_CHANGE_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::ACCESS_DENIED,
+            },
+            {
+                    .propId = GLOBAL_CONTINUOUS_PROP,
+                    .areaId = 0,
+                    .errorCode = StatusCode::INVALID_ARG,
+            },
+    };
+    getHardware()->sendOnPropertySetErrorEvent(errorEvents);
+
+    ASSERT_EQ(getCallback()->countOnPropertySetErrorResults(), 1u);
+    auto maybeVehiclePropErrors = getCallback()->nextOnPropertySetErrorResults();
+    ASSERT_TRUE(maybeVehiclePropErrors.has_value());
+    const auto& vehiclePropErrors = maybeVehiclePropErrors.value();
+    ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults));
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
index f51ce5c..54fede1 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
@@ -81,8 +81,14 @@
     return result;
 }
 
-ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) {
-    return ScopedAStatus::ok();
+ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors& results) {
+    ScopedAStatus result;
+    {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
+        result = storeResults(results, &mOnPropertySetErrorResults);
+    }
+    mCond.notify_all();
+    return result;
 }
 
 std::optional<GetValueResults> MockVehicleCallback::nextGetValueResults() {
@@ -105,6 +111,16 @@
     return mOnPropertyEventResults.size();
 }
 
+std::optional<VehiclePropErrors> MockVehicleCallback::nextOnPropertySetErrorResults() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return pop(mOnPropertySetErrorResults);
+}
+
+size_t MockVehicleCallback::countOnPropertySetErrorResults() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return mOnPropertySetErrorResults.size();
+}
+
 bool MockVehicleCallback::waitForSetValueResults(size_t size, size_t timeoutInNano) {
     std::unique_lock lk(mLock);
     return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] {
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
index f17b273..1545eae 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
@@ -63,6 +63,9 @@
     nextSetValueResults();
     std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
     nextOnPropertyEventResults();
+    size_t countOnPropertySetErrorResults();
+    std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
+    nextOnPropertySetErrorResults();
     size_t countOnPropertyEventResults();
     bool waitForSetValueResults(size_t size, size_t timeoutInNano);
     bool waitForGetValueResults(size_t size, size_t timeoutInNano);
@@ -77,6 +80,8 @@
     std::list<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
             mOnPropertyEventResults GUARDED_BY(mLock);
     int32_t mSharedMemoryFileCount GUARDED_BY(mLock);
+    std::list<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
+            mOnPropertySetErrorResults GUARDED_BY(mLock);
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index 4df4e1a..ba0d33d 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -131,8 +131,9 @@
 }
 
 void MockVehicleHardware::registerOnPropertySetErrorEvent(
-        std::unique_ptr<const PropertySetErrorCallback>) {
-    // TODO(b/200737967): mock this.
+        std::unique_ptr<const PropertySetErrorCallback> callback) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    mPropertySetErrorCallback = std::move(callback);
 }
 
 void MockVehicleHardware::setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
@@ -254,6 +255,12 @@
         std::list<std::vector<SetValueRequest>>* storedRequests,
         std::list<std::vector<SetValueResult>>* storedResponses) const;
 
+void MockVehicleHardware::sendOnPropertySetErrorEvent(
+        const std::vector<SetValueErrorEvent>& errorEvents) {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    (*mPropertySetErrorCallback)(errorEvents);
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index 743841c..46b30b9 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -85,6 +85,7 @@
                    aidl::android::hardware::automotive::vehicle::StatusCode status);
     void setSleepTime(int64_t timeInNano);
     void setDumpResult(DumpResult result);
+    void sendOnPropertySetErrorEvent(const std::vector<SetValueErrorEvent>& errorEvents);
 
   private:
     mutable std::mutex mLock;
@@ -104,6 +105,7 @@
             mStatusByFunctions GUARDED_BY(mLock);
     int64_t mSleepTime GUARDED_BY(mLock) = 0;
     std::unique_ptr<const PropertyChangeCallback> mPropertyChangeCallback GUARDED_BY(mLock);
+    std::unique_ptr<const PropertySetErrorCallback> mPropertySetErrorCallback GUARDED_BY(mLock);
     std::function<aidl::android::hardware::automotive::vehicle::StatusCode(
             std::shared_ptr<const GetValuesCallback>,
             const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>
diff --git a/automotive/vehicle/aidl_property/Android.bp b/automotive/vehicle/aidl_property/Android.bp
index 19fa4a3..db96382 100644
--- a/automotive/vehicle/aidl_property/Android.bp
+++ b/automotive/vehicle/aidl_property/Android.bp
@@ -28,7 +28,7 @@
         // This HAL was originally part of android.hardware.automotive.vehicle
         "android/hardware/automotive/vehicle/*.aidl",
     ],
-    frozen: true,
+    frozen: false,
     stability: "vintf",
     backend: {
         cpp: {
@@ -52,7 +52,6 @@
             version: "2",
             imports: [],
         },
-
     ],
 
 }
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
index 44c9d54..a24f515 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -34,6 +34,7 @@
 package android.hardware.automotive.vehicle;
 @Backing(type="int") @VintfStability
 enum VehicleAreaSeat {
+  UNKNOWN = 0x0000,
   ROW_1_LEFT = 0x0001,
   ROW_1_CENTER = 0x0002,
   ROW_1_RIGHT = 0x0004,
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
index 89d50ea..e70fb22 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -22,6 +22,7 @@
 @VintfStability
 @Backing(type="int")
 enum VehicleAreaSeat {
+    UNKNOWN = 0x0000,
     ROW_1_LEFT = 0x0001,
     ROW_1_CENTER = 0x0002,
     ROW_1_RIGHT = 0x0004,
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
index d9c6de7..7d88810 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -169,7 +169,7 @@
      *  int32Values[4] = wheel base
      *  int32Values[5] = track width front
      *  int32Values[6] = track width rear
-     *  int32Values[7] = curb to curb turning radius
+     *  int32Values[7] = curb to curb turning diameter
      *
      * @change_mode VehiclePropertyChangeMode.STATIC
      * @access VehiclePropertyAccess.READ
@@ -345,6 +345,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     FUEL_DOOR_OPEN = 0x0308 + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -383,6 +384,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     EV_CHARGE_PORT_OPEN = 0x030A + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -419,6 +421,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.CONTINUOUS
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @unit VehicleUnit:METER
      */
     RANGE_REMAINING = 0x0308 + 0x10000000 + 0x01000000
@@ -476,6 +479,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     ENGINE_IDLE_AUTO_STOP_ENABLED =
             0x0320 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -560,6 +564,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     EV_BRAKE_REGENERATION_LEVEL =
             0x040C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -648,6 +653,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum EvStoppingMode
      */
     EV_STOPPING_MODE =
@@ -696,8 +702,9 @@
      *     and passenger side, an alternative mapping would be:
      *      - ROW_1_LEFT
      *      - ROW_1_RIGHT
-     *
-     *
+     */
+
+    /**
      * Fan speed setting
      *
      * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined.
@@ -713,6 +720,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_FAN_SPEED = 0x0500 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -724,6 +732,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleHvacFanDirection
      */
     HVAC_FAN_DIRECTION = 0x0501 + 0x10000000 + 0x05000000
@@ -763,6 +772,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @unit VehicleUnit:CELSIUS
      */
     HVAC_TEMPERATURE_SET = 0x0503 + 0x10000000 + 0x05000000
@@ -775,6 +785,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_DEFROSTER = 0x0504 + 0x10000000 + 0x03000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -786,6 +797,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @config_flags Supported areaIds
      */
     HVAC_AC_ON = 0x0505 + 0x10000000 + 0x05000000
@@ -803,6 +815,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_MAX_AC_ON = 0x0506 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -825,6 +838,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_MAX_DEFROST_ON = 0x0507 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -841,6 +855,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_RECIRC_ON = 0x0508 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -879,6 +894,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_DUAL_ON = 0x0509 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -900,6 +916,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_AUTO_ON = 0x050A + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -921,6 +938,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_SEAT_TEMPERATURE = 0x050B + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -943,6 +961,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_SIDE_MIRROR_HEAT = 0x050C + 0x10000000 + 0x04000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -965,6 +984,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_STEERING_WHEEL_HEAT = 0x050D + 0x10000000 + 0x01000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -989,6 +1009,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleUnit
      */
     HVAC_TEMPERATURE_DISPLAY_UNITS = 0x050E + 0x10000000 + 0x01000000
@@ -1043,6 +1064,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_POWER_ON = 0x0510 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1077,6 +1099,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_AUTO_RECIRC_ON = 0x0512 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1101,6 +1124,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_SEAT_VENTILATION = 0x0513 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1112,6 +1136,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HVAC_ELECTRIC_DEFROSTER_ON = 0x0514 + 0x10000000 + 0x03000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -1175,6 +1200,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleUnit
      */
     DISTANCE_DISPLAY_UNITS = 0x0600 + 0x10000000 + 0x01000000
@@ -1198,6 +1224,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleUnit
      */
     FUEL_VOLUME_DISPLAY_UNITS = 0x0601 + 0x10000000 + 0x01000000
@@ -1222,6 +1249,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleUnit
      */
     TIRE_PRESSURE_DISPLAY_UNITS = 0x0602 + 0x10000000 + 0x01000000
@@ -1246,6 +1274,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleUnit
      */
     EV_BATTERY_DISPLAY_UNITS = 0x0603 + 0x10000000 + 0x01000000
@@ -1262,6 +1291,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 0x0604 + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1284,6 +1314,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -1633,6 +1664,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     DOOR_POS = 0x0B00 + 0x10000000 + 0x06000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
@@ -1657,6 +1689,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     DOOR_MOVE = 0x0B01 + 0x10000000 + 0x06000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
@@ -1670,6 +1703,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     DOOR_LOCK = 0x0B02 + 0x10000000 + 0x06000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:BOOLEAN
@@ -1685,6 +1719,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     DOOR_CHILD_LOCK_ENABLED =
             0x0B03 + VehiclePropertyGroup.SYSTEM + VehicleArea.DOOR + VehiclePropertyType.BOOLEAN,
@@ -1710,6 +1745,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_Z_POS = 0x0B40 + 0x10000000 + 0x04000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1735,6 +1771,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_Z_MOVE = 0x0B41 + 0x10000000 + 0x04000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1760,6 +1797,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_Y_POS = 0x0B42 + 0x10000000 + 0x04000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1784,6 +1822,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_Y_MOVE = 0x0B43 + 0x10000000 + 0x04000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
@@ -1797,6 +1836,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_LOCK = 0x0B44 + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1810,6 +1850,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     MIRROR_FOLD = 0x0B45 + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -1826,6 +1867,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
 
     MIRROR_AUTO_FOLD_ENABLED =
@@ -1843,6 +1885,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
 
     MIRROR_AUTO_TILT_ENABLED =
@@ -1891,6 +1934,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BELT_BUCKLED = 0x0B82 + 0x10000000 + 0x05000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
@@ -1915,6 +1959,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BELT_HEIGHT_POS = 0x0B83 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1942,6 +1987,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BELT_HEIGHT_MOVE = 0x0B84 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1966,6 +2012,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_FORE_AFT_POS = 0x0B85 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -1992,6 +2039,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_FORE_AFT_MOVE = 0x0B86 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2018,6 +2066,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BACKREST_ANGLE_1_POS = 0x0B87 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2044,6 +2093,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BACKREST_ANGLE_1_MOVE = 0x0B88 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2072,6 +2122,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BACKREST_ANGLE_2_POS = 0x0B89 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2098,6 +2149,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_BACKREST_ANGLE_2_MOVE = 0x0B8A + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2120,6 +2172,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEIGHT_POS = 0x0B8B + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2144,6 +2197,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEIGHT_MOVE = 0x0B8C + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2171,6 +2225,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_DEPTH_POS = 0x0B8D + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2196,6 +2251,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_DEPTH_MOVE = 0x0B8E + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2222,6 +2278,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_TILT_POS = 0x0B8F + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2248,6 +2305,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_TILT_MOVE = 0x0B90 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2272,6 +2330,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_FORE_AFT_POS = 0x0B91 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2299,6 +2358,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_FORE_AFT_MOVE = 0x0B92 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2323,6 +2383,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x0B93 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2350,6 +2411,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2369,6 +2431,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_HEIGHT_POS = 0x0B95 + 0x10000000 + 0x01000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
@@ -2395,6 +2458,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_HEIGHT_POS_V2 =
             0x0BA4 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2423,6 +2487,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_HEIGHT_MOVE = 0x0B96 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2445,6 +2510,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_ANGLE_POS = 0x0B97 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2472,6 +2538,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_ANGLE_MOVE = 0x0B98 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2494,6 +2561,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_FORE_AFT_POS = 0x0B99 + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2521,6 +2589,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
@@ -2565,6 +2634,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     SEAT_FOOTWELL_LIGHTS_SWITCH =
@@ -2581,6 +2651,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_EASY_ACCESS_ENABLED =
             0x0B9D + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -2600,6 +2671,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_AIRBAG_ENABLED =
             0x0B9E + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -2624,6 +2696,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_CUSHION_SIDE_SUPPORT_POS =
             0x0B9F + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2651,6 +2724,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_CUSHION_SIDE_SUPPORT_MOVE =
             0x0BA0 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2673,6 +2747,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_VERTICAL_POS =
             0x0BA1 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2698,6 +2773,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_LUMBAR_VERTICAL_MOVE =
             0x0BA2 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2723,6 +2799,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     SEAT_WALK_IN_POS =
             0x0BA3 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -2770,6 +2847,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     WINDOW_POS = 0x0BC0 + 0x10000000 + 0x03000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
@@ -2811,6 +2889,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
@@ -2824,6 +2903,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     WINDOW_LOCK = 0x0BC4 + 0x10000000 + 0x03000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
@@ -2889,6 +2969,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum WindshieldWipersSwitch
      */
     WINDSHIELD_WIPERS_SWITCH =
@@ -2915,6 +2996,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_DEPTH_POS =
             0x0BE0 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -2940,6 +3022,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_DEPTH_MOVE =
             0x0BE1 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -2962,6 +3045,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_HEIGHT_POS =
             0x0BE2 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -2987,6 +3071,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_HEIGHT_MOVE =
             0x0BE3 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
@@ -3001,6 +3086,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_THEFT_LOCK_ENABLED =
             0x0BE4 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3014,6 +3100,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_LOCKED =
             0x0BE5 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3028,6 +3115,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     STEERING_WHEEL_EASY_ACCESS_ENABLED =
             0x0BE6 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -3054,6 +3142,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     GLOVE_BOX_DOOR_POS =
             0x0BF0 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
@@ -3072,6 +3161,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     GLOVE_BOX_LOCKED =
             0x0BF1 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
@@ -3291,6 +3381,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     HEADLIGHTS_SWITCH = 0x0E10 + 0x10000000 + 0x01000000
@@ -3305,6 +3396,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     HIGH_BEAM_LIGHTS_SWITCH = 0x0E11 + 0x10000000 + 0x01000000
@@ -3335,6 +3427,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     FOG_LIGHTS_SWITCH = 0x0E12 + 0x10000000 + 0x01000000
@@ -3349,6 +3442,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     HAZARD_LIGHTS_SWITCH = 0x0E13 + 0x10000000 + 0x01000000
@@ -3377,6 +3471,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     CABIN_LIGHTS_SWITCH = 0x0F02 + 0x10000000 + 0x01000000
@@ -3405,6 +3500,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     READING_LIGHTS_SWITCH = 0x0F04 + 0x10000000 + 0x05000000
@@ -3450,6 +3546,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     STEERING_WHEEL_LIGHTS_SWITCH =
@@ -4119,6 +4216,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     FRONT_FOG_LIGHTS_SWITCH = 0x0F3C + 0x10000000 + 0x01000000
@@ -4150,6 +4248,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum VehicleLightSwitch
      */
     REAR_FOG_LIGHTS_SWITCH = 0x0F3E + 0x10000000 + 0x01000000
@@ -4166,6 +4265,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @unit VehicleUnit:AMPERE
      */
     EV_CHARGE_CURRENT_DRAW_LIMIT = 0x0F3F + 0x10000000 + 0x01000000
@@ -4187,6 +4287,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     EV_CHARGE_PERCENT_LIMIT = 0x0F40 + 0x10000000 + 0x01000000
             + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
@@ -4214,6 +4315,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     EV_CHARGE_SWITCH = 0x0F42 + 0x10000000 + 0x01000000
             + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
@@ -4375,8 +4477,12 @@
      * powers on the vehicle. VEHICLE_IN_USE is set to true. After a driving session, user powers
      * off the vehicle, VEHICLE_IN_USE is set to false.
      *
+     * <p>This property is defined as VehiclePropertyAccess.READ_WRITE, but OEMs have the option to
+     * implement it as VehiclePropertyAccess.READ only.
+     *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     VEHICLE_IN_USE =
             0x0F4A + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4403,6 +4509,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     AUTOMATIC_EMERGENCY_BRAKING_ENABLED =
             0x1000 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4445,6 +4552,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     FORWARD_COLLISION_WARNING_ENABLED =
             0x1002 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4484,6 +4592,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     BLIND_SPOT_WARNING_ENABLED =
             0x1004 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4524,6 +4633,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     LANE_DEPARTURE_WARNING_ENABLED =
             0x1006 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4568,6 +4678,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     LANE_KEEP_ASSIST_ENABLED =
             0x1008 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4616,6 +4727,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     LANE_CENTERING_ASSIST_ENABLED =
             0x100A + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4690,6 +4802,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     EMERGENCY_LANE_KEEP_ASSIST_ENABLED =
             0x100D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4733,6 +4846,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     CRUISE_CONTROL_ENABLED =
             0x100F + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
@@ -4758,6 +4872,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @data_enum CruiseControlType
      * @data_enum ErrorState
      */
@@ -4855,6 +4970,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      * @unit VehicleUnit:MILLI_SECS
      */
     ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP =
@@ -4906,6 +5022,7 @@
      *
      * @change_mode VehiclePropertyChangeMode.ON_CHANGE
      * @access VehiclePropertyAccess.READ_WRITE
+     * @access VehiclePropertyAccess.READ
      */
     HANDS_ON_DETECTION_ENABLED =
             0x1016 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
diff --git a/automotive/vehicle/tools/generate_annotation_enums.py b/automotive/vehicle/tools/generate_annotation_enums.py
old mode 100644
new mode 100755
index c36cbb0..fddc55b
--- a/automotive/vehicle/tools/generate_annotation_enums.py
+++ b/automotive/vehicle/tools/generate_annotation_enums.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # Copyright (C) 2022 The Android Open Source Project
 #
@@ -23,29 +23,35 @@
    Usage:
    $ python generate_annotation_enums.py
 """
+import argparse
+import filecmp
 import os
 import re
 import sys
+import tempfile
 
-PROP_AIDL_FILE_PATH = ("hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/" +
-    "automotive/vehicle/VehicleProperty.aidl")
-CHANGE_MODE_CPP_FILE_PATH = ("hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/" +
-    "ChangeModeForVehicleProperty.h")
-ACCESS_CPP_FILE_PATH = ("hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/" +
-    "AccessForVehicleProperty.h")
-CHANGE_MODE_JAVA_FILE_PATH = ("hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/" +
-    "ChangeModeForVehicleProperty.java")
-ACCESS_JAVA_FILE_PATH = ("hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/" +
-    "AccessForVehicleProperty.java")
+PROP_AIDL_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/' +
+    'automotive/vehicle/VehicleProperty.aidl')
+CHANGE_MODE_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
+    'ChangeModeForVehicleProperty.h')
+ACCESS_CPP_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/cpp/' +
+    'AccessForVehicleProperty.h')
+CHANGE_MODE_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
+    'ChangeModeForVehicleProperty.java')
+ACCESS_JAVA_FILE_PATH = ('hardware/interfaces/automotive/vehicle/aidl/generated_lib/java/' +
+    'AccessForVehicleProperty.java')
+SCRIPT_PATH = 'hardware/interfaces/automotive/vehicle/tools/generate_annotation_enums.py'
 
-TAB = "    "
-RE_ENUM_START = re.compile("\s*enum VehicleProperty \{")
-RE_ENUM_END = re.compile("\s*\}\;")
-RE_COMMENT_BEGIN = re.compile("\s*\/\*\*?")
-RE_COMMENT_END = re.compile("\s*\*\/")
-RE_CHANGE_MODE = re.compile("\s*\* @change_mode (\S+)\s*")
-RE_ACCESS = re.compile("\s*\* @access (\S+)\s*")
-RE_VALUE = re.compile("\s*(\w+)\s*=(.*)")
+TAB = '    '
+RE_ENUM_START = re.compile('\s*enum VehicleProperty \{')
+RE_ENUM_END = re.compile('\s*\}\;')
+RE_COMMENT_BEGIN = re.compile('\s*\/\*\*?')
+RE_COMMENT_END = re.compile('\s*\*\/')
+RE_CHANGE_MODE = re.compile('\s*\* @change_mode (\S+)\s*')
+RE_ACCESS = re.compile('\s*\* @access (\S+)\s*')
+RE_DATA_ENUM = re.compile('\s*\* @data_enum (\S+)\s*')
+RE_UNIT = re.compile('\s*\* @unit (\S+)\s+')
+RE_VALUE = re.compile('\s*(\w+)\s*=(.*)')
 
 LICENSE = """/*
  * Copyright (C) 2022 The Android Open Source Project
@@ -162,56 +168,123 @@
 """
 
 
-class Converter:
+class PropertyConfig:
+    """Represents one VHAL property definition in VehicleProperty.aidl."""
 
-    def __init__(self, name, annotation_re):
-        self.name = name
-        self.annotation_re = annotation_re
+    def __init__(self):
+        self.name = None
+        self.description = None
+        self.change_mode = None
+        self.access_modes = []
+        self.enum_types = []
+        self.unit_type = None
 
-    def convert(self, input, output, header, footer, cpp):
+    def __repr__(self):
+        return self.__str__()
+
+    def __str__(self):
+        return ('PropertyConfig{{' +
+            'name: {}, description: {}, change_mode: {}, access_modes: {}, enum_types: {}' +
+            ', unit_type: {}}}').format(self.name, self.description, self.change_mode,
+                self.access_modes, self.enum_types, self.unit_type)
+
+
+class FileParser:
+
+    def __init__(self):
+        self.configs = None
+
+    def parseFile(self, input_file):
+        """Parses the input VehicleProperty.aidl file into a list of property configs."""
         processing = False
         in_comment = False
-        content = LICENSE + header
-        annotation = None
-        id = 0
-        with open(input, 'r') as f:
+        configs = []
+        config = None
+        with open(input_file, 'r') as f:
             for line in f.readlines():
                 if RE_ENUM_START.match(line):
                     processing = True
-                    annotation = None
                 elif RE_ENUM_END.match(line):
                     processing = False
                 if not processing:
                     continue
                 if RE_COMMENT_BEGIN.match(line):
                     in_comment = True
+                    config = PropertyConfig()
+                    description = ''
                 if RE_COMMENT_END.match(line):
                     in_comment = False
                 if in_comment:
-                    match = self.annotation_re.match(line)
+                    if not config.description:
+                        sline = line.strip()
+                        # Skip the first line of comment
+                        if sline.startswith('*'):
+                            # Remove the '*'.
+                            sline = sline[1:].strip()
+                            # We reach an empty line of comment, the description part is ending.
+                            if sline == '':
+                                config.description = description
+                            else:
+                                if description != '':
+                                    description += ' '
+                                description += sline
+                    match = RE_CHANGE_MODE.match(line)
                     if match:
-                        annotation = match.group(1)
+                        config.change_mode = match.group(1).replace('VehiclePropertyChangeMode.', '')
+                    match = RE_ACCESS.match(line)
+                    if match:
+                        config.access_modes.append(match.group(1).replace('VehiclePropertyAccess.', ''))
+                    match = RE_UNIT.match(line)
+                    if match:
+                        config.unit_type = match.group(1)
+                    match = RE_DATA_ENUM.match(line)
+                    if match:
+                        config.enum_types.append(match.group(1))
                 else:
                     match = RE_VALUE.match(line)
                     if match:
                         prop_name = match.group(1)
-                        if prop_name == "INVALID":
+                        if prop_name == 'INVALID':
                             continue
-                        if not annotation:
-                            print("No @" + self.name + " annotation for property: " + prop_name)
-                            sys.exit(1)
-                        if id != 0:
-                            content += "\n"
-                        if cpp:
-                            annotation = annotation.replace(".", "::")
-                            content += (TAB + TAB + "{VehicleProperty::" + prop_name + ", " +
-                                        annotation + "},")
-                        else:
-                            content += (TAB + TAB + "Map.entry(VehicleProperty." + prop_name + ", " +
-                                        annotation + "),")
-                        id += 1
+                        if not config.change_mode:
+                            raise Exception(
+                                    'No change_mode annotation for property: ' + prop_name)
+                        if not config.access_modes:
+                            raise Exception(
+                                    'No access_mode annotation for property: ' + prop_name)
+                        config.name = prop_name
+                        configs.append(config)
 
-        # Remove the additional "," at the end for the Java file.
+        self.configs = configs
+
+    def convert(self, output, header, footer, cpp, field):
+        """Converts the property config file to C++/Java output file."""
+        counter = 0
+        content = LICENSE + header
+        for config in self.configs:
+            if field == 'change_mode':
+                if cpp:
+                    annotation = "VehiclePropertyChangeMode::" + config.change_mode
+                else:
+                    annotation = "VehiclePropertyChangeMode." + config.change_mode
+            elif field == 'access_mode':
+                if cpp:
+                    annotation = "VehiclePropertyAccess::" + config.access_modes[0]
+                else:
+                    annotation = "VehiclePropertyAccess." + config.access_modes[0]
+            else:
+                raise Exception('Unknown field: ' + field)
+            if counter != 0:
+                content += '\n'
+            if cpp:
+                content += (TAB + TAB + '{VehicleProperty::' + config.name + ', ' +
+                            annotation + '},')
+            else:
+                content += (TAB + TAB + 'Map.entry(VehicleProperty.' + config.name + ', ' +
+                            annotation + '),')
+            counter += 1
+
+        # Remove the additional ',' at the end for the Java file.
         if not cpp:
             content = content[:-1]
 
@@ -220,26 +293,119 @@
         with open(output, 'w') as f:
             f.write(content)
 
+    def outputAsCsv(self, output):
+        content = 'name,description,change mode,access mode,enum type,unit type\n'
+        for config in self.configs:
+            enum_types = None
+            if not config.enum_types:
+                enum_types = '/'
+            else:
+                enum_types = '/'.join(config.enum_types)
+            unit_type = config.unit_type
+            if not unit_type:
+                unit_type = '/'
+            access_modes = ''
+            content += '"{}","{}","{}","{}","{}","{}"\n'.format(
+                    config.name,
+                    # Need to escape quote as double quote.
+                    config.description.replace('"', '""'),
+                    config.change_mode,
+                    '/'.join(config.access_modes),
+                    enum_types,
+                    unit_type)
+
+        with open(output, 'w+') as f:
+            f.write(content)
+
+
+def createTempFile():
+    f = tempfile.NamedTemporaryFile(delete=False);
+    f.close();
+    return f.name
+
 
 def main():
-    android_top = os.environ['ANDROID_BUILD_TOP']
+    parser = argparse.ArgumentParser(
+            description='Generate Java and C++ enums based on annotations in VehicleProperty.aidl')
+    parser.add_argument('--android_build_top', required=False, help='Path to ANDROID_BUILD_TOP')
+    parser.add_argument('--preupload_files', nargs='*', required=False, help='modified files')
+    parser.add_argument('--check_only', required=False, action='store_true',
+            help='only check whether the generated files need update')
+    parser.add_argument('--output_csv', required=False,
+            help='Path to the parsing result in CSV style, useful for doc generation')
+    args = parser.parse_args();
+    android_top = None
+    output_folder = None
+    if args.android_build_top:
+        android_top = args.android_build_top
+        vehiclePropertyUpdated = False
+        for preuload_file in args.preupload_files:
+            if preuload_file.endswith('VehicleProperty.aidl'):
+                vehiclePropertyUpdated = True
+                break
+        if not vehiclePropertyUpdated:
+            return
+    else:
+        android_top = os.environ['ANDROID_BUILD_TOP']
     if not android_top:
-        print("ANDROID_BUILD_TOP is not in envorinmental variable, please run source and lunch " +
-            "at the android root")
+        print('ANDROID_BUILD_TOP is not in envorinmental variable, please run source and lunch ' +
+            'at the android root')
 
     aidl_file = os.path.join(android_top, PROP_AIDL_FILE_PATH)
-    change_mode_cpp_output = os.path.join(android_top, CHANGE_MODE_CPP_FILE_PATH);
-    access_cpp_output = os.path.join(android_top, ACCESS_CPP_FILE_PATH);
-    change_mode_java_output = os.path.join(android_top, CHANGE_MODE_JAVA_FILE_PATH);
-    access_java_output = os.path.join(android_top, ACCESS_JAVA_FILE_PATH);
+    f = FileParser();
+    f.parseFile(aidl_file)
 
-    c = Converter("change_mode", RE_CHANGE_MODE);
-    c.convert(aidl_file, change_mode_cpp_output, CHANGE_MODE_CPP_HEADER, CHANGE_MODE_CPP_FOOTER, True)
-    c.convert(aidl_file, change_mode_java_output, CHANGE_MODE_JAVA_HEADER, CHANGE_MODE_JAVA_FOOTER, False)
-    c = Converter("access", RE_ACCESS)
-    c.convert(aidl_file, access_cpp_output, ACCESS_CPP_HEADER, ACCESS_CPP_FOOTER, True)
-    c.convert(aidl_file, access_java_output, ACCESS_JAVA_HEADER, ACCESS_JAVA_FOOTER, False)
+    if args.output_csv:
+        f.outputAsCsv(args.output_csv)
+        return
+
+    change_mode_cpp_file = os.path.join(android_top, CHANGE_MODE_CPP_FILE_PATH);
+    access_cpp_file = os.path.join(android_top, ACCESS_CPP_FILE_PATH);
+    change_mode_java_file = os.path.join(android_top, CHANGE_MODE_JAVA_FILE_PATH);
+    access_java_file = os.path.join(android_top, ACCESS_JAVA_FILE_PATH);
+    temp_files = []
+
+    if not args.check_only:
+        change_mode_cpp_output = change_mode_cpp_file
+        access_cpp_output = access_cpp_file
+        change_mode_java_output = change_mode_java_file
+        access_java_output = access_java_file
+    else:
+        change_mode_cpp_output = createTempFile()
+        temp_files.append(change_mode_cpp_output)
+        access_cpp_output = createTempFile()
+        temp_files.append(access_cpp_output)
+        change_mode_java_output = createTempFile()
+        temp_files.append(change_mode_java_output)
+        access_java_output = createTempFile()
+        temp_files.append(access_java_output)
+
+    try:
+        f.convert(change_mode_cpp_output, CHANGE_MODE_CPP_HEADER, CHANGE_MODE_CPP_FOOTER,
+                True, 'change_mode')
+        f.convert(change_mode_java_output, CHANGE_MODE_JAVA_HEADER,
+                CHANGE_MODE_JAVA_FOOTER, False, 'change_mode')
+        f.convert(access_cpp_output, ACCESS_CPP_HEADER, ACCESS_CPP_FOOTER, True, 'access_mode')
+        f.convert(access_java_output, ACCESS_JAVA_HEADER, ACCESS_JAVA_FOOTER, False, 'access_mode')
+
+        if not args.check_only:
+            return
+
+        if ((not filecmp.cmp(change_mode_cpp_output, change_mode_cpp_file)) or
+                (not filecmp.cmp(change_mode_java_output, change_mode_java_file)) or
+                (not filecmp.cmp(access_cpp_output, access_cpp_file)) or
+                (not filecmp.cmp(access_java_output, access_java_file))):
+            print('The generated enum files for VehicleProperty.aidl requires update, ')
+            print('Run \npython ' + android_top + '/' + SCRIPT_PATH)
+            sys.exit(1)
+    except Exception as e:
+        print('Error parsing VehicleProperty.aidl')
+        print(e)
+        sys.exit(1)
+    finally:
+        for file in temp_files:
+            os.remove(file)
 
 
-if __name__ == "__main__":
+if __name__ == '__main__':
     main()
\ No newline at end of file
diff --git a/automotive/vehicle/vhal_static_cpp_lib.mk b/automotive/vehicle/vhal_static_cpp_lib.mk
index 995589c..bffa076 100644
--- a/automotive/vehicle/vhal_static_cpp_lib.mk
+++ b/automotive/vehicle/vhal_static_cpp_lib.mk
@@ -17,4 +17,4 @@
 
 LOCAL_STATIC_LIBRARIES += \
     android.hardware.automotive.vehicle-V2-ndk \
-    android.hardware.automotive.vehicle.property-V2-ndk
+    android.hardware.automotive.vehicle.property-V3-ndk
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 876a91f..7bc2198 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -7,11 +7,21 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+filegroup {
+    name: "face-example.rc",
+    srcs: ["face-example.rc"],
+}
+
+filegroup {
+    name: "face-example.xml",
+    srcs: ["face-example.xml"],
+}
+
 cc_binary {
     name: "android.hardware.biometrics.face-service.example",
     relative_install_path: "hw",
-    init_rc: ["face-default.rc"],
-    vintf_fragments: ["face-default.xml"],
+    init_rc: [":face-example.rc"],
+    vintf_fragments: [":face-example.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.h b/biometrics/face/aidl/default/FakeFaceEngine.h
index edb54ce..eb99441 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.h
+++ b/biometrics/face/aidl/default/FakeFaceEngine.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#define LOG_TAG "FaceVirtualHal"
+
 #include <aidl/android/hardware/biometrics/common/SensorStrength.h>
 #include <aidl/android/hardware/biometrics/face/BnSession.h>
 #include <aidl/android/hardware/biometrics/face/FaceSensorType.h>
@@ -62,4 +64,4 @@
     std::mt19937 mRandom;
 };
 
-}  // namespace aidl::android::hardware::biometrics::face
\ No newline at end of file
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/README.md b/biometrics/face/aidl/default/README.md
index 1655973..77bfe57 100644
--- a/biometrics/face/aidl/default/README.md
+++ b/biometrics/face/aidl/default/README.md
@@ -1,77 +1,63 @@
-# Virtual Face HAL
+# Face Virtual HAL (VHAL)
 
 This is a virtual HAL implementation that is backed by system properties
 instead of actual hardware. It's intended for testing and UI development
 on debuggable builds to allow devices to masquerade as alternative device
 types and for emulators.
+Note: The virtual face HAL feature development will be done in phases. Refer to this doc often for
+the latest supported features
 
-## Device Selection
+## Supported Devices
 
-You can either run the FakeFaceEngine on a [real device](#actual-device) or a [virtual device/cuttlefish](#getting-started-on-a-virtual-device-cuttlefish). This document should
-help you to get started on either one.
+The face virtual hal is automatically built in in all debug builds (userdebug and eng) for the latest pixel devices and CF.
+The instructions in this doc applies  to all
 
-After setting up a device, go ahead and try out [enrolling](#enrolling) & [authenticating](#authenticating)
+## Enabling Face Virtual HAL
 
-### Getting started on a Virtual Device (cuttlefish)
+On pixel devicse (non-CF), by default (after manufacture reset), Face VHAL is not enabled. Therefore real Face HAL is used.
+Face VHAL enabling is gated by the following two AND conditions:
+1. The Face VHAL feature flag (as part of Trunk-development strategy) must be tured until the flags life-cycle ends.
+2. The Face VHAL must be enabled via sysprop
 
+##Getting Stared
 
-Note, I'm running this via a cloudtop virtual device.
+A basic use case for a successful authentication via Face VHAL is given as an exmple below.
 
-1. Setup cuttlefish on cloudtop, See [this](https://g3doc.corp.google.com/company/teams/android/teampages/acloud/getting_started.md?cl=head) for more details.
-2. acloud create --local-image
-3. Enter in the shell command to disable hidl
-
+### Enabling VHAL
 ```shell
 $ adb root
-$ adb shell settings put secure com.android.server.biometrics.AuthService.hidlDisabled 1
-$ adb reboot
-```
-4. You should now be able to do fake enrollments and authentications (as seen down below)
-
-### Actual Device
-
-1. Modify your real devices make file (I.E. vendor/google/products/{YOUR_DEVICE}.mk)
-2. Ensure that there is no other face HAL that is being included by the device
-3. Add the following
-```
-PRODUCT_COPY_FILES += \
-    frameworks/native/data/etc/android.hardware.biometrics.face.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/android.hardware.biometrics.face.xml
-
-PRODUCT_PACKAGES += \
-    android.hardware.biometrics.face-service.example \
-
-```
-4. Now build and flash m -j120 && flash
-5. Run the following commands
-
-```shell
-# This is a temporary workaround
-$ adb root
-$ adb shell setprop persist.vendor.face.virtual.type RGB
+$ adb shell device_config put biometrics_framework com.android.server.biometrics.face_vhal_feature true
+$ adb shell settings put secure biometric_virtual_enabled 1
 $ adb shell setprop persist.vendor.face.virtual.strength strong
-$ adb shell locksettings set-pin 0000
+$ adb shell setprop persist.vendor.face.virtual.type RGB
 $ adb reboot
 ```
 
-## Enrolling
+### Direct Enrollment
+```shell
+$ adb shell locksettings set-pin 0000
+$ adb shell setprop persist.vendor.face.virtual.enrollments 1
+$ adb shell cmd face syncadb shell cmd face sync
+```
+
+## Authenticating
+To authenticate successfully, the captured (hit) must match the enrollment id set above. To  trigger
+authentication failure, set the hit id to a different value.
+```shell
+$ adb shell setprop vendor.face.virtual.operation_authenticate_duration 800
+$ adb shell setprop vendor.face.virtual.enrollment_hit 1
+```
+Note: At the initial phase of the Face VHAL development, Face-on-camera simulation is not supported, hence
+the authentication immediately occurrs  as soon as the authentication request arriving at VHAL.
+
+
+## Enrollment via Setup
 
 ```shell
 # authenticar_id,bucket_id:duration:(true|false)....
 $ adb shell setprop vendor.face.virtual.next_enrollment 1,0:500:true,5:250:true,10:150:true,15:500:true
-$ adb shell am start -n com.android.settings/.biometrics.face.FaceEnrollIntroduction
+$ walk thru the manual enrollment process by following screen instructions
+
 # If you would like to get rid of the enrollment, run the follwoing command
 $ adb shell setprop persist.vendor.face.virtual.enrollments \"\"
 ```
-
-## Authenticating
-
-```shell
-# If enrollment hasn't been setup
-$ adb shell setprop persist.vendor.face.virtual.enrollments 1
-$ adb shell cmd face sync
-# After enrollment has been setup
-$ adb shell setprop vendor.face.virtual.operation_authenticate_duration 800
-$ adb shell setprop vendor.face.virtual.enrollment_hit 1
-# Power button press to simulate auth
-$ adb shell input keyevent 26
-```
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index 1188459..6235b83 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -18,6 +18,9 @@
 
 #include "Session.h"
 
+#undef LOG_TAG
+#define LOG_TAG "FaceVirtualHalSession"
+
 namespace aidl::android::hardware::biometrics::face {
 
 constexpr size_t MAX_WORKER_QUEUE_SIZE = 5;
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..9c031a3
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -0,0 +1,74 @@
+// Copyright (C) 2023 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+    name: "com.android.hardware.biometrics.face.virtual.key",
+    public_key: "com.android.hardware.biometrics.face.virtual.avbpubkey",
+    private_key: "com.android.hardware.biometrics.face.virtual.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.biometrics.face.virtual.certificate",
+    certificate: "com.android.hardware.biometrics.face.virtual",
+}
+
+apex {
+    name: "com.android.hardware.biometrics.face.virtual",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.biometrics.face.virtual.key",
+    certificate: ":com.android.hardware.biometrics.face.virtual.certificate",
+    updatable: false,
+    vendor: true,
+    use_vndk_as_stable: true,
+
+    binaries: [
+        // hal
+        "android.hardware.biometrics.face-service.example",
+    ],
+    prebuilts: [
+        // init_rc
+        "face-example-apex.rc",
+        // vintf_fragment
+        "face-example-apex.xml",
+    ],
+
+    overrides: [
+        "android.hardware.biometrics.face-service.example",
+    ],
+}
+
+prebuilt_etc {
+    name: "face-example-apex.rc",
+    src: ":gen-face-example-apex.rc",
+    installable: false,
+}
+
+genrule {
+    name: "gen-face-example-apex.rc",
+    srcs: [":face-example.rc"],
+    out: ["face-example-apex.rc"],
+    cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face.virtual/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "face-example-apex.xml",
+    src: ":face-example.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.avbpubkey b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.avbpubkey
new file mode 100644
index 0000000..9f358ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.avbpubkey
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pem
new file mode 100644
index 0000000..ad8f57d
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCoZ28KVXxB9kkX
+zPhi8pVSmiMU0xchU4PkoOvFzmr9t5b7rA1zmzOLjkNWMrxt1XCUEfOgT3N50z5T
+484dpEZBrwIH31NqSOr/T8mG5frZAkNg0WqfgV+AG81mCuA+nG4a08fmDL4nEzVg
+irQvWpXzRCNIn+LEx+gG4I2KG8EGWDiFnzXwSFJG4n60rfLQNHgsejv/06BmPCnS
+gp06LhqJTO2oJKCJVQxfO0TPNUd9FSVSXdWuHcHE2gwoHM/7C/10Bdx8XXCMbAQR
+a4d3moH5oRuhh1841PtIQ0ozw/vHapCTmdMbjmgbwpXZ49DfvJl2cnz5c5G/CUO1
+9CkLDdxffsHh48jLUzH1nRgcWW2CAnSIs8nGjScyOKB+gn831ke8agJGbVHs1Cp/
+ONbMZeQIhEL0kderI1vVoufeBf38/I93rpz6PXp5NiTwOnVdEik595/W7oldr/rM
+taKvWwfnjml+Z1uzJWWDKPnS+onxBVcoBGFhiewIejPz3UjncMiHW5QAx/BzfGgh
+UmFO0vsh8qrEfAqT4AqL4uCuyVm0JmugdWKoeQISh5i4+HMmvPaudd+8yF0plr10
++pyNGkLZm4NBJxOD7V0AMjfTIpKRbmV8xnCAnWQ+xx/qWxHAZ0wfbZXXF0m6L6po
+dVwJJI7EnuQbAkbXnzMtCTQToZTSVwIDAQABAoICAAGjGJNY15kYKO3xzXWMyfXT
+gl7L9Im1TNVwP3Dpu+S7U0NSd1w12Iju35znzlwhx7/j8skOrKubaZvM9ztJ79Yb
+1CDs3PWhP6OVJeGvvHU9zkp59RexQ5Ma8hXskIroE2WJ97bQgRkfi/r9x8wKc39T
+aYv/SrTC0SPr+YRFSjMvfV35kvLC759slgwkmsH6ZWatSeyhPooJfX1kTRBi08A2
+i4lOBD+Bhtn2jG/+1eYtFyYXVaHx/E9XfU6QhSPgIhBULdujPucmj6pc4yRYnKxA
+32QxGc35u0QHEqJ9/iWAoporIMAmU/Qp7phl9g+OvxrFkloMc3cp3GSMh8k2bJUY
+nRvk0IPG1bF7jwezHbQGTwTlguJlWPl3+v+qeKJQI4pov3Cz6aNrBmBfEbjwcJrf
+RvPNCQ2X1GciZcGoJxcHRgFNKarzb+m92qNRftr6YDBZM8PlvJgGhnTRkOuFmIZB
+WPRergEwaClp1DbQsXwKlWpGfSMLznj57oKT3MJ31R4pusfMDBS39p9jUFH7uO+p
+e/Wdy+RaKei4AYBZIc+ks8LJzeIG+YWD9kN0lPVvzoza6nJYGGNVe/bxErjpESsR
+fZDs5EMNPGsCQ56Tgt+vtHEGF3x7ufGMF1XqisCMlaxH03aT2N3Wi5um8jO2pfFC
+4NEBq4ixvlyefb0TER+5AoIBAQC6nSDDzeeseLOJ8QSb1kHHkvQOGb8kdYY/KJ51
++uiwoEWOYAxKubqumo2rYaqcM0lbZKWb/9cgVK4LAzdqY4z3BINA7YRzXSUXdb8T
+rbqtg33Yj7f1KBiBqns2FMktfIZ+6JUDALb+CD7rHGpi62RDd8JaKL8wugqMBmwM
+YHBfzECVSjDosjGpbILbDJPTfiEQLyPEoJxJ48Z3Xg6l+0BSZrrH9FqGVgsvEQ7f
+zhZ6rpJIefb1cFjwIRFORS4tMqS1keu+dugyUBs83AOp5kaq6O31n5hDAOyZVFsw
+HSBu8pbWAceWJrF7R1Am23063hIztjPbU9yeN2mvhVQSgO4PAoIBAQDnBQHt3prI
+AajCYbHmk0v1WT2kDD5yEX/fZzifTU5k/+0Jvixpa0KOR2qaUXyx4ocIT6F1hR89
+VXGby2UG6SlvuwXMzwmoVf5sueQ6wshu3fCaS8BYNpJnOAfgLTnUpKIWITDm/2Hj
+4NCFYL77EfBXXhFH7lLPhiPcTWQlPDuFCXU/BJuVhJbpd+GtF1+loiNQArg9nmKb
+9Ac7ccR9UBO/XSQN1th4+yaxyGQKaiYsBqsy8SPp2ynTdGXT72LePqSUrkNsjgE7
+PkzgX0pBZw8upBXk+8ByfIaaQONRbCuMQEXj6B66szaWeR2hDfaoDOk3/w6JN93r
+yPKfk4TFNB85AoIBAGoiHVVfUOjViP7l9cIPvD+eQ3GVkRFSSfS3zE+7UQXLUWPl
+GniRYywUuIgFNvw5avowpsOvYRGBN68JuEWosq52gZO2wkK+ce8Cx5aQkwBGLZey
+PWSP1khAxmx+q+BT10ZsTvtzN6AI3ofnFFaIG/EHNqECVaKH3KHAsUjkvGSvjPeb
+R2/AkOAT1+RvJc/+Bx3mQYh99AVOJz0SYHBkEjQLOyWnwqhuXVP6dqQw2LYTfRz9
+SMhUijCgDfCfBeEs0WJ2yEX96Jdc2fDmDKtfTUe8zEGK8BUDfIzD3kzh8+VF0SWL
+w5CRFxXO/DXtVS7ayC1i7eFKs8nEKDZsNOGFNF8CggEAKXRMlFKNk7Y4gijls2pb
+Bvusg/NugSmCuKPdFTjaCGWkM0tczM3ic4V9K5PTvFfZwzQG1P++S1M5v6sPxd2x
+AcudjtLX+Mz1iq0QtzqcnMhWlFljenDQdJUpVKDI789bBn2OOOU6u5lr0YM6wfLG
+HedTUoUBdxuq860vez8DryuzTkuVX48bRWmtpVG8aAxgKctTJDt3lmSDp7cSeyoT
+YRNllNYoogzvNJew2+2QS/YmYk3DFAOvzbHlU9Jw+1BiWAutLZ2NuwPC58AxourL
+XqMzCpPiRKjzvlpGcCXo6pHd+Ld+TCI8eWPiXTQUPrOSZenuwdC0kcrNPrVJ7dkc
+gQKCAQEAmE6BTX7nn0HT859PtBlsy3rM8psihR4UYuYkTdE0+KF4hBRIP6uhMAVh
+vV6UMnt3QubKIekG14seGkwkBnEhv5reYWn/1+t3qP7qqvgndGgI2yPbzJx/cPMK
++KKhRbBAIgkjiY6hlo+DhrNS5nuBjZS2q/NnkO4NK7qBHvpIYAnRZK9qNsT4KZm6
+EO9YlCCnoZ3EB7brNgBZkxoekZG4jTlpD0E7nTxPTF1iVWedKRfmLFxAiDaSz0eo
+9tbTaRQ6ybU6jl1hMg4aINjp4xl/ScKk51veKg5ptjpPtspIh7keJRIUz3qwhuvk
+ZJpVwCxgxAOagrQtvwdedbmvChAfGA==
+-----END PRIVATE KEY-----
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pk8 b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pk8
new file mode 100644
index 0000000..af0ff4e
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.pk8
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.x509.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.x509.pem
new file mode 100644
index 0000000..3dc37ff
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.virtual.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF7TCCA9UCFCmJBOOYRVUgdy8vKm8OQd0ii2pPMA0GCSqGSIb3DQEBCwUAMIGx
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEtMCsGA1UEAwwkY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5mYWNlMCAXDTIzMDUyNTA2NDIw
+MFoYDzQ3NjEwNDIwMDY0MjAwWjCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJv
+aWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k
+cm9pZC5jb20xLTArBgNVBAMMJGNvbS5hbmRyb2lkLmhhcmR3YXJlLmJpb21ldHJp
+Y3MuZmFjZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPadnCNPEvKN
+HxACZt3C+tE2rga6gZ1pxfvlwGo1UY9yAxcQjL22SW93OA6R3de5uvQUbHh7b9g5
+AbNYcRnxOMiuUK2XSGWGDscxuGpQVCph4G1rXCOtbTmz1Zb42vQLCCQHHyxzI7ZE
+9Y6+rzw4p3jtEyBSiiErk13GFZTzwcDzqsQs12vDn9ovSTTn5Nyy6Csz7+O2t4SN
+qU4S/uLE6b/TiXj7196r58DcGvJgKbzbbnv/DUHGfaESrVWYLk3xoX3X8VJvP7jI
+M9XoZBbbgFLgAP5DFEvf5QWS9tR092z0YXOGr+mLHtkJM7Or9nKOohm6aFfHbuvu
+pSWyR4FWnaFANQ8wLH+fH485fiO6juJdTuRWeQpZddv0/IgguZ2Plu7z6NHCf5+L
+KYFjQ5y716wOufIqHhRLqYnpsAG2AFaMuPKzsy2KMifqoyB4KYR24EA1MCT7vwqu
+Hurp+SJrmNdkFVXbhGVUfMKf4nRZ37b9Miie0ju0OxJ9C3zY5uR5BMnqEjqq/rCX
+pQh5o1y+bWacOQVp0iQWJHfy8KkjhhQ1Pd1VeoVk9l2DsAJWm6unwMvGHviRcvzg
+BejDOVcE0x4xDj+TwAu2X2+w2hbUSY9W6lmkX4nGHlbLz211bIBFq42PzAMpRnYq
+jLxml4VpO4UnhyRp7Ipps99s7/iMFOn7AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
+AG/5t56hKYKORne0bwJpMSCWZNT6JcYjf6fEmNrvG3/gz9BCuj4osZjJHD2OSUJl
+F5yI52RgPrXK8bNqJOvX6MIc4Y2JoSI2Uz4J2vZ3QhRkPC9oqwk/Enz4GIVJ4Dnm
+/kgpBbN2SN0TjnmEooptly5tWb3IPTjqLZpaPIW1ntQeCAbgrYVHiMsvNe1BuBrn
+RNi1xqw3QGp2ZV/RfJ3MH6d49TswEL1gwiUeg3hw5eG7IDfLB/2IJBrff7kmPTQ6
+n+il4uXuXMmX70xSvJXwP/NinomJsORZ4Npbmp7xV/QJp9cNoxNAo3DJ4OHRAnA+
+L7E1KZ3+nSRxGcVlqBekmG6wH9U39NN+dh758aGdJOWqA+B+1PAGxkvFCNqLgTpm
+xNl62YiRRo4FiIAkntvs+JneMEphv/T5i824t2xFZD2lBuW8r54nWj5cpx8AU9W2
+rulR0jx7BnVdj6czn1/pPCIah8Os9pZM8q1CbF8vXD+QLAF0/NjPNomTEGd/M+V+
+sfn1OhLGF/E1kWyNeOmkvX26txQdY8k6jUdsAc5vmQqgwxdorjI38ynpYQnFwq2g
+eO4l62sx8icsSh2TRklWy8BwZpaCyO/WVv/FcjIUexYhmZ0EHpmQk/RAlD1f9wFy
+CciNa/Dm94AwJgZk9LcXye3BSvb1sKF6C7eYrW0eI95V
+-----END CERTIFICATE-----
diff --git a/biometrics/face/aidl/default/apex/file_contexts b/biometrics/face/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..4f935c1
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:hal_face_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/face/aidl/default/apex/manifest.json b/biometrics/face/aidl/default/apex/manifest.json
new file mode 100644
index 0000000..ecdc299
--- /dev/null
+++ b/biometrics/face/aidl/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.biometrics.face.virtual",
+    "version": 1
+}
diff --git a/biometrics/face/aidl/default/face-default.rc b/biometrics/face/aidl/default/face-default.rc
deleted file mode 100644
index f6499f0..0000000
--- a/biometrics/face/aidl/default/face-default.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.example
-    class hal
-    user nobody
-    group nobody
-
diff --git a/biometrics/face/aidl/default/face-example.rc b/biometrics/face/aidl/default/face-example.rc
new file mode 100644
index 0000000..b0d82c6
--- /dev/null
+++ b/biometrics/face/aidl/default/face-example.rc
@@ -0,0 +1,8 @@
+service vendor.face-example /vendor/bin/hw/android.hardware.biometrics.face-service.example
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.biometrics.face.IFace/virtual
+    oneshot
+    disabled
+
diff --git a/biometrics/face/aidl/default/face-default.xml b/biometrics/face/aidl/default/face-example.xml
similarity index 81%
rename from biometrics/face/aidl/default/face-default.xml
rename to biometrics/face/aidl/default/face-example.xml
index 8f2fbb8..1c5071a 100644
--- a/biometrics/face/aidl/default/face-default.xml
+++ b/biometrics/face/aidl/default/face-example.xml
@@ -2,6 +2,6 @@
     <hal format="aidl">
         <name>android.hardware.biometrics.face</name>
         <version>3</version>
-        <fqname>IFace/default</fqname>
+        <fqname>IFace/virtual</fqname>
     </hal>
 </manifest>
diff --git a/biometrics/face/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp
index b7274e3..38e1c63 100644
--- a/biometrics/face/aidl/default/main.cpp
+++ b/biometrics/face/aidl/default/main.cpp
@@ -27,9 +27,11 @@
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
 
-    const std::string instance = std::string(Face::descriptor) + "/default";
-    binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
+    const std::string instance = std::string(Face::descriptor) + "/virtual";
+    binder_status_t status =
+            AServiceManager_registerLazyService(hal->asBinder().get(), instance.c_str());
     CHECK_EQ(status, STATUS_OK);
+    AServiceManager_forceLazyServicesPersist(true);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 16302eb..3bb3f3a 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -11,8 +11,8 @@
     name: "android.hardware.biometrics.fingerprint-service.example",
     vendor: true,
     relative_install_path: "hw",
-    init_rc: ["fingerprint-example.rc"],
-    vintf_fragments: ["fingerprint-example.xml"],
+    init_rc: [":fingerprint-example.rc"],
+    vintf_fragments: [":fingerprint-example.xml"],
     local_include_dirs: ["include"],
     srcs: [
         "FakeLockoutTracker.cpp",
@@ -142,3 +142,13 @@
     property_owner: "Vendor",
     vendor: true,
 }
+
+filegroup {
+    name: "fingerprint-example.rc",
+    srcs: ["fingerprint-example.rc"],
+}
+
+filegroup {
+    name: "fingerprint-example.xml",
+    srcs: ["fingerprint-example.xml"],
+}
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 90ec8f2..54076c8 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -31,6 +31,9 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
+FakeFingerprintEngine::FakeFingerprintEngine()
+    : mRandom(std::mt19937::default_seed), mWorkMode(WorkMode::kIdle) {}
+
 void FakeFingerprintEngine::generateChallengeImpl(ISessionCallback* cb) {
     BEGIN_OP(0);
     std::uniform_int_distribution<int64_t> dist;
@@ -48,7 +51,7 @@
 void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
                                        const keymaster::HardwareAuthToken& hat,
                                        const std::future<void>& cancel) {
-    BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
+    BEGIN_OP(0);
 
     // Do proper HAT verification in the real implementation.
     if (hat.mac.empty()) {
@@ -57,13 +60,77 @@
         return;
     }
 
+    updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
+}
+
+void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t operationId,
+                                             const std::future<void>& cancel) {
+    BEGIN_OP(0);
+    updateContext(WorkMode::kAuthenticate, cb, const_cast<std::future<void>&>(cancel), operationId,
+                  keymaster::HardwareAuthToken());
+}
+
+void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
+                                                  const std::future<void>& cancel) {
+    BEGIN_OP(0);
+
+    auto detectInteractionSupported =
+            FingerprintHalProperties::detect_interaction().value_or(false);
+    if (!detectInteractionSupported) {
+        LOG(ERROR) << "Detect interaction is not supported";
+        cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+        return;
+    }
+
+    updateContext(WorkMode::kDetectInteract, cb, const_cast<std::future<void>&>(cancel), 0,
+                  keymaster::HardwareAuthToken());
+}
+
+void FakeFingerprintEngine::updateContext(WorkMode mode, ISessionCallback* cb,
+                                          std::future<void>& cancel, int64_t operationId,
+                                          const keymaster::HardwareAuthToken& hat) {
+    mCancel = std::move(cancel);
+    mWorkMode = mode;
+    mCb = cb;
+    mOperationId = operationId;
+    mHat = hat;
+}
+
+void FakeFingerprintEngine::fingerDownAction() {
+    bool isTerminal = false;
+    LOG(INFO) << __func__;
+    switch (mWorkMode) {
+        case WorkMode::kAuthenticate:
+            isTerminal = onAuthenticateFingerDown(mCb, mOperationId, mCancel);
+            break;
+        case WorkMode::kEnroll:
+            isTerminal = onEnrollFingerDown(mCb, mHat, mCancel);
+            break;
+        case WorkMode::kDetectInteract:
+            isTerminal = onDetectInteractFingerDown(mCb, mCancel);
+            break;
+        default:
+            LOG(WARNING) << "unexpected mode: on fingerDownAction(), " << (int)mWorkMode;
+            break;
+    }
+
+    if (isTerminal) {
+        mWorkMode = WorkMode::kIdle;
+    }
+}
+
+bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb,
+                                               const keymaster::HardwareAuthToken&,
+                                               const std::future<void>& cancel) {
+    BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
+
     // Force error-out
     auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
     if (err != 0) {
         LOG(ERROR) << "Fail: operation_enroll_error";
         auto ec = convertError(err);
         cb->onError(ec.first, ec.second);
-        return;
+        return true;
     }
 
     // Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
@@ -72,7 +139,7 @@
     if (parts.size() != 3) {
         LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
         cb->onError(Error::VENDOR, 0 /* vendorError */);
-        return;
+        return true;
     }
     auto enrollmentId = std::stoi(parts[0]);
     auto progress = parseEnrollmentCapture(parts[1]);
@@ -88,7 +155,7 @@
             if (shouldCancel(cancel)) {
                 LOG(ERROR) << "Fail: cancel";
                 cb->onError(Error::CANCELED, 0 /* vendorCode */);
-                return;
+                return true;
             }
             auto ac = convertAcquiredInfo(acquired[j]);
             cb->onAcquired(ac.first, ac.second);
@@ -114,10 +181,13 @@
             cb->onEnrollmentProgress(enrollmentId, left);
         }
     }
+
+    return true;
 }
 
-void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */,
-                                             const std::future<void>& cancel) {
+bool FakeFingerprintEngine::onAuthenticateFingerDown(ISessionCallback* cb,
+                                                     int64_t /* operationId */,
+                                                     const std::future<void>& cancel) {
     BEGIN_OP(getLatency(FingerprintHalProperties::operation_authenticate_latency()));
 
     int64_t now = Util::getSystemNanoTime();
@@ -129,19 +199,12 @@
     if (N == 0) {
         LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
-        return;
+        return true;
     }
 
     // got lockout?
-    FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
-    if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
-        LOG(ERROR) << "Fail: lockout permanent";
-        cb->onLockoutPermanent();
-        return;
-    } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
-        int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
-        LOG(ERROR) << "Fail: lockout timed " << timeLeft;
-        cb->onLockoutTimed(timeLeft);
+    if (checkSensorLockout(cb)) {
+        return FakeLockoutTracker::LockoutMode::kPermanent == mLockoutTracker.getMode();
     }
 
     int i = 0;
@@ -150,7 +213,7 @@
             LOG(ERROR) << "Fail: operation_authenticate_fails";
             mLockoutTracker.addFailedAttempt();
             cb->onAuthenticationFailed();
-            return;
+            return false;
         }
 
         auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0);
@@ -158,20 +221,21 @@
             LOG(ERROR) << "Fail: operation_authenticate_error";
             auto ec = convertError(err);
             cb->onError(ec.first, ec.second);
-            return;
+            return true; /* simply terminating current operation for any user inserted error,
+                            revisit if tests need*/
         }
 
         if (FingerprintHalProperties::lockout().value_or(false)) {
             LOG(ERROR) << "Fail: lockout";
             cb->onLockoutPermanent();
             cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
-            return;
+            return true;
         }
 
         if (shouldCancel(cancel)) {
             LOG(ERROR) << "Fail: cancel";
             cb->onError(Error::CANCELED, 0 /* vendorCode */);
-            return;
+            return true;
         }
 
         if (i < N) {
@@ -189,29 +253,23 @@
     if (id > 0 && isEnrolled) {
         cb->onAuthenticationSucceeded(id, {} /* hat */);
         mLockoutTracker.reset();
-        return;
+        return true;
     } else {
         LOG(ERROR) << "Fail: fingerprint not enrolled";
         cb->onAuthenticationFailed();
         mLockoutTracker.addFailedAttempt();
+        checkSensorLockout(cb);
+        return false;
     }
 }
 
-void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
-                                                  const std::future<void>& cancel) {
+bool FakeFingerprintEngine::onDetectInteractFingerDown(ISessionCallback* cb,
+                                                       const std::future<void>& cancel) {
     BEGIN_OP(getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
 
     int64_t duration =
             FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
 
-    auto detectInteractionSupported =
-            FingerprintHalProperties::detect_interaction().value_or(false);
-    if (!detectInteractionSupported) {
-        LOG(ERROR) << "Detect interaction is not supported";
-        cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
-        return;
-    }
-
     auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
     auto acquiredInfos = parseIntSequence(acquired);
     int N = acquiredInfos.size();
@@ -220,7 +278,7 @@
     if (N == 0) {
         LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired;
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
-        return;
+        return true;
     }
 
     int i = 0;
@@ -230,13 +288,13 @@
             LOG(ERROR) << "Fail: operation_detect_interaction_error";
             auto ec = convertError(err);
             cb->onError(ec.first, ec.second);
-            return;
+            return true;
         }
 
         if (shouldCancel(cancel)) {
             LOG(ERROR) << "Fail: cancel";
             cb->onError(Error::CANCELED, 0 /* vendorCode */);
-            return;
+            return true;
         }
 
         if (i < N) {
@@ -253,21 +311,18 @@
     if (id <= 0 || !isEnrolled) {
         LOG(ERROR) << "Fail: not enrolled";
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
-        return;
+        return true;
     }
 
     cb->onInteractionDetected();
+
+    return true;
 }
 
 void FakeFingerprintEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
     BEGIN_OP(0);
 
     std::vector<int32_t> ids;
-    // There are some enrollment sync issue with framework, which results in
-    //  a single template removal during the very firt sync command after reboot.
-    //  This is a workaround for now. TODO(b/243129174)
-    ids.push_back(-1);
-
     for (auto& enrollment : FingerprintHalProperties::enrollments()) {
         auto id = enrollment.value_or(0);
         if (id > 0) {
@@ -330,6 +385,11 @@
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
         return;
     }
+    clearLockout(cb);
+    isLockoutTimerAborted = true;
+}
+
+void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
     FingerprintHalProperties::lockout(false);
     cb->onLockoutCleared();
     mLockoutTracker.reset();
@@ -339,6 +399,7 @@
                                                             int32_t /*y*/, float /*minor*/,
                                                             float /*major*/) {
     BEGIN_OP(0);
+    fingerDownAction();
     return ndk::ScopedAStatus::ok();
 }
 
@@ -369,7 +430,8 @@
         if (dim.size() >= 4) {
             d = dim[3];
         }
-        if (isValidStr) out = {0, x, y, r, d};
+        if (isValidStr)
+            out = {.sensorLocationX = x, .sensorLocationY = y, .sensorRadius = r, .display = d};
 
         return isValidStr;
     }
@@ -385,8 +447,7 @@
 }
 
 SensorLocation FakeFingerprintEngine::defaultSensorLocation() {
-    return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */,
-            0 /* sensorRadius */, "" /* display */};
+    return SensorLocation();
 }
 
 std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
@@ -513,4 +574,39 @@
     return dist(mRandom);
 }
 
+bool FakeFingerprintEngine::checkSensorLockout(ISessionCallback* cb) {
+    FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
+    if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
+        LOG(ERROR) << "Fail: lockout permanent";
+        cb->onLockoutPermanent();
+        isLockoutTimerAborted = true;
+        return true;
+    } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
+        int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
+        LOG(ERROR) << "Fail: lockout timed " << timeLeft;
+        cb->onLockoutTimed(timeLeft);
+        if (isLockoutTimerSupported && !isLockoutTimerStarted) startLockoutTimer(timeLeft, cb);
+        return true;
+    }
+    return false;
+}
+
+void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
+    BEGIN_OP(0);
+    std::function<void(ISessionCallback*)> action =
+            std::bind(&FakeFingerprintEngine::lockoutTimerExpired, this, std::placeholders::_1);
+    std::thread([timeout, action, cb]() {
+        std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+        action(cb);
+    }).detach();
+
+    isLockoutTimerStarted = true;
+}
+void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
+    if (!isLockoutTimerAborted) {
+        clearLockout(cb);
+    }
+    isLockoutTimerStarted = false;
+    isLockoutTimerAborted = false;
+}
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
index 9f736e7..a78cdcd 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
@@ -27,11 +27,13 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
-SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() {
-    SensorLocation location;
+FakeFingerprintEngineSide::FakeFingerprintEngineSide() : FakeFingerprintEngine() {
+    isLockoutTimerSupported = true;
+}
 
-    return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */,
-            defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */,
-            "" /* display */};
+SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() {
+    return SensorLocation{.sensorLocationX = defaultSensorLocationX,
+                          .sensorLocationY = defaultSensorLocationY,
+                          .sensorRadius = defaultSensorRadius};
 }
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
index 3cdfc70..68b0f0d 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
@@ -31,12 +31,12 @@
 namespace aidl::android::hardware::biometrics::fingerprint {
 
 FakeFingerprintEngineUdfps::FakeFingerprintEngineUdfps()
-    : FakeFingerprintEngine(), mWorkMode(WorkMode::kIdle), mPointerDownTime(0), mUiReadyTime(0) {}
+    : FakeFingerprintEngine(), mPointerDownTime(0), mUiReadyTime(0) {}
 
 SensorLocation FakeFingerprintEngineUdfps::defaultSensorLocation() {
-    return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */,
-            defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */,
-            "" /* display */};
+    return SensorLocation{.sensorLocationX = defaultSensorLocationX,
+                          .sensorLocationY = defaultSensorLocationY,
+                          .sensorRadius = defaultSensorRadius};
 }
 
 ndk::ScopedAStatus FakeFingerprintEngineUdfps::onPointerDownImpl(int32_t /*pointerId*/,
@@ -70,68 +70,17 @@
 }
 
 void FakeFingerprintEngineUdfps::fingerDownAction() {
-    switch (mWorkMode) {
-        case WorkMode::kAuthenticate:
-            onAuthenticateFingerDown();
-            break;
-        case WorkMode::kEnroll:
-            onEnrollFingerDown();
-            break;
-        case WorkMode::kDetectInteract:
-            onDetectInteractFingerDown();
-            break;
-        default:
-            LOG(WARNING) << "unexpected call: onUiReady()";
-            break;
-    }
-
+    FakeFingerprintEngine::fingerDownAction();
     mUiReadyTime = 0;
     mPointerDownTime = 0;
 }
 
-void FakeFingerprintEngineUdfps::onAuthenticateFingerDown() {
-    FakeFingerprintEngine::authenticateImpl(mCb, mOperationId, mCancelVec[0]);
-}
-
-void FakeFingerprintEngineUdfps::onEnrollFingerDown() {
-    // Any use case to emulate display touch for each capture during enrollment?
-    FakeFingerprintEngine::enrollImpl(mCb, mHat, mCancelVec[0]);
-}
-
-void FakeFingerprintEngineUdfps::onDetectInteractFingerDown() {
-    FakeFingerprintEngine::detectInteractionImpl(mCb, mCancelVec[0]);
-}
-
-void FakeFingerprintEngineUdfps::enrollImpl(ISessionCallback* cb,
-                                            const keymaster::HardwareAuthToken& hat,
-                                            const std::future<void>& cancel) {
-    updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
-}
-
-void FakeFingerprintEngineUdfps::authenticateImpl(ISessionCallback* cb, int64_t operationId,
-                                                  const std::future<void>& cancel) {
-    updateContext(WorkMode::kAuthenticate, cb, const_cast<std::future<void>&>(cancel), operationId,
-                  keymaster::HardwareAuthToken());
-}
-
-void FakeFingerprintEngineUdfps::detectInteractionImpl(ISessionCallback* cb,
-                                                       const std::future<void>& cancel) {
-    updateContext(WorkMode::kDetectInteract, cb, const_cast<std::future<void>&>(cancel), 0,
-                  keymaster::HardwareAuthToken());
-}
-
 void FakeFingerprintEngineUdfps::updateContext(WorkMode mode, ISessionCallback* cb,
                                                std::future<void>& cancel, int64_t operationId,
                                                const keymaster::HardwareAuthToken& hat) {
+    FakeFingerprintEngine::updateContext(mode, cb, cancel, operationId, hat);
     mPointerDownTime = 0;
     mUiReadyTime = 0;
-    mCancelVec.clear();
-
-    mCancelVec.push_back(std::move(cancel));
-    mWorkMode = mode;
-    mCb = cb;
-    mOperationId = operationId;
-    mHat = hat;
 }
 
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
index 5996406..b0163ee 100644
--- a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
@@ -67,9 +67,13 @@
     int64_t res = 0;
 
     if (mLockoutTimedStart > 0) {
+        int32_t lockoutTimedDuration =
+                FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100);
         auto now = Util::getSystemNanoTime();
-        auto left = now - mLockoutTimedStart;
-        res = (left > 0) ? (left / 1000000LL) : 0;
+        auto elapsed = (now - mLockoutTimedStart) / 1000000LL;
+        res = lockoutTimedDuration - elapsed;
+        LOG(INFO) << "xxxxxx: elapsed=" << elapsed << " now = " << now
+                  << " mLockoutTimedStart=" << mLockoutTimedStart << " res=" << res;
     }
 
     return res;
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index f00a49d..79b563e 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -17,6 +17,7 @@
 #include "Fingerprint.h"
 #include "Session.h"
 
+#include <android-base/properties.h>
 #include <fingerprint.sysprop.h>
 
 #include <android-base/file.h>
@@ -59,6 +60,7 @@
                              << sensorTypeProp;
     }
     LOG(INFO) << "sensorTypeProp:" << sensorTypeProp;
+    LOG(INFO) << "ro.product.name=" << ::android::base::GetProperty("ro.product.name", "UNKNOWN");
 }
 
 ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
@@ -105,16 +107,16 @@
 
     mSession->linkToDeath(cb->asBinder().get());
 
-    LOG(INFO) << "createSession: sensorId:" << sensorId << " userId:" << userId;
+    LOG(INFO) << __func__ << ": sensorId:" << sensorId << " userId:" << userId;
     return ndk::ScopedAStatus::ok();
 }
 
 binder_status_t Fingerprint::dump(int fd, const char** /*args*/, uint32_t numArgs) {
     if (fd < 0) {
-        LOG(ERROR) << "Fingerprint::dump fd invalid: " << fd;
+        LOG(ERROR) << __func__ << "fd invalid: " << fd;
         return STATUS_BAD_VALUE;
     } else {
-        LOG(INFO) << "Fingerprint::dump fd:" << fd << "numArgs:" << numArgs;
+        LOG(INFO) << __func__ << " fd:" << fd << "numArgs:" << numArgs;
     }
 
     dprintf(fd, "----- FingerprintVirtualHal::dump -----\n");
@@ -131,11 +133,11 @@
 
 binder_status_t Fingerprint::handleShellCommand(int in, int out, int err, const char** args,
                                                 uint32_t numArgs) {
-    LOG(INFO) << "Fingerprint::handleShellCommand in:" << in << " out:" << out << " err:" << err
+    LOG(INFO) << __func__ << " in:" << in << " out:" << out << " err:" << err
               << " numArgs:" << numArgs;
 
     if (numArgs == 0) {
-        LOG(INFO) << "Fingerprint::handleShellCommand: available commands";
+        LOG(INFO) << __func__ << ": available commands";
         onHelp(out);
         return STATUS_OK;
     }
@@ -163,7 +165,7 @@
 }
 
 void Fingerprint::resetConfigToDefault() {
-    LOG(INFO) << "reset virtual HAL configuration to default";
+    LOG(INFO) << __func__ << ": reset virtual HAL configuration to default";
 #define RESET_CONFIG_O(__NAME__) \
     if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt)
 #define RESET_CONFIG_V(__NAME__)                       \
diff --git a/biometrics/fingerprint/aidl/default/README.md b/biometrics/fingerprint/aidl/default/README.md
index 49b6c9d..823cd18 100644
--- a/biometrics/fingerprint/aidl/default/README.md
+++ b/biometrics/fingerprint/aidl/default/README.md
@@ -14,6 +14,12 @@
 PRODUCT_PACKAGES_DEBUG += android.hardware.biometrics.fingerprint-service.example
 ```
 
+or add the following to include it as an apex:
+
+```
+PRODUCT_PACKAGES_DEBUG += com.android.hardware.biometrics.fingerprint.virtual
+```
+
 The virtual HAL will be ignored if a real HAL is also installed on the target
 device. Set the `biometric_virtual_enabled` settings and reboot the device to
 switch to the virtual HAL. Unset it and reboot again to switch back.
diff --git a/biometrics/fingerprint/aidl/default/apex/Android.bp b/biometrics/fingerprint/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..ad36ae2
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/Android.bp
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+    name: "com.android.hardware.biometrics.fingerprint.virtual.key",
+    public_key: "com.android.hardware.biometrics.fingerprint.virtual.avbpubkey",
+    private_key: "com.android.hardware.biometrics.fingerprint.virtual.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.biometrics.fingerprint.virtual.certificate",
+    certificate: "com.android.hardware.biometrics.fingerprint.virtual",
+}
+
+apex {
+    name: "com.android.hardware.biometrics.fingerprint.virtual",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.biometrics.fingerprint.virtual.key",
+    certificate: ":com.android.hardware.biometrics.fingerprint.virtual.certificate",
+    updatable: false,
+    use_vndk_as_stable: true,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.biometrics.fingerprint-service.example",
+    ],
+    prebuilts: [
+        // init_rc
+        "fingerprint-example-apex.rc",
+        // vintf_fragment
+        "fingerprint-example-apex.xml",
+    ],
+
+    overrides: [
+        "android.hardware.biometrics.fingerprint-service.example",
+    ],
+}
+
+genrule {
+    name: "gen-fingerprint-example-apex.rc",
+    srcs: [":fingerprint-example.rc"],
+    out: ["fingerprint-example-apex.rc"],
+    cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.fingerprint.virtual/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "fingerprint-example-apex.rc",
+    src: ":gen-fingerprint-example-apex.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "fingerprint-example-apex.xml",
+    src: ":fingerprint-example.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
new file mode 100644
index 0000000..9f2334a
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
new file mode 100644
index 0000000..14eb288
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDwo6CxzAwmX46C
+N1j8zr0qf6uy1rDkG5r1s4faDNX/ThYpd69DWbVGf22yFO3KY3B+TmqKU+B0SiqY
+MHQjXc+UcTa0BKtPtQNSYFLK13/1rW69QrlLtcGyAp/CwksXYuuJ8Uzs28nQ5A+z
+fh6Vfsla9tUWDeWtN4oehmOwZ0ZKPBAKKocB5W+YJoIkdVnzkiOnWawk8Wn7a1N0
+jN5wFDO/99De+rTzYgKvV3Xb68H2UrIei4TW4wEpMZuDRUfbPlrSkJpdf+hYKKLb
+AkotUrwA1znYR3U9t0GIHwZ5sp+OQTCkTfJMg2c+Bpmkp3TAL24LdvkYVA2LZERB
+p7xNeACH210Bb8QOAEaiLyVWuL6iapXI67TOkZ5yk7heb5zCxRcpOMA4FQ0hWYoX
+AWstem9ADWvZgKe0BFGx7lhp5YmdBCzdNv0za3Va9EATJ0wgy4qMpZu3yjDPE9bq
+gdb3BQL3kiDHdfR/LF9bCIP9QEHg+1mWOZDO1x8lXCuQrgp+gnh9bbfX5g6lA8IQ
+dTfozjLQC3mVbl0P7/PIf9rnHjcqUh3/1RJH51tkgqBO8xn7D6AIOv665hI+O319
+PU4j26vLSfEu624IjEDK/gcgacuoYl3H3LMI5a2JIWFLOtpKRo9P2qFF702o8B97
+5slGDYnxpAAnEQQADuRYgDalDlFDNQIDAQABAoICABe7k4wleydHslbeXYzlWNu5
+prXnHaAJpvFHiQT00iAxU9c4IhVq4gl3ZNq03LTitMQIONK2rgLaE7RZxwJ77I6P
+0dzUPw8H47F6pX+y3EBfH/ZTf9HbNaS4RIhhQCWo0GEU5sjPbmqHK5NAw4Rr8jDh
++icILNg2C42yJF/P96s3nD9cbV8/ARAI8DnnRv1SMuj825DzLEgrEBqFECUOoQH0
+T2nGYRVF28zuO8X6TPFdu4puqSXGUqV86oD6UrlpP2zX7Rl+lWwoadNeuPEaYUdV
+8rMFbScujSx/HtTezISroj/6HgT0yrhfz0RhbY7MvrYrwCppk8JlG6Q8BkK/rJGI
+lGw7nKIp43Tl8T2Rzw0I1dPwxCLMJuVErUclznN7lq25akG5XRwBAUQQE6nHO3GL
+jh7eFW7rEcpUBEKYTK1ZA8QrWGUW3WittDqZ6VQU/ZudVoTcgbW3YpUYq5z76O4u
+B6tqlmNtQfIi3LBh8CD19SIjV6KKVa0s++ArQEu/DWzmHWh/STZZk4b1DSdFYqm0
+zgylOVUfpcG10OxPOdvMEsA0VoXxxwl6Hx3DSEX6VxOQvBSkwhu+gw8u2keOsIYZ
+Ha2OxtG5FiEQqSa8YNN/0NDdOp1eEyqvdvT7o51cqHHPvlyhk7XL0AguErCtGggn
+TZ3rsUChlauG9GbJ4nOBAoIBAQD+ceJpOkMuw04dhIY5of3CcTTKGWdt2/9SP9PU
+ZORC6ywBhRORQBhyVZIERmxfJUGsmePHeIEQ5L8IniUDRTCKrL+J2bR8NdYZfvCJ
+9cYD2gjXmikFabKn6mkQz7JXjSr3Vamx2ueKuYqfo72aHVvhFv6Hi/ulbUPPZ15c
+gVo0iU5GRt/1XNyTksSiSKRyxXJYWqg5GD2JQ92Zbo5a5LhulC7wFF39jyfTe7K2
+mfrCI7dr+A0WtiTpbRH9EIU8CseIBgIEDTgMAxbBdUZpF8pecIAy0MLFefLA+8CK
+RN+8AI+HRHybjvuonOAfeEtQyyknzycxh20dyrd3FvBj40NBAoIBAQDyHCRuNwXA
+twETiysx1XStaoODLQkPxSqdFIBD+tfVR+E/3blVXkdrFfrTcr8NGdcgsJgQgYWr
+h9OENizcHg75gX6wdo3qYGQdZZxws/dQbNylObFYNkyFQrD1vkQzjZl5O4DaRJC7
+6YbJrrXZ44dgZoMo/M8nyNU5yaLvoOf4GV4bSiEfsx/MxWK7x6rCcpw9jpm+yQlB
+9NblSgWzfg0hmcRBn6haC3q45walBYGTVJfzTOMgn5bUmMxKqKlCXvp20BPLdclQ
+5Y14OqkqhnFeHpBSJ7iVI9BBy2nAsyk37NvYVg7mN8fGiWbCqurIrbPRGSCdohGr
+wY7zOVd1hmb1AoIBAGPhVJ0177VlmT5hDUeGXVR8l9pVipJHb7xbrc2MJUZXhpi6
+Imo8HNyU1pKzCkt3Foaoig99MDzvbkX1vlXATUPCeBWmzgCMKZUsjUO6pJZSenIX
+485qJWVg0Ql2Xm2bzqf0in50jbuZBd+QqRbcO3rqSdPvkULo11uNGi95320MERvp
+KnTolPWhAWsq1NLwyuf//lUbPNyrNUvLaDop2nQd2ycG97ZXAa00u3yOiS64UoIh
+hxHJQkgXNp5+Y66kFJtCsHvirIOams4qOQ979UaJJunLpQlby30R1gzw6FqmZbEV
+o0x1HjicDCaOVBJNDcTAvoPkw2KUdtxattafGYECggEBAPICm4/oREHdLKBCjszj
+mBv4yrkG/XXcGrql0YkiZzj0/v3+PtJMyYsLj4xpuPv5hodQvtBRCDLsNMyF8tWc
+3k8d2GvANh/AdpLEDVrDKkYka3Jldxa8QEU84vLiW/5EXtNGXYjQ3PRZfLiBgZnp
+zFraXeVMwC3+nNWE7vAloXrosJ8KvI2ZWgIwlH8sGU8BjZgiwSBqiGx7t4u/MG+5
+Yprhv8HxPDG2I9hMZuHx3RJOjw1PIAJuRDEDA8LlUTvdAPRfDkpk1PWeYIl76blu
+Zkg0uQLGXcYG5JfAI1fSPzN9+kwHyiDqRTH6CtQwUTyEFajAO1AWvx82/hO2j+wU
+izkCggEANyPfsBjEUIZjwBuaHajm/tkcQAo3F4EgIkb1XR/EnfaaJp4I9S6hJ0vv
+5/fQtASn+JHjuIRk5l7g9N7lU+W+SiPvSxm1zZv8zLkqJpbKpMh7VIxT9joZ3E3/
+rzRLL60zYJ42hdulSFLoO1qCMErifBiTIwIZu7p6qKRH4+vqappb9QTPPlyAFFT6
+3UJfs49HGqd6gTyN7TSNxaya+ZBaLgSXhmExY/OtZazQn/iJl/dYpyYvmJdzNpd+
+XELU0IUcKivJaueCqK8NfEqfHz28GHdAkwHd0CzGnciF4tn9K2Sg8+X9jISk/Usx
+qHAY4JU3ldxQzDUZCz5VCz372pgXkQ==
+-----END PRIVATE KEY-----
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8 b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
new file mode 100644
index 0000000..ab59820
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
new file mode 100644
index 0000000..6d10157
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/MCFFuIt0T1K9U92QfzZI3RpCyRp1ruMA0GCSqGSIb3DQEBCwUAMIHA
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTE8MDoGA1UEAwwzY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5maW5nZXJwcmludC52aXJ0dWFs
+MCAXDTIzMDUxMDA3MDkwMloYDzQ3NjEwNDA1MDcwOTAyWjCBwDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx
+EDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0B
+CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xPDA6BgNVBAMMM2NvbS5hbmRyb2lkLmhh
+cmR3YXJlLmJpb21ldHJpY3MuZmluZ2VycHJpbnQudmlydHVhbDCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAMKXBcAw2Cs68KUMt5Hw2LVwkgEDiwqaXkG9
+V0SBK9y/q+6JCoxs9+4NsDPAEzHB+UHpqJ2i07VW1YV9F+2V93KCy/0fUjXIWmu8
+P0ixb+t8wlHZM2zYXQe9PELUZ/ZlYjAxkVKJjDmsCM8yzpRk+g3KKswlYwzyBoat
+qukrtvAaNKlRGJmjeStEo2o4qgQQUq96NAvSt3d6PsrNdFbXxqX61JT1dT8Kgxhk
++oSAkV2/C2knQp/8ME1oJrK/D+glynXVqVkvYYplxp+GCIZUs/DOJcHyb+ZrNLJP
+f2zr4yDoB2pnV3G9VcjbdznWc661Wg+B2yZEvLVbOMiqaMRlpHzNczghowCy3xoq
+42IUmp3HLak0DUmrrUZDnJAAT/KEZxh/PwLeAcmUrQCbUiG5lN/njuZ5LjJ8gdcg
+v0RDPSIIszamrf2l+xlaI34iXS7xHf3OLTbgst2L7LhW5qmLsB1SZzAYGIUYnRWZ
+aqzaFIAWt28S0yhpOt+qS7b1l+fvMb09jiKfxzkYQh2bB0HrpbTl2x390q2GW6yE
+jmraC+nTiAVDCUnDjOVji7nXDloSmK+MDD/DaDQ47PoYE3hBqc0fsRr2aIlvMOvb
+m+4VhO85gCuJAK02XuixLPo6ZqBAEFNwQ4NDcuOHuODaaJ/amTxQBXRpNXUSnhXy
+ejpwspHrAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAGl3KGKMAWpefnRSQWs0n8kD
+eKYbzbe6mG0O5lqx5FKpJZpIki4RH1Yh5ZDR/NIeF2RNhlb/dqo99TKbCEGAoMB9
+R7EXDhyMcEXr5ATCA6iurhMKgkcLfOz6HkTI6k3wlPNuvx4iZGHD2KEvZiZGmae1
+dnK9iVtNs6ccyC0+V3y3Yt1fvjzp9SWcPpBXiO5QNf0sHxtzc32xXsBH0aLwLjDZ
+BCytwfEvq2S25v0r9m0fKquDBoFnk68cqClpNQZ9Ky0k8fGgOiQ5/jnVmgPmTheG
+mBcdPeUrhxGNs1vax/i/ysT4AVmDzIVW0uXVouhVeMQzykuy1+Ywa/Rn0jLxeNF2
+X3ooOE+EF8u9Pxf8ILRnfqok3VRuYLH6neNknTSKTx1aQAh9XbBpTUa/eCq3LDCP
+L6hSXYWjk9e5txbn0cNw9WuKMUg+Z9Qms3aVRFcvBxZQySEvf8FhgSrQbqbCbzhf
+dI0/ouW5w9iHUOh/FDvfETeZCeeTS+EOvGOqknzO8Y7PiChlgFsoMvC1GpHZ1ADy
+3xKSh15G92JCiv89CK2VvM8QDFh8ErQmSLjhMl700CLYis+AAZhCKOhAo573zj2u
+dZf29S+o3SEBhsl5snVGJW13Bu7BjxQtscCwKOv0g1cCkrqgcm2bMuNhpTK7rhMP
+i4hGSvbdGC27BtXbsiVX
+-----END CERTIFICATE-----
diff --git a/biometrics/fingerprint/aidl/default/apex/file_contexts b/biometrics/fingerprint/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..1c189fc
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.biometrics\.fingerprint-service\.example u:object_r:hal_fingerprint_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/fingerprint/aidl/default/apex/manifest.json b/biometrics/fingerprint/aidl/default/apex/manifest.json
new file mode 100644
index 0000000..bbd2c69
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.biometrics.fingerprint.virtual",
+    "version": 1
+}
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 1279cd9..2450115 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -38,7 +38,7 @@
 // A fake engine that is backed by system properties instead of hardware.
 class FakeFingerprintEngine {
   public:
-    FakeFingerprintEngine() : mRandom(std::mt19937::default_seed) {}
+    FakeFingerprintEngine();
     virtual ~FakeFingerprintEngine() {}
 
     void generateChallengeImpl(ISessionCallback* cb);
@@ -66,6 +66,8 @@
 
     virtual SensorLocation defaultSensorLocation();
 
+    virtual void fingerDownAction();
+
     std::vector<int32_t> parseIntSequence(const std::string& str, const std::string& sep = ",");
 
     std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str);
@@ -74,15 +76,35 @@
 
     std::mt19937 mRandom;
 
+    enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract };
+
+    WorkMode getWorkMode() { return mWorkMode; }
+
     virtual std::string toString() const {
         std::ostringstream os;
         os << "----- FakeFingerprintEngine:: -----" << std::endl;
+        os << "mWorkMode:" << (int)mWorkMode;
         os << "acquiredVendorInfoBase:" << FINGERPRINT_ACQUIRED_VENDOR_BASE;
         os << ", errorVendorBase:" << FINGERPRINT_ERROR_VENDOR_BASE << std::endl;
         os << mLockoutTracker.toString();
         return os.str();
     }
 
+  protected:
+    virtual void updateContext(WorkMode mode, ISessionCallback* cb, std::future<void>& cancel,
+                               int64_t operationId, const keymaster::HardwareAuthToken& hat);
+
+    bool onEnrollFingerDown(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
+                            const std::future<void>& cancel);
+    bool onAuthenticateFingerDown(ISessionCallback* cb, int64_t, const std::future<void>& cancel);
+    bool onDetectInteractFingerDown(ISessionCallback* cb, const std::future<void>& cancel);
+
+    WorkMode mWorkMode;
+    ISessionCallback* mCb;
+    keymaster::HardwareAuthToken mHat;
+    std::future<void> mCancel;
+    int64_t mOperationId;
+
   private:
     static constexpr int32_t FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
     static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000;
@@ -91,8 +113,21 @@
     bool parseEnrollmentCaptureSingle(const std::string& str,
                                       std::vector<std::vector<int32_t>>& res);
     int32_t getRandomInRange(int32_t bound1, int32_t bound2);
+    bool checkSensorLockout(ISessionCallback*);
+    void clearLockout(ISessionCallback* cb);
 
     FakeLockoutTracker mLockoutTracker;
+
+  protected:
+    // lockout timer
+    void lockoutTimerExpired(ISessionCallback* cb);
+    bool isLockoutTimerSupported;
+    bool isLockoutTimerStarted;
+    bool isLockoutTimerAborted;
+
+  public:
+    void startLockoutTimer(int64_t timeout, ISessionCallback* cb);
+    bool getLockoutTimerStarted() { return isLockoutTimerStarted; }
 };
 
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
index c2fc005..67a3ebc 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
@@ -28,7 +28,7 @@
     static constexpr int32_t defaultSensorLocationY = 600;
     static constexpr int32_t defaultSensorRadius = 150;
 
-    FakeFingerprintEngineSide() : FakeFingerprintEngine() {}
+    FakeFingerprintEngineSide();
     ~FakeFingerprintEngineSide() {}
 
     virtual SensorLocation defaultSensorLocation() override;
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
index c5e93e7..2270eca 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
@@ -42,39 +42,20 @@
 
     SensorLocation defaultSensorLocation() override;
 
-    void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
-                    const std::future<void>& cancel);
-    void authenticateImpl(ISessionCallback* cb, int64_t operationId,
-                          const std::future<void>& cancel);
-    void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
-
-    enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract };
-
-    WorkMode getWorkMode() { return mWorkMode; }
+    void updateContext(WorkMode mode, ISessionCallback* cb, std::future<void>& cancel,
+                       int64_t operationId, const keymaster::HardwareAuthToken& hat);
+    void fingerDownAction();
 
     std::string toString() const {
         std::ostringstream os;
         os << FakeFingerprintEngine::toString();
         os << "----- FakeFingerprintEngineUdfps -----" << std::endl;
-        os << "mWorkMode:" << (int)mWorkMode;
         os << ", mUiReadyTime:" << mUiReadyTime;
         os << ", mPointerDownTime:" << mPointerDownTime << std::endl;
         return os.str();
     }
 
   private:
-    void onAuthenticateFingerDown();
-    void onEnrollFingerDown();
-    void onDetectInteractFingerDown();
-    void fingerDownAction();
-    void updateContext(WorkMode mode, ISessionCallback* cb, std::future<void>& cancel,
-                       int64_t operationId, const keymaster::HardwareAuthToken& hat);
-
-    WorkMode mWorkMode;
-    ISessionCallback* mCb;
-    keymaster::HardwareAuthToken mHat;
-    std::vector<std::future<void>> mCancelVec;
-    int64_t mOperationId;
     int64_t mPointerDownTime;
     int64_t mUiReadyTime;
 };
diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
index fc4fb8d..2bd66d4 100644
--- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
@@ -43,6 +43,7 @@
   private:
     void resetConfigToDefault();
     void onHelp(int);
+    void onSimFingerDown();
 
     std::unique_ptr<FakeFingerprintEngine> mEngine;
     WorkerThread mWorker;
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index a200b39..fe405f4 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -93,9 +93,13 @@
         return ndk::ScopedAStatus::ok();
     };
     ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
+        mLockoutTimed = true;
         return ndk::ScopedAStatus::ok();
     }
-    ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onLockoutCleared() override {
+        mLockoutCleared = true;
+        return ndk::ScopedAStatus::ok();
+    }
     ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
 
     Error mError = Error::UNKNOWN;
@@ -110,6 +114,8 @@
     bool mAuthenticateFailed = false;
     bool mAuthenticatorIdInvalidated = false;
     bool mLockoutPermanent = false;
+    bool mLockoutTimed = false;
+    bool mLockoutCleared = false;
     int mInteractionDetectedCount = 0;
     int32_t mLastAcquiredInfo = -1;
     int32_t mLastAcquiredVendorCode = -1;
@@ -132,6 +138,8 @@
         FingerprintHalProperties::operation_enroll_latency({});
         FingerprintHalProperties::operation_authenticate_latency({});
         FingerprintHalProperties::operation_detect_interaction_latency({});
+        FingerprintHalProperties::operation_authenticate_fails(false);
+        FingerprintHalProperties::operation_detect_interaction_latency({});
     }
 
     FakeFingerprintEngine mEngine;
@@ -178,11 +186,14 @@
     FingerprintHalProperties::next_enrollment("4:0,0:true");
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kEnroll);
+    mEngine.fingerDownAction();
     ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
     ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
     ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
     ASSERT_EQ(4, mCallback->mLastEnrolled);
     ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle);
 }
 
 TEST_F(FakeFingerprintEngineTest, EnrollCancel) {
@@ -192,6 +203,7 @@
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mCancel.set_value();
     mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
     ASSERT_EQ(-1, mCallback->mLastEnrolled);
     ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
@@ -204,6 +216,7 @@
     FingerprintHalProperties::next_enrollment(next);
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError);
     ASSERT_EQ(-1, mCallback->mLastEnrolled);
     ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
@@ -216,6 +229,7 @@
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     int32_t prevCnt = mCallback->mLastAcquiredCount;
     mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
     ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
     ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
@@ -229,9 +243,12 @@
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(2);
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate);
+    mEngine.fingerDownAction();
     ASSERT_FALSE(mCallback->mAuthenticateFailed);
     ASSERT_EQ(2, mCallback->mLastAuthenticated);
     ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle);
 }
 
 TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) {
@@ -239,6 +256,7 @@
     FingerprintHalProperties::enrollment_hit(2);
     mCancel.set_value();
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
     ASSERT_EQ(-1, mCallback->mLastAuthenticated);
 }
@@ -247,6 +265,7 @@
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit({});
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_TRUE(mCallback->mAuthenticateFailed);
 }
 
@@ -254,7 +273,9 @@
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(3);
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_TRUE(mCallback->mAuthenticateFailed);
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate);
 }
 
 TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
@@ -262,6 +283,7 @@
     FingerprintHalProperties::enrollment_hit(2);
     FingerprintHalProperties::lockout(true);
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_TRUE(mCallback->mLockoutPermanent);
     ASSERT_NE(mCallback->mError, Error::UNKNOWN);
 }
@@ -269,6 +291,7 @@
 TEST_F(FakeFingerprintEngineTest, AuthenticateError8) {
     FingerprintHalProperties::operation_authenticate_error(8);
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(mCallback->mError, (Error)8);
     ASSERT_EQ(mCallback->mErrorVendorCode, 0);
 }
@@ -276,10 +299,19 @@
 TEST_F(FakeFingerprintEngineTest, AuthenticateError9) {
     FingerprintHalProperties::operation_authenticate_error(1009);
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(mCallback->mError, (Error)7);
     ASSERT_EQ(mCallback->mErrorVendorCode, 9);
 }
 
+TEST_F(FakeFingerprintEngineTest, AuthenticateFails) {
+    FingerprintHalProperties::operation_authenticate_fails(true);
+    mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
+    ASSERT_TRUE(mCallback->mAuthenticateFailed);
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate);
+}
+
 TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) {
     FingerprintHalProperties::lockout(false);
     FingerprintHalProperties::enrollments({1, 2});
@@ -287,6 +319,7 @@
     FingerprintHalProperties::operation_authenticate_acquired("4,1009");
     int32_t prevCount = mCallback->mLastAcquiredCount;
     mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_FALSE(mCallback->mAuthenticateFailed);
     ASSERT_EQ(2, mCallback->mLastAuthenticated);
     ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
@@ -300,8 +333,11 @@
     FingerprintHalProperties::enrollment_hit(2);
     FingerprintHalProperties::operation_detect_interaction_acquired("");
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kDetectInteract);
+    mEngine.fingerDownAction();
     ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
     ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
+    ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle);
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
@@ -310,6 +346,7 @@
     FingerprintHalProperties::enrollment_hit(2);
     mCancel.set_value();
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
 }
@@ -319,6 +356,7 @@
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit({});
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
 }
 
@@ -326,6 +364,7 @@
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(25);
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
 }
 
@@ -333,6 +372,7 @@
     FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::operation_detect_interaction_error(8);
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
     ASSERT_EQ(mCallback->mError, (Error)8);
     ASSERT_EQ(mCallback->mErrorVendorCode, 0);
@@ -345,6 +385,7 @@
     FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
     int32_t prevCount = mCallback->mLastAcquiredCount;
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+    mEngine.fingerDownAction();
     ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
     ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
     ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
@@ -354,9 +395,7 @@
 TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) {
     FingerprintHalProperties::enrollments({2, 4, 8});
     mEngine.enumerateEnrollmentsImpl(mCallback.get());
-    ASSERT_EQ(
-            4,
-            mCallback->mLastEnrollmentEnumerated.size());  // Due to workaround. TODO (b/243129174)
+    ASSERT_EQ(3, mCallback->mLastEnrollmentEnumerated.size());
     for (auto id : FingerprintHalProperties::enrollments()) {
         ASSERT_TRUE(std::find(mCallback->mLastEnrollmentEnumerated.begin(),
                               mCallback->mLastEnrollmentEnumerated.end(),
@@ -464,9 +503,15 @@
                 FingerprintHalProperties::operation_detect_interaction_latency()));
     }
     ASSERT_TRUE(latencySet.size() > 95);
-    FingerprintHalProperties::operation_detect_interaction_latency({});
 }
 
+TEST_F(FakeFingerprintEngineTest, lockoutTimer) {
+    mEngine.startLockoutTimer(200, mCallback.get());
+    ASSERT_TRUE(mEngine.getLockoutTimerStarted());
+    std::this_thread::sleep_for(std::chrono::milliseconds(210));
+    ASSERT_FALSE(mEngine.getLockoutTimerStarted());
+    ASSERT_TRUE(mCallback->mLockoutCleared);
+}
 }  // namespace aidl::android::hardware::biometrics::fingerprint
 
 int main(int argc, char** argv) {
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
index 1b071ee..93c6f84 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -65,11 +65,11 @@
     ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
     // time left
     int N = 5;
-    int64_t prevTimeLeft = INT_MIN;
+    int64_t prevTimeLeft = INT_MAX;
     for (int i = 0; i < N; i++) {
         SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1);
         int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft();
-        ASSERT_TRUE(currTimeLeft > prevTimeLeft);
+        ASSERT_TRUE(currTimeLeft < prevTimeLeft);
         prevTimeLeft = currTimeLeft;
     }
     ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
diff --git a/bluetooth/1.0/default/bluetooth_address.cc b/bluetooth/1.0/default/bluetooth_address.cc
index 93a5469..df3e84a 100644
--- a/bluetooth/1.0/default/bluetooth_address.cc
+++ b/bluetooth/1.0/default/bluetooth_address.cc
@@ -67,7 +67,7 @@
       const uint8_t zero_bdaddr[kBytes] = {0, 0, 0, 0, 0, 0};
       if ((string_to_bytes(address, local_addr)) &&
           (memcmp(local_addr, zero_bdaddr, kBytes) != 0)) {
-        ALOGD("%s: Got Factory BDA %s", __func__, address);
+        ALOGD("%s: Got Factory BDA", __func__);
         return true;
       } else {
         ALOGE("%s: Got Invalid BDA '%s' from %s", __func__, address, property);
@@ -78,12 +78,14 @@
   // No BDADDR found in the file. Look for BDA in a factory property.
   if (property_get(FACTORY_BDADDR_PROPERTY, property, NULL) &&
       string_to_bytes(property, local_addr)) {
+    ALOGD("%s: Using FACTORY_BDADDR_PROPERTY", __func__);
     return true;
   }
 
   // No factory BDADDR found. Look for a previously stored BDA.
   if (property_get(PERSIST_BDADDR_PROPERTY, property, NULL) &&
       string_to_bytes(property, local_addr)) {
+    ALOGD("%s: Using PERSIST_BDADDR_PROPERTY", __func__);
     return true;
   }
 
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index 869c723..a2211f4 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -33,8 +33,7 @@
 
 class BluetoothDeathRecipient : public hidl_death_recipient {
  public:
-  BluetoothDeathRecipient(const sp<IBluetoothHci> hci)
-    : mHci(hci), has_died_(false) {}
+  BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
 
   virtual void serviceDied(
       uint64_t /*cookie*/,
@@ -52,7 +51,7 @@
 };
 
 BluetoothHci::BluetoothHci()
-    : death_recipient_(new BluetoothDeathRecipient(this)) {bt_enabled = 0;}
+    : death_recipient_(new BluetoothDeathRecipient(this)) {}
 
 Return<void> BluetoothHci::initialize(
     const ::android::sp<IBluetoothHciCallbacks>& cb) {
@@ -62,19 +61,8 @@
     return Void();
   }
 
-  if (bt_enabled == 1) {
-    ALOGE("initialize was called!");
-    return Void();
-  }
-  bt_enabled = 1;
   death_recipient_->setHasDied(false);
   cb->linkToDeath(death_recipient_, 0);
-  unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
-    if (death_recipient->getHasDied())
-      ALOGI("Skipping unlink call, service died.");
-    else
-      cb->unlinkToDeath(death_recipient);
-  };
 
   bool rc = VendorInterface::Initialize(
       [cb](bool status) {
@@ -124,12 +112,6 @@
 
 Return<void> BluetoothHci::close() {
   ALOGI("BluetoothHci::close()");
-
-  if (bt_enabled != 1) {
-    ALOGE("should initialize first!");
-    return Void();
-  }
-  bt_enabled = 0;
   unlink_cb_(death_recipient_);
   VendorInterface::Shutdown();
   return Void();
@@ -152,11 +134,6 @@
 
 void BluetoothHci::sendDataToController(const uint8_t type,
                                         const hidl_vec<uint8_t>& data) {
-  if (bt_enabled != 1) {
-    ALOGE("should initialize first!");
-    return;
-  }
-
   VendorInterface::get()->Send(type, data.data(), data.size());
 }
 
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index 5130c87..c966990 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -48,7 +48,6 @@
   void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
   ::android::sp<BluetoothDeathRecipient> death_recipient_;
   std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
-  int bt_enabled;
 };
 
 extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index c23d667..1d15dd6 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -36,8 +36,6 @@
     "BLUETOOTH_VENDOR_LIB_INTERFACE";
 
 static const int INVALID_FD = -1;
-std::mutex vendor_mutex_;
-std::mutex initcb_mutex_;
 
 namespace {
 
@@ -49,25 +47,13 @@
   uint16_t opcode;
 } internal_command;
 
-enum {
-  VENDOR_STATE_INIT = 1,
-  VENDOR_STATE_OPENING,	/* during opening */
-  VENDOR_STATE_OPENED,	/* open in fops_open */
-  VENDOR_STATE_CLOSING,	/* during closing */
-  VENDOR_STATE_CLOSED,	/* closed */
-
-  VENDOR_STATE_MSG_NUM
-} ;
-
-uint8_t vstate = VENDOR_STATE_INIT;
-
 // True when LPM is not enabled yet or wake is not asserted.
 bool lpm_wake_deasserted;
 uint32_t lpm_timeout_ms;
 bool recent_activity_flag;
 
 VendorInterface* g_vendor_interface = nullptr;
-static VendorInterface vendor_interface;
+std::mutex wakeup_mutex_;
 
 HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
   size_t packet_size = data.size() + sizeof(HC_BT_HDR);
@@ -181,8 +167,11 @@
     InitializeCompleteCallback initialize_complete_cb,
     PacketReadCallback event_cb, PacketReadCallback acl_cb,
     PacketReadCallback sco_cb, PacketReadCallback iso_cb) {
-  ALOGI("%s: VendorInterface::Initialize", __func__);
-  g_vendor_interface = &vendor_interface;
+  if (g_vendor_interface) {
+    ALOGE("%s: No previous Shutdown()?", __func__);
+    return false;
+  }
+  g_vendor_interface = new VendorInterface();
   return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
                                   sco_cb, iso_cb);
 }
@@ -190,8 +179,9 @@
 void VendorInterface::Shutdown() {
   LOG_ALWAYS_FATAL_IF(!g_vendor_interface, "%s: No Vendor interface!",
                       __func__);
-  ALOGI("%s: VendorInterface::Shutdown", __func__);
   g_vendor_interface->Close();
+  delete g_vendor_interface;
+  g_vendor_interface = nullptr;
 }
 
 VendorInterface* VendorInterface::get() { return g_vendor_interface; }
@@ -201,189 +191,144 @@
                            PacketReadCallback acl_cb,
                            PacketReadCallback sco_cb,
                            PacketReadCallback iso_cb) {
-  {
-    std::unique_lock<std::mutex> guard(vendor_mutex_);
-    if (vstate == VENDOR_STATE_OPENED) {
-      ALOGW("VendorInterface opened!");
-      return true;
-    }
+  initialize_complete_cb_ = initialize_complete_cb;
 
-    if ((vstate == VENDOR_STATE_CLOSING) ||
-        (vstate == VENDOR_STATE_OPENING)) {
-      ALOGW("VendorInterface open/close is on-going !");
-      return true;
-    }
+  // Initialize vendor interface
 
-    vstate = VENDOR_STATE_OPENING;
-    ALOGI("%s: VendorInterface::Open", __func__);
+  lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
+  if (!lib_handle_) {
+    ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
+          dlerror());
+    return false;
+  }
 
-    initialize_complete_cb_ = initialize_complete_cb;
-    // Initialize vendor interface
-
-    lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
-    if (!lib_handle_) {
-      ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
-            dlerror());
-      return false;
-    }
-
-    lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
-        dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
-    if (!lib_interface_) {
-      ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
-            VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
-      return false;
-    }
+  lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
+      dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
+  if (!lib_interface_) {
+    ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
+          VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
+    return false;
+  }
 
   // Get the local BD address
 
-    uint8_t local_bda[BluetoothAddress::kBytes] = {0, 0, 0, 0, 0, 0};
-    if (!BluetoothAddress::get_local_address(local_bda)) {
-      // BT driver will get BD address from NVRAM for MTK solution
-      ALOGW("%s: No pre-set Bluetooth Address!", __func__);
-    }
-    int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
-    if (status) {
-      ALOGE("%s unable to initialize vendor library: %d", __func__, status);
-      return false;
-    }
+  uint8_t local_bda[BluetoothAddress::kBytes];
+  if (!BluetoothAddress::get_local_address(local_bda)) {
+    LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__);
+  }
+  int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
+  if (status) {
+    ALOGE("%s unable to initialize vendor library: %d", __func__, status);
+    return false;
+  }
 
-    ALOGD("%s vendor library loaded", __func__);
+  ALOGD("%s vendor library loaded", __func__);
 
   // Power on the controller
 
-    int power_state = BT_VND_PWR_ON;
-    lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+  int power_state = BT_VND_PWR_ON;
+  lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
 
   // Get the UART socket(s)
 
-    int fd_list[CH_MAX] = {0};
-    int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
+  int fd_list[CH_MAX] = {0};
+  int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
 
-    if (fd_count < 1 || fd_count > CH_MAX - 1) {
-      ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
+  if (fd_count < 1 || fd_count > CH_MAX - 1) {
+    ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
+    return false;
+  }
+
+  for (int i = 0; i < fd_count; i++) {
+    if (fd_list[i] == INVALID_FD) {
+      ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
       return false;
     }
+  }
 
-    for (int i = 0; i < fd_count; i++) {
-      if (fd_list[i] == INVALID_FD) {
-        ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
-        return false;
-      }
-    }
+  event_cb_ = event_cb;
+  PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
+    HandleIncomingEvent(event);
+  };
 
-    event_cb_ = event_cb;
-    PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
-      HandleIncomingEvent(event);
-    };
-
-    if (fd_count == 1) {
-      hci::H4Protocol* h4_hci =
-          new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
-      fd_watcher_.WatchFdForNonBlockingReads(
-          fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
-      hci_ = h4_hci;
-    } else {
-      hci::MctProtocol* mct_hci =
-          new hci::MctProtocol(fd_list, intercept_events, acl_cb);
-      fd_watcher_.WatchFdForNonBlockingReads(
-          fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
-      fd_watcher_.WatchFdForNonBlockingReads(
-          fd_list[CH_ACL_IN],
-          [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
-      hci_ = mct_hci;
-    }
+  if (fd_count == 1) {
+    hci::H4Protocol* h4_hci =
+        new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
+    fd_watcher_.WatchFdForNonBlockingReads(
+        fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
+    hci_ = h4_hci;
+  } else {
+    hci::MctProtocol* mct_hci =
+        new hci::MctProtocol(fd_list, intercept_events, acl_cb);
+    fd_watcher_.WatchFdForNonBlockingReads(
+        fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
+    fd_watcher_.WatchFdForNonBlockingReads(
+        fd_list[CH_ACL_IN], [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
+    hci_ = mct_hci;
+  }
 
   // Initially, the power management is off.
-    lpm_wake_deasserted = true;
+  lpm_wake_deasserted = true;
 
   // Start configuring the firmware
-    firmware_startup_timer_ = new FirmwareStartupTimer();
-    lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
+  firmware_startup_timer_ = new FirmwareStartupTimer();
+  lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
 
-    vstate = VENDOR_STATE_OPENED;
-    ALOGI("%s: VendorInterface::Open done!!!", __func__);
-  }  // vendor_mutex_ done
   return true;
 }
 
 void VendorInterface::Close() {
   // These callbacks may send HCI events (vendor-dependent), so make sure to
   // StopWatching the file descriptor after this.
-
-  if (vstate != VENDOR_STATE_OPENED) {
-    ALOGW("VendorInterface is not allow close(%d)", vstate);
-    return;
-  }
-  vstate = VENDOR_STATE_CLOSING;
-  ALOGI("%s: VendorInterface::Close", __func__);
-
   if (lib_interface_ != nullptr) {
-    lib_interface_->cleanup();
     bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
     lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
   }
 
-  {
-    std::unique_lock<std::mutex> guard(vendor_mutex_);
+  fd_watcher_.StopWatchingFileDescriptors();
 
-    fd_watcher_.StopWatchingFileDescriptors();
-    if (hci_ != nullptr) {
-      delete hci_;
-      hci_ = nullptr;
-    }
+  if (hci_ != nullptr) {
+    delete hci_;
+    hci_ = nullptr;
+  }
 
-    if (lib_interface_ != nullptr) {
-      lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
+  if (lib_interface_ != nullptr) {
+    lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
 
-      int power_state = BT_VND_PWR_OFF;
-      lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+    int power_state = BT_VND_PWR_OFF;
+    lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
 
-      lib_interface_ = nullptr;
-    }
+    lib_interface_->cleanup();
+    lib_interface_ = nullptr;
+  }
 
-    if (lib_handle_ != nullptr) {
-      dlclose(lib_handle_);
-      lib_handle_ = nullptr;
-    }
+  if (lib_handle_ != nullptr) {
+    dlclose(lib_handle_);
+    lib_handle_ = nullptr;
+  }
 
-    if (firmware_startup_timer_ != nullptr) {
-      delete firmware_startup_timer_;
-      firmware_startup_timer_ = nullptr;
-    }
-    vstate = VENDOR_STATE_CLOSED;
-  }  // vendor_mutex_ done
-  ALOGI("%s: VendorInterface::Close done!!!", __func__);
+  if (firmware_startup_timer_ != nullptr) {
+    delete firmware_startup_timer_;
+    firmware_startup_timer_ = nullptr;
+  }
 }
 
 size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
-  {
-    std::unique_lock<std::mutex> guard(vendor_mutex_);
+  std::unique_lock<std::mutex> lock(wakeup_mutex_);
+  recent_activity_flag = true;
 
-    if (vstate != VENDOR_STATE_OPENED) {
-      ALOGW("VendorInterface is not open yet(%d)!", vstate);
-      return 0;
-    }
-    ALOGI("%s: VendorInterface::Send", __func__);
-
-    if (lib_interface_ == nullptr) {
-      ALOGE("lib_interface_ is null");
-      return 0;
-    }
-    recent_activity_flag = true;
-    if (lpm_wake_deasserted == true) {
-      // Restart the timer.
-      fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+  if (lpm_wake_deasserted == true) {
+    // Restart the timer.
+    fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
                                  [this]() { OnTimeout(); });
-      // Assert wake.
-      lpm_wake_deasserted = false;
-      bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
-      lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
-      ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
-    }
+    // Assert wake.
+    lpm_wake_deasserted = false;
+    bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
+    lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
+    ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
+  }
 
-    return hci_ ? hci_->Send(type, data, length) : 0;
-  }  // vendor_mutex_ done
+  return hci_->Send(type, data, length);
 }
 
 void VendorInterface::OnFirmwareConfigured(uint8_t result) {
@@ -394,36 +339,25 @@
     firmware_startup_timer_ = nullptr;
   }
 
-  {
-    std::unique_lock<std::mutex> guard(initcb_mutex_);
-    ALOGD("%s OnFirmwareConfigured get lock", __func__);
-    if (initialize_complete_cb_ != nullptr) {
-      LOG_ALWAYS_FATAL_IF((result != 0),
-          "%s: Failed to init firmware!", __func__);
-      initialize_complete_cb_(result == 0);
-    }
-  }  // initcb_mutex_ done
-
-  if (lib_interface_ != nullptr) {
-    lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
-    ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
-
-    bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
-    lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
-
-    ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
-    fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
-                                 [this]() { OnTimeout(); });
-  }
-  else {
-    ALOGE("lib_interface_ is null");
+  if (initialize_complete_cb_ != nullptr) {
+    initialize_complete_cb_(result == 0);
+    initialize_complete_cb_ = nullptr;
   }
 
-  initialize_complete_cb_ = nullptr;
+  lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
+  ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
+
+  bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
+  lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
+
+  ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
+  fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+                               [this]() { OnTimeout(); });
 }
 
 void VendorInterface::OnTimeout() {
   ALOGV("%s", __func__);
+  std::unique_lock<std::mutex> lock(wakeup_mutex_);
   if (recent_activity_flag == false) {
     lpm_wake_deasserted = true;
     bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index 2df3946..040f31a 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -22,8 +22,6 @@
 #include "bt_vendor_lib.h"
 #include "hci_protocol.h"
 
-extern std::mutex initcb_mutex_;
-
 namespace android {
 namespace hardware {
 namespace bluetooth {
@@ -47,9 +45,10 @@
   size_t Send(uint8_t type, const uint8_t* data, size_t length);
 
   void OnFirmwareConfigured(uint8_t result);
-  virtual ~VendorInterface() = default;
 
  private:
+  virtual ~VendorInterface() = default;
+
   bool Open(InitializeCompleteCallback initialize_complete_cb,
             PacketReadCallback event_cb, PacketReadCallback acl_cb,
             PacketReadCallback sco_cb, PacketReadCallback iso_cb);
diff --git a/bluetooth/aidl/TEST_MAPPING b/bluetooth/aidl/TEST_MAPPING
index 41a508e..18958d2 100644
--- a/bluetooth/aidl/TEST_MAPPING
+++ b/bluetooth/aidl/TEST_MAPPING
@@ -1,24 +1,12 @@
 {
   "presubmit" : [
     {
-      "name" : "VtsHalBluetoothTargetTest",
-      "options": [
-        {
-          // TODO(b/275847929)
-          "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
-        }
-      ]
+      "name" : "VtsHalBluetoothTargetTest"
     }
   ],
   "hwasan-presubmit" : [
     {
-      "name" : "VtsHalBluetoothTargetTest",
-      "options": [
-        {
-          // TODO(b/275847929)
-          "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Vsr_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
-        }
-      ]
+      "name" : "VtsHalBluetoothTargetTest"
     }
   ]
 }
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index afe153a..9862e9e 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -50,6 +50,19 @@
 
 void OnDeath(void* cookie);
 
+std::optional<std::string> GetSystemProperty(const std::string& property) {
+  std::array<char, PROPERTY_VALUE_MAX> value_array{0};
+  auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
+  if (value_len <= 0) {
+    return std::nullopt;
+  }
+  return std::string(value_array.data(), value_len);
+}
+
+bool starts_with(const std::string& str, const std::string& prefix) {
+  return str.compare(0, prefix.length(), prefix) == 0;
+}
+
 class BluetoothDeathRecipient {
  public:
   BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
@@ -169,7 +182,10 @@
   mFdWatcher.WatchFdForNonBlockingReads(mFd,
                                         [this](int) { mH4->OnDataReady(); });
 
-  send(PacketType::COMMAND, reset);
+  ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
+  if (!result.isOk()) {
+    ALOGE("Error sending reset command");
+  }
   auto status = resetFuture.wait_for(std::chrono::seconds(1));
   mFdWatcher.StopWatchingFileDescriptors();
   if (status == std::future_status::ready) {
@@ -224,8 +240,19 @@
 
   mDeathRecipient->LinkToDeath(mCb);
 
-  // TODO: This should not be necessary when the device implements rfkill.
-  reset();
+  // TODO: HCI Reset on emulators since the bluetooth controller
+  // cannot be powered on/off during the HAL setup; and the stack
+  // might received spurious packets/events during boottime.
+  // Proper solution would be to use bt-virtio or vsock to better
+  // control the link to rootcanal and the controller lifetime.
+  const std::string kBoardProperty = "ro.product.board";
+  const std::string kCuttlefishBoard = "cutf";
+  auto board_name = GetSystemProperty(kBoardProperty);
+  if (board_name.has_value() && (
+        starts_with(board_name.value(), "cutf") ||
+        starts_with(board_name.value(), "goldfish"))) {
+    reset();
+  }
 
   mH4 = std::make_shared<H4Protocol>(
       mFd,
@@ -299,30 +326,35 @@
 
 ndk::ScopedAStatus BluetoothHci::sendHciCommand(
     const std::vector<uint8_t>& packet) {
-  send(PacketType::COMMAND, packet);
-  return ndk::ScopedAStatus::ok();
+  return send(PacketType::COMMAND, packet);
 }
 
 ndk::ScopedAStatus BluetoothHci::sendAclData(
     const std::vector<uint8_t>& packet) {
-  send(PacketType::ACL_DATA, packet);
-  return ndk::ScopedAStatus::ok();
+  return send(PacketType::ACL_DATA, packet);
 }
 
 ndk::ScopedAStatus BluetoothHci::sendScoData(
     const std::vector<uint8_t>& packet) {
-  send(PacketType::SCO_DATA, packet);
-  return ndk::ScopedAStatus::ok();
+  return send(PacketType::SCO_DATA, packet);
 }
 
 ndk::ScopedAStatus BluetoothHci::sendIsoData(
     const std::vector<uint8_t>& packet) {
-  send(PacketType::ISO_DATA, packet);
-  return ndk::ScopedAStatus::ok();
+  return send(PacketType::ISO_DATA, packet);
 }
 
-void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
+ndk::ScopedAStatus BluetoothHci::send(PacketType type,
+    const std::vector<uint8_t>& v) {
+  if (mH4 == nullptr) {
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+  }
+  if (v.empty()) {
+    ALOGE("Packet is empty, no data was found to be sent");
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
   mH4->Send(type, v);
+  return ndk::ScopedAStatus::ok();
 }
 
 }  // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
index 85aafc8..477cc5c 100644
--- a/bluetooth/aidl/default/BluetoothHci.h
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -66,8 +66,9 @@
   ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
 
   int getFdFromDevPath();
-  void send(::android::hardware::bluetooth::hci::PacketType type,
-            const std::vector<uint8_t>& packet);
+  [[nodiscard]] ndk::ScopedAStatus send(
+      ::android::hardware::bluetooth::hci::PacketType type,
+      const std::vector<uint8_t>& packet);
   std::unique_ptr<NetBluetoothMgmt> management_{};
 
   // Send a reset command and discard all packets until a reset is received.
diff --git a/bluetooth/audio/OWNERS b/bluetooth/audio/OWNERS
index a8e9bda..f3657ca 100644
--- a/bluetooth/audio/OWNERS
+++ b/bluetooth/audio/OWNERS
@@ -1,4 +1,6 @@
+# Bug component: 27441
+
 include platform/packages/modules/Bluetooth:/OWNERS
 
-cheneyni@google.com
 aliceypkuo@google.com
+quocbaodo@google.com
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 16b22fe..1028fae 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -24,6 +24,7 @@
 aidl_interface {
     name: "android.hardware.bluetooth.audio",
     vendor_available: true,
+    host_supported: true,
     srcs: ["android/hardware/bluetooth/audio/*.aidl"],
     stability: "vintf",
     imports: [
diff --git a/bluetooth/audio/aidl/TEST_MAPPING b/bluetooth/audio/aidl/TEST_MAPPING
new file mode 100644
index 0000000..0c853f8
--- /dev/null
+++ b/bluetooth/audio/aidl/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalBluetoothAudioTargetTest"
+    }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "VtsHalBluetoothAudioTargetTest"
+    }
+  ]
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index 2a88959..9c72e19 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -27,9 +27,31 @@
 namespace bluetooth {
 namespace audio {
 
+struct BluetoothAudioProviderContext {
+  SessionType session_type;
+};
+
+static void binderUnlinkedCallbackAidl(void* cookie) {
+  LOG(INFO) << __func__;
+  BluetoothAudioProviderContext* ctx =
+      static_cast<BluetoothAudioProviderContext*>(cookie);
+  delete ctx;
+}
+
+static void binderDiedCallbackAidl(void* cookie) {
+  LOG(INFO) << __func__;
+  BluetoothAudioProviderContext* ctx =
+      static_cast<BluetoothAudioProviderContext*>(cookie);
+  CHECK_NE(ctx, nullptr);
+
+  BluetoothAudioSessionReport::OnSessionEnded(ctx->session_type);
+}
+
 BluetoothAudioProvider::BluetoothAudioProvider() {
   death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
       AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
+  AIBinder_DeathRecipient_setOnUnlinked(death_recipient_.get(),
+                                        binderUnlinkedCallbackAidl);
 }
 
 ndk::ScopedAStatus BluetoothAudioProvider::startSession(
@@ -39,17 +61,21 @@
     DataMQDesc* _aidl_return) {
   if (host_if == nullptr) {
     *_aidl_return = DataMQDesc();
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " Illegal argument";
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
   latency_modes_ = latencyModes;
   audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
   stack_iface_ = host_if;
-  is_binder_died = false;
+  BluetoothAudioProviderContext* cookie =
+      new BluetoothAudioProviderContext{session_type_};
 
   AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
-                       this);
+                       cookie);
 
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
   onSessionReady(_aidl_return);
   return ndk::ScopedAStatus::ok();
 }
@@ -60,10 +86,8 @@
   if (stack_iface_ != nullptr) {
     BluetoothAudioSessionReport::OnSessionEnded(session_type_);
 
-    if (!is_binder_died) {
-      AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
-                             death_recipient_.get(), this);
-    }
+    AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
+                           death_recipient_.get(), this);
   } else {
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << " has NO session";
@@ -77,10 +101,9 @@
 
 ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
     BluetoothAudioStatus status) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-            << ", status=" << toString(status);
-
   if (stack_iface_ != nullptr) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", status=" << toString(status);
     BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
                                                      status);
   } else {
@@ -108,8 +131,6 @@
 
 ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
     const AudioConfiguration& audio_config) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
   if (stack_iface_ == nullptr || audio_config_ == nullptr) {
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << " has NO session";
@@ -125,13 +146,13 @@
   audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
   BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
                                                         *audio_config_);
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << " | audio_config=" << audio_config.toString();
   return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed(
     bool allowed) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
   if (stack_iface_ == nullptr) {
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << " has NO session";
@@ -143,17 +164,6 @@
   return ndk::ScopedAStatus::ok();
 }
 
-void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) {
-  LOG(ERROR) << __func__ << " - BluetoothAudio Service died";
-  auto provider = static_cast<BluetoothAudioProvider*>(ptr);
-  if (provider == nullptr) {
-    LOG(ERROR) << __func__ << ": Null AudioProvider HAL died";
-    return;
-  }
-  provider->is_binder_died = true;
-  provider->endSession();
-}
-
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace hardware
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index dbfff7d..b6e07a1 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -54,7 +54,6 @@
 
  protected:
   virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0;
-  static void binderDiedCallbackAidl(void* cookie_ptr);
 
   ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
 
@@ -62,9 +61,7 @@
   std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
   SessionType session_type_;
   std::vector<LatencyMode> latency_modes_;
-  bool is_binder_died = false;
 };
-
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace hardware
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index fe297e0..fa85fa8 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -28,6 +28,7 @@
         "libcutils",
         "libfmq",
     ],
+    test_config: "VtsHalBluetoothAudioTargetTest.xml",
     test_suites: [
         "general-tests",
         "vts",
diff --git a/camera/provider/aidl/vts/AndroidTest.xml b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
similarity index 65%
rename from camera/provider/aidl/vts/AndroidTest.xml
rename to bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
index 226121d..7b02685 100644
--- a/camera/provider/aidl/vts/AndroidTest.xml
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -13,21 +13,24 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Runs VtsAidlHalCameraProvider_TargetTest.">
+<configuration description="Runs VtsHalBluetoothAudioTargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController">
+        <!-- Skips test module if ro.product.first_api_level < 33. -->
+        <option name="min-api-level" value="33" />
+    </object>
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="VtsAidlHalCameraProvider_TargetTest->/data/local/tmp/VtsAidlHalCameraProvider_TargetTest" />
+        <option name="push" value="VtsHalBluetoothAudioTargetTest->/data/local/tmp/VtsHalBluetoothAudioTargetTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlHalCameraProvider_TargetTest" />
-        <option name="native-test-timeout" value="1800000"/> <!-- 30 min -->
+        <option name="module-name" value="VtsHalBluetoothAudioTargetTest" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 914d2b2..a09e7fe 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -36,6 +36,7 @@
 cc_library_shared {
     name: "libbluetooth_audio_session_aidl",
     vendor: true,
+    host_supported: true,
     srcs: [
         "aidl_session/BluetoothAudioCodecs.cpp",
         "aidl_session/BluetoothAudioSession.cpp",
@@ -93,4 +94,5 @@
     srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],
     package_name: "aidl.android.hardware.bluetooth.audio.setting",
     api_dir: "le_audio_codec_capabilities/schema",
+    root_elements: ["leAudioOffloadSetting"],
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index ee5527e..0bcafa3 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -20,6 +20,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android/binder_manager.h>
+#include <hardware/audio.h>
 
 #include "BluetoothAudioSession.h"
 
@@ -440,6 +441,16 @@
 void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   low_latency_allowed_ = allowed;
+  // TODO(b/294498919): Remove this after there is API to update latency mode
+  // after audio session started. If low_latency_allowed_ is true, the session
+  // can support LOW_LATENCY and FREE LatencyMode.
+  if (low_latency_allowed_) {
+    if (std::find(latency_modes_.begin(), latency_modes_.end(),
+                  LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
+      LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
+      latency_modes_.push_back(LatencyMode::LOW_LATENCY);
+    }
+  }
   if (observers_.empty()) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
                  << " has NO port state observer";
@@ -476,23 +487,9 @@
 
 void BluetoothAudioSession::UpdateSourceMetadata(
     const struct source_metadata& source_metadata) {
-  std::lock_guard<std::recursive_mutex> guard(mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
-               << " has NO session";
-    return;
-  }
-
   ssize_t track_count = source_metadata.track_count;
   LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
             << track_count << " track(s)";
-  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return;
-  }
-
   SourceMetadata hal_source_metadata;
   hal_source_metadata.tracks.resize(track_count);
   for (int i = 0; i < track_count; i++) {
@@ -509,33 +506,14 @@
                  << toString(hal_source_metadata.tracks[i].contentType)
                  << ", gain=" << hal_source_metadata.tracks[i].gain;
   }
-
-  auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_) << " failed";
-  }
+  UpdateSourceMetadata(hal_source_metadata);
 }
 
 void BluetoothAudioSession::UpdateSinkMetadata(
     const struct sink_metadata& sink_metadata) {
-  std::lock_guard<std::recursive_mutex> guard(mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
-               << " has NO session";
-    return;
-  }
-
   ssize_t track_count = sink_metadata.track_count;
   LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
             << track_count << " track(s)";
-  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return;
-  }
-
   SinkMetadata hal_sink_metadata;
   hal_sink_metadata.tracks.resize(track_count);
   for (int i = 0; i < track_count; i++) {
@@ -550,12 +528,57 @@
               << ", dest_device_address="
               << sink_metadata.tracks[i].dest_device_address;
   }
+  UpdateSinkMetadata(hal_sink_metadata);
+}
+
+bool BluetoothAudioSession::UpdateSourceMetadata(
+    const SourceMetadata& hal_source_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return false;
+  }
+
+  auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothAudioSession::UpdateSinkMetadata(
+    const SinkMetadata& hal_sink_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return false;
+  }
 
   auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
   if (!hal_retval.isOk()) {
     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
                  << toString(session_type_) << " failed";
+    return false;
   }
+  return true;
 }
 
 std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
index 5bf17bd..103a9ea 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -23,12 +23,15 @@
 #include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
 #include <aidl/android/hardware/bluetooth/audio/SessionType.h>
 #include <fmq/AidlMessageQueue.h>
-#include <hardware/audio.h>
 
 #include <mutex>
 #include <unordered_map>
 #include <vector>
 
+// To avoid inclusion of hardware/audio.h
+struct sink_metadata;
+struct source_metadata;
+
 namespace aidl {
 namespace android {
 namespace hardware {
@@ -183,6 +186,9 @@
   bool GetPresentationPosition(PresentationPosition& presentation_position);
   void UpdateSourceMetadata(const struct source_metadata& source_metadata);
   void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
+  // New versions for AIDL-only clients.
+  bool UpdateSourceMetadata(const SourceMetadata& hal_source_metadata);
+  bool UpdateSinkMetadata(const SinkMetadata& hal_sink_metadata);
 
   std::vector<LatencyMode> GetSupportedLatencyModes();
   void SetLatencyMode(const LatencyMode& latency_mode);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
index 0782c82..7ae0353 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -156,6 +156,26 @@
     }
   }
 
+  static bool UpdateSourceMetadata(const SessionType& session_type,
+                                   const SourceMetadata& source_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->UpdateSourceMetadata(source_metadata);
+    }
+    return false;
+  }
+
+  static bool UpdateSinkMetadata(const SessionType& session_type,
+                                 const SinkMetadata& sink_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->UpdateSinkMetadata(sink_metadata);
+    }
+    return false;
+  }
+
   static std::vector<LatencyMode> GetSupportedLatencyModes(
       const SessionType& session_type) {
     std::shared_ptr<BluetoothAudioSession> session_ptr =
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
index a4664f1..3d92ee7 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -583,7 +583,7 @@
     *total_bytes_readed = presentation_position.transmittedOctets;
   if (data_position)
     *data_position = {
-        .tv_sec = static_cast<__kernel_old_time_t>(
+        .tv_sec = static_cast<long>(
             presentation_position.transmittedOctetsTimestamp.tvSec),
         .tv_nsec = static_cast<long>(
             presentation_position.transmittedOctetsTimestamp.tvNSec)};
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index 886350e..3cef417 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -96,15 +96,7 @@
 
   public class XmlParser {
     ctor public XmlParser();
-    method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration readCodecConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList readCodecConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.Configuration readConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.ConfigurationList readConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static aidl.android.hardware.bluetooth.audio.setting.LeAudioOffloadSetting readLeAudioOffloadSetting(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.Scenario readScenario(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.ScenarioList readScenarioList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration readStrategyConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList readStrategyConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
   }
diff --git a/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
index 51a624f..5f6d86e 100644
--- a/bluetooth/hci/h4_protocol.cc
+++ b/bluetooth/hci/h4_protocol.cc
@@ -105,15 +105,12 @@
       buffer_offset += 1;
     } else {
       bool packet_ready = hci_packetizer_.OnDataReady(
-          hci_packet_type_, input_buffer, buffer_offset);
+          hci_packet_type_, input_buffer, &buffer_offset);
       if (packet_ready) {
-        // Call packet callback and move offset.
-        buffer_offset += OnPacketReady(hci_packetizer_.GetPacket());
+        // Call packet callback.
+        OnPacketReady(hci_packetizer_.GetPacket());
         // Get ready for the next type byte.
         hci_packet_type_ = PacketType::UNKNOWN;
-      } else {
-        // The data was consumed, but there wasn't a packet.
-        buffer_offset = input_buffer.size();
       }
     }
   }
diff --git a/bluetooth/hci/hci_packetizer.cc b/bluetooth/hci/hci_packetizer.cc
index 5b6c443..4135920 100644
--- a/bluetooth/hci/hci_packetizer.cc
+++ b/bluetooth/hci/hci_packetizer.cc
@@ -51,9 +51,10 @@
 
 bool HciPacketizer::OnDataReady(PacketType packet_type,
                                 const std::vector<uint8_t>& buffer,
-                                size_t offset) {
+                                size_t* offset) {
   bool packet_completed = false;
-  size_t bytes_available = buffer.size() - offset;
+  size_t bytes_available = buffer.size() - *offset;
+
   switch (state_) {
     case HCI_HEADER: {
       size_t header_size =
@@ -62,18 +63,20 @@
         bytes_remaining_ = header_size;
         packet_.clear();
       }
+
       size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
-      packet_.insert(packet_.end(), buffer.begin() + offset,
-                     buffer.begin() + offset + bytes_to_copy);
+      packet_.insert(packet_.end(), buffer.begin() + *offset,
+                     buffer.begin() + *offset + bytes_to_copy);
       bytes_remaining_ -= bytes_to_copy;
       bytes_available -= bytes_to_copy;
+      *offset += bytes_to_copy;
+
       if (bytes_remaining_ == 0) {
         bytes_remaining_ = HciGetPacketLengthForType(packet_type, packet_);
         if (bytes_remaining_ > 0) {
           state_ = HCI_PAYLOAD;
           if (bytes_available > 0) {
-            packet_completed =
-                OnDataReady(packet_type, buffer, offset + bytes_to_copy);
+            packet_completed = OnDataReady(packet_type, buffer, offset);
           }
         } else {
           packet_completed = true;
@@ -84,9 +87,10 @@
 
     case HCI_PAYLOAD: {
       size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
-      packet_.insert(packet_.end(), buffer.begin() + offset,
-                     buffer.begin() + offset + bytes_to_copy);
+      packet_.insert(packet_.end(), buffer.begin() + *offset,
+                     buffer.begin() + *offset + bytes_to_copy);
       bytes_remaining_ -= bytes_to_copy;
+      *offset += bytes_to_copy;
       if (bytes_remaining_ == 0) {
         state_ = HCI_HEADER;
         packet_completed = true;
@@ -94,6 +98,7 @@
       break;
     }
   }
+
   return packet_completed;
 }
 
diff --git a/bluetooth/hci/hci_packetizer.h b/bluetooth/hci/hci_packetizer.h
index ba3e841..0d9319f 100644
--- a/bluetooth/hci/hci_packetizer.h
+++ b/bluetooth/hci/hci_packetizer.h
@@ -28,7 +28,7 @@
  public:
   HciPacketizer() = default;
   bool OnDataReady(PacketType packet_type, const std::vector<uint8_t>& data,
-                   size_t offset);
+                   size_t* offset);
   const std::vector<uint8_t>& GetPacket() const;
 
  protected:
diff --git a/bluetooth/hci/test/h4_protocol_unittest.cc b/bluetooth/hci/test/h4_protocol_unittest.cc
index d3fab61..f0c49b5 100644
--- a/bluetooth/hci/test/h4_protocol_unittest.cc
+++ b/bluetooth/hci/test/h4_protocol_unittest.cc
@@ -31,7 +31,6 @@
 #include <vector>
 
 #include "async_fd_watcher.h"
-#include "log/log.h"
 
 using android::hardware::bluetooth::async::AsyncFdWatcher;
 using namespace android::hardware::bluetooth::hci;
@@ -49,6 +48,7 @@
 static char event_data[100] = "The edges of a surface are lines.";
 static char iso_data[100] =
     "A plane angle is the inclination to one another of two lines in a ...";
+static char short_payload[10] = "12345";
 
 // 5 seconds.  Just don't hang.
 static constexpr size_t kTimeoutMs = 5000;
@@ -225,6 +225,49 @@
     CallDataReady();
   }
 
+  void WriteAndExpectManyAclDataPacketsDifferentOffsetsShort() {
+    std::promise<void> last_packet_promise;
+    size_t kNumPackets = 30;
+    // h4 type[1] + handle[2] + size[2]
+    char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
+                        0};
+    int length = strlen(short_payload);
+    preamble[3] = length & 0xFF;
+    preamble[4] = 0;
+
+    EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, kAclHeaderSize,
+                                            short_payload)))
+        .Times(kNumPackets);
+    ExpectInboundEvent(event_data, &last_packet_promise);
+
+    char all_packets[kNumPackets * 10];
+    size_t total_bytes = 0;
+
+    for (size_t packet = 0; packet < kNumPackets; packet++) {
+      for (size_t i = 0; i < sizeof(preamble); i++) {
+        all_packets[total_bytes++] = preamble[i];
+      }
+      for (size_t i = 0; i < length; i++) {
+        all_packets[total_bytes++] = short_payload[i];
+      }
+    }
+
+    size_t written_bytes = 0;
+    size_t partial_size = 1;
+    while (written_bytes < total_bytes) {
+      size_t to_write = std::min(partial_size, total_bytes - written_bytes);
+      TEMP_FAILURE_RETRY(
+          write(chip_uart_fd_, all_packets + written_bytes, to_write));
+      written_bytes += to_write;
+      CallDataReady();
+      partial_size++;
+      partial_size = partial_size % 5 + 1;
+    }
+    WriteInboundEvent(event_data);
+    CallDataReady();
+    WaitForTimeout(&last_packet_promise);
+  }
+
   testing::MockFunction<void(const std::vector<uint8_t>&)> cmd_cb_;
   testing::MockFunction<void(const std::vector<uint8_t>&)> event_cb_;
   testing::MockFunction<void(const std::vector<uint8_t>&)> acl_cb_;
@@ -276,6 +319,10 @@
   WriteAndExpectManyInboundAclDataPackets(sco_data);
 }
 
+TEST_F(H4ProtocolTest, TestMultipleWritesPacketsShortWrites) {
+  WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
 TEST_F(H4ProtocolTest, TestDisconnect) {
   EXPECT_CALL(disconnect_cb_, Call());
   close(chip_uart_fd_);
@@ -332,10 +379,8 @@
 
   void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
 
-  void CallDataReady() override {
-    // The Async test can't call data ready.
-    FAIL();
-  }
+  // Calling CallDataReady() has no effect in the AsyncTest
+  void CallDataReady() override {}
 
   void SendAndReadUartOutbound(PacketType type, char* data) {
     ALOGD("%s sending", __func__);
@@ -434,6 +479,10 @@
   WriteAndExpectManyInboundAclDataPackets(sco_data);
 }
 
+TEST_F(H4ProtocolAsyncTest, TestMultipleWritesPacketsShortWrites) {
+  WriteAndExpectManyAclDataPacketsDifferentOffsetsShort();
+}
+
 TEST_F(H4ProtocolAsyncTest, TestDisconnect) {
   std::promise<void> promise;
   EXPECT_CALL(disconnect_cb_, Call()).WillOnce(Notify(&promise));
diff --git a/boot/1.0/vts/functional/OWNERS b/boot/1.0/vts/functional/OWNERS
deleted file mode 100644
index 36e79be..0000000
--- a/boot/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 30545
-dvander@google.com
diff --git a/boot/1.1/vts/functional/OWNERS b/boot/1.1/vts/functional/OWNERS
deleted file mode 100644
index 36e79be..0000000
--- a/boot/1.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 30545
-dvander@google.com
diff --git a/boot/OWNERS b/boot/OWNERS
new file mode 100644
index 0000000..fca3dff
--- /dev/null
+++ b/boot/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1014951
+
+dvander@google.com
+zhangkelvin@google.com
diff --git a/boot/aidl/vts/functional/OWNERS b/boot/aidl/vts/functional/OWNERS
deleted file mode 100644
index bc813d8..0000000
--- a/boot/aidl/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 30545
-zhangkelvin@google.com
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
deleted file mode 100644
index 302fdd7..0000000
--- a/broadcastradio/1.0/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/1.0/vts/functional/OWNERS b/broadcastradio/1.0/vts/functional/OWNERS
deleted file mode 100644
index aa19d6a..0000000
--- a/broadcastradio/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 533946
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/1.1/default/OWNERS
deleted file mode 100644
index 259b91e..0000000
--- a/broadcastradio/1.1/default/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Automotive team
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/2.0/default/OWNERS b/broadcastradio/2.0/default/OWNERS
deleted file mode 100644
index 259b91e..0000000
--- a/broadcastradio/2.0/default/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Automotive team
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/2.0/vts/OWNERS b/broadcastradio/2.0/vts/OWNERS
deleted file mode 100644
index 09690ef..0000000
--- a/broadcastradio/2.0/vts/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Automotive team
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
-
-# VTS team
-dshi@google.com
diff --git a/broadcastradio/2.0/vts/functional/OWNERS b/broadcastradio/2.0/vts/functional/OWNERS
deleted file mode 100644
index aa19d6a..0000000
--- a/broadcastradio/2.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 533946
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/OWNERS
similarity index 80%
rename from broadcastradio/1.1/vts/OWNERS
rename to broadcastradio/OWNERS
index aa19d6a..7c6aaca 100644
--- a/broadcastradio/1.1/vts/OWNERS
+++ b/broadcastradio/OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 533946
-xuweilin@google.com
-oscarazu@google.com
+
 ericjeong@google.com
-keunyoung@google.com
+oscarazu@google.com
+xuweilin@google.com
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl
index 3298cac..7769b8c 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Metadata.aidl
@@ -70,9 +70,9 @@
     /**
      * Station name.
      *
-     * This is a generic field to cover any radio technology.
+     * <p>This is a generic field to cover any radio technology.
      *
-     * If the PROGRAM_NAME has the same content as DAB_*_NAME or RDS_PS,
+     * <p>Note: If the program name has the same content as dab*Name or ({@link Metadata#rdsPs},
      * it may not be present, to preserve space - framework must repopulate
      * it on the client side.
      */
@@ -86,10 +86,10 @@
     /**
      * DAB ensemble name abbreviated (string).
      *
-     * The string must be up to 8 characters long.
+     * <p>Note: The string must be up to 8 characters long.
      *
-     * If the short variant is present, the long (DAB_ENSEMBLE_NAME) one must be
-     * present as well.
+     * <p>Note: If the short variant is present, the long ({@link Metadata#dabEnsembleName})
+     * one must be present as well.
      */
     String dabEnsembleNameShort;
 
@@ -99,7 +99,9 @@
     String dabServiceName;
 
     /**
-     * DAB service name abbreviated (see DAB_ENSEMBLE_NAME_SHORT) (string)
+     * DAB service name abbreviated (string)
+     *
+     * <p>Note: The string must be up to 8 characters long.
      */
     String dabServiceNameShort;
 
@@ -109,7 +111,9 @@
     String dabComponentName;
 
     /**
-     * DAB component name abbreviated (see DAB_ENSEMBLE_NAME_SHORT) (string)
+     * DAB component name abbreviated (string)
+     *
+     * <p>Note: The string must be up to 8 characters long.
      */
     String dabComponentNameShort;
 }
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl
index 2057d97..a2de5d6 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramIdentifier.aidl
@@ -30,8 +30,10 @@
     IdentifierType type = IdentifierType.INVALID;
 
     /**
-     * The uint64_t value field holds the value in format described in comments
-     * for IdentifierType enum.
+     * The value field holds the value in format described in comments for IdentifierType enum.
+     *
+     * The value should be 64-bit unsigned integer, but is represented as 64-bit signed integer
+     * in AIDL.
      */
     long value;
 }
diff --git a/broadcastradio/aidl/default/Android.bp b/broadcastradio/aidl/default/Android.bp
index 720aa8a..1d1bef7 100644
--- a/broadcastradio/aidl/default/Android.bp
+++ b/broadcastradio/aidl/default/Android.bp
@@ -23,23 +23,8 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_binary {
-    name: "android.hardware.broadcastradio-service.default",
-    relative_install_path: "hw",
-    init_rc: ["broadcastradio-default.rc"],
-    vintf_fragments: ["broadcastradio-default.xml"],
-    vendor: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-    srcs: [
-        "BroadcastRadio.cpp",
-        "main.cpp",
-        "VirtualProgram.cpp",
-        "VirtualRadio.cpp",
-    ],
+cc_defaults {
+    name: "BroadcastRadioHalDefaults",
     static_libs: [
         "android.hardware.broadcastradio@common-utils-aidl-lib",
         "android.hardware.broadcastradio@common-utils-lib",
@@ -51,4 +36,61 @@
         "liblog",
         "libcutils",
     ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.broadcastradio-service.default",
+    relative_install_path: "hw",
+    init_rc: ["broadcastradio-default.rc"],
+    vintf_fragments: ["broadcastradio-default.xml"],
+    vendor: true,
+    defaults: [
+        "BroadcastRadioHalDefaults",
+    ],
+    srcs: [
+        "main.cpp",
+    ],
+    static_libs: [
+        "DefaultBroadcastRadioHal",
+    ],
+}
+
+cc_library {
+    name: "DefaultBroadcastRadioHal",
+    vendor: true,
+    export_include_dirs: ["."],
+    defaults: [
+        "BroadcastRadioHalDefaults",
+    ],
+    srcs: [
+        "BroadcastRadio.cpp",
+        "VirtualProgram.cpp",
+        "VirtualRadio.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "android.hardware.broadcastradio-service.default_fuzzer",
+    vendor: true,
+    defaults: [
+        "BroadcastRadioHalDefaults",
+        "service_fuzzer_defaults",
+    ],
+    static_libs: [
+        "DefaultBroadcastRadioHal",
+        "android.hardware.broadcastradio-V1-ndk",
+    ],
+    srcs: [
+        "fuzzer.cpp",
+    ],
+    fuzz_config: {
+        cc: [
+            "xuweilin@google.com",
+        ],
+    },
 }
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index c0c475a..8584921 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -115,7 +115,8 @@
 }
 
 BroadcastRadio::~BroadcastRadio() {
-    mThread.reset();
+    mTuningThread.reset();
+    mProgramListThread.reset();
 }
 
 ScopedAStatus BroadcastRadio::getAmFmRegionConfig(bool full, AmFmRegionConfig* returnConfigs) {
@@ -239,7 +240,7 @@
         callback->onCurrentProgramInfoChanged(programInfo);
     };
     auto cancelTask = [program, callback]() { callback->onTuneFailed(Result::CANCELED, program); };
-    mThread->schedule(task, cancelTask, kTuneDelayTimeMs);
+    mTuningThread->schedule(task, cancelTask, kTuneDelayTimeMs);
 
     return ScopedAStatus::ok();
 }
@@ -267,7 +268,7 @@
 
             callback->onTuneFailed(Result::TIMEOUT, {});
         };
-        mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+        mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
 
         return ScopedAStatus::ok();
     }
@@ -300,7 +301,7 @@
         }
         callback->onCurrentProgramInfoChanged(programInfo);
     };
-    mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+    mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
 
     return ScopedAStatus::ok();
 }
@@ -355,15 +356,15 @@
         callback->onCurrentProgramInfoChanged(programInfo);
     };
     auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
-    mThread->schedule(task, cancelTask, kStepDelayTimeMs);
+    mTuningThread->schedule(task, cancelTask, kStepDelayTimeMs);
 
     return ScopedAStatus::ok();
 }
 
 void BroadcastRadio::cancelLocked() {
-    LOG(DEBUG) << __func__ << ": cancelling current operations...";
+    LOG(DEBUG) << __func__ << ": cancelling current tuning operations...";
 
-    mThread->cancelAll();
+    mTuningThread->cancelAll();
     if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) {
         mIsTuneCompleted = true;
     }
@@ -388,6 +389,8 @@
 
     lock_guard<mutex> lk(mMutex);
 
+    cancelProgramListUpdateLocked();
+
     const auto& list = mVirtualRadio.getProgramList();
     vector<VirtualProgram> filteredList;
     std::copy_if(list.begin(), list.end(), std::back_inserter(filteredList), filterCb);
@@ -410,31 +413,43 @@
 
         callback->onProgramListUpdated(chunk);
     };
-    mThread->schedule(task, kListDelayTimeS);
+    mProgramListThread->schedule(task, kListDelayTimeS);
 
     return ScopedAStatus::ok();
 }
 
+void BroadcastRadio::cancelProgramListUpdateLocked() {
+    LOG(DEBUG) << __func__ << ": cancelling current program list update operations...";
+    mProgramListThread->cancelAll();
+}
+
 ScopedAStatus BroadcastRadio::stopProgramListUpdates() {
     LOG(DEBUG) << __func__ << ": requested program list updates to stop...";
-    // TODO(b/243681584) Implement stop program list updates method
+    lock_guard<mutex> lk(mMutex);
+    cancelProgramListUpdateLocked();
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus BroadcastRadio::isConfigFlagSet(ConfigFlag flag, [[maybe_unused]] bool* returnIsSet) {
+ScopedAStatus BroadcastRadio::isConfigFlagSet(ConfigFlag flag, bool* returnIsSet) {
     LOG(DEBUG) << __func__ << ": flag = " << toString(flag);
 
-    LOG(INFO) << __func__ << ": getting ConfigFlag is not supported";
-    return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-            resultToInt(Result::NOT_SUPPORTED), "getting ConfigFlag is not supported");
+    int flagBit = static_cast<int>(flag);
+    lock_guard<mutex> lk(mMutex);
+    *returnIsSet = ((mConfigFlagValues >> flagBit) & 1) == 1;
+    return ScopedAStatus::ok();
 }
 
 ScopedAStatus BroadcastRadio::setConfigFlag(ConfigFlag flag, bool value) {
     LOG(DEBUG) << __func__ << ": flag = " << toString(flag) << ", value = " << value;
 
-    LOG(INFO) << __func__ << ": setting ConfigFlag is not supported";
-    return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-            resultToInt(Result::NOT_SUPPORTED), "setting ConfigFlag is not supported");
+    int flagBitMask = 1 << (static_cast<int>(flag));
+    lock_guard<mutex> lk(mMutex);
+    if (value) {
+        mConfigFlagValues |= flagBitMask;
+    } else {
+        mConfigFlagValues &= ~flagBitMask;
+    }
+    return ScopedAStatus::ok();
 }
 
 ScopedAStatus BroadcastRadio::setParameters(
diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h
index 1c85ddc..0f818ce 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -68,16 +68,22 @@
     const VirtualRadio& mVirtualRadio;
     std::mutex mMutex;
     AmFmRegionConfig mAmFmConfig GUARDED_BY(mMutex);
-    std::unique_ptr<::android::WorkerThread> mThread GUARDED_BY(mMutex) =
+    std::unique_ptr<::android::WorkerThread> mTuningThread GUARDED_BY(mMutex) =
+            std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
+    std::unique_ptr<::android::WorkerThread> mProgramListThread GUARDED_BY(mMutex) =
             std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
     bool mIsTuneCompleted GUARDED_BY(mMutex) = true;
     Properties mProperties GUARDED_BY(mMutex);
     ProgramSelector mCurrentProgram GUARDED_BY(mMutex) = {};
     std::shared_ptr<ITunerCallback> mCallback GUARDED_BY(mMutex);
 
+    // Bitmap for all ConfigFlag values
+    int mConfigFlagValues GUARDED_BY(mMutex) = 0;
+
     std::optional<AmFmBandRange> getAmFmRangeLocked() const;
     void cancelLocked();
     ProgramInfo tuneInternalLocked(const ProgramSelector& sel);
+    void cancelProgramListUpdateLocked();
 
     binder_status_t cmdHelp(int fd) const;
     binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
diff --git a/broadcastradio/aidl/default/VirtualRadio.cpp b/broadcastradio/aidl/default/VirtualRadio.cpp
index 126bcff..86c5a96 100644
--- a/broadcastradio/aidl/default/VirtualRadio.cpp
+++ b/broadcastradio/aidl/default/VirtualRadio.cpp
@@ -53,18 +53,18 @@
     static VirtualRadio amFmRadioMock(
         "AM/FM radio mock",
         {
-            {makeSelectorAmfm(/* frequency= */ 94900), "Wild 94.9", "Drake ft. Rihanna",
+            {makeSelectorAmfm(/* frequency= */ 94900u), "Wild 94.9", "Drake ft. Rihanna",
                 "Too Good"},
-            {makeSelectorAmfm(/* frequency= */ 96500), "KOIT", "Celine Dion", "All By Myself"},
-            {makeSelectorAmfm(/* frequency= */ 97300), "Alice@97.3", "Drops of Jupiter", "Train"},
-            {makeSelectorAmfm(/* frequency= */ 99700), "99.7 Now!", "The Chainsmokers", "Closer"},
-            {makeSelectorAmfm(/* frequency= */ 101300), "101-3 KISS-FM", "Justin Timberlake",
+            {makeSelectorAmfm(/* frequency= */ 96500u), "KOIT", "Celine Dion", "All By Myself"},
+            {makeSelectorAmfm(/* frequency= */ 97300u), "Alice@97.3", "Drops of Jupiter", "Train"},
+            {makeSelectorAmfm(/* frequency= */ 99700u), "99.7 Now!", "The Chainsmokers", "Closer"},
+            {makeSelectorAmfm(/* frequency= */ 101300u), "101-3 KISS-FM", "Justin Timberlake",
                 "Rock Your Body"},
-            {makeSelectorAmfm(/* frequency= */ 103700), "iHeart80s @ 103.7", "Michael Jackson",
+            {makeSelectorAmfm(/* frequency= */ 103700u), "iHeart80s @ 103.7", "Michael Jackson",
                 "Billie Jean"},
-            {makeSelectorAmfm(/* frequency= */ 106100), "106 KMEL", "Drake", "Marvins Room"},
-            {makeSelectorAmfm(/* frequency= */ 700), "700 AM", "Artist700", "Title700"},
-            {makeSelectorAmfm(/* frequency= */ 1700), "1700 AM", "Artist1700", "Title1700"},
+            {makeSelectorAmfm(/* frequency= */ 106100u), "106 KMEL", "Drake", "Marvins Room"},
+            {makeSelectorAmfm(/* frequency= */ 700u), "700 AM", "Artist700", "Title700"},
+            {makeSelectorAmfm(/* frequency= */ 1700u), "1700 AM", "Artist1700", "Title1700"},
         });
     // clang-format on
     return amFmRadioMock;
@@ -77,13 +77,13 @@
         "DAB radio mock",
         {
             {makeSelectorDab(/* sidExt= */ 0xA000000001u, /* ensemble= */ 0x0001u,
-                /* freq= */ 225648), "BBC Radio 1", "Khalid", "Talk"},
+                /* freq= */ 225648u), "BBC Radio 1", "Khalid", "Talk"},
             {makeSelectorDab(/* sidExt= */ 0xB000000001u, /* ensemble= */ 0x1001u,
-                /* freq= */ 222064), "Classic FM", "Jean Sibelius", "Andante Festivo"},
+                /* freq= */ 222064u), "Classic FM", "Jean Sibelius", "Andante Festivo"},
             {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u,
-                /* freq= */ 227360), "Absolute Radio", "Coldplay", "Clocks"},
+                /* freq= */ 227360u), "Absolute Radio", "Coldplay", "Clocks"},
             {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u,
-                /* freq= */ 222064), "Absolute Radio", "Coldplay", "Clocks"},
+                /* freq= */ 222064u), "Absolute Radio", "Coldplay", "Clocks"},
         });
     // clang-format on
     return dabRadioMock;
diff --git a/broadcastradio/aidl/default/fuzzer.cpp b/broadcastradio/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..d535432
--- /dev/null
+++ b/broadcastradio/aidl/default/fuzzer.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "BroadcastRadio.h"
+#include "VirtualRadio.h"
+
+using ::aidl::android::hardware::broadcastradio::BroadcastRadio;
+using ::aidl::android::hardware::broadcastradio::VirtualRadio;
+using ::android::fuzzService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    const VirtualRadio& amFmRadioMock = VirtualRadio::getAmFmRadio();
+    std::shared_ptr<BroadcastRadio> amFmRadio =
+            ::ndk::SharedRefBase::make<BroadcastRadio>(amFmRadioMock);
+    const VirtualRadio& dabRadioMock = VirtualRadio::getDabRadio();
+    std::shared_ptr<BroadcastRadio> dabRadio =
+            ::ndk::SharedRefBase::make<BroadcastRadio>(dabRadioMock);
+
+    std::vector<ndk::SpAIBinder> binder_services = {amFmRadio->asBinder(), dabRadio->asBinder()};
+
+    fuzzService(binder_services, FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/broadcastradio/common/OWNERS b/broadcastradio/common/OWNERS
deleted file mode 100644
index 259b91e..0000000
--- a/broadcastradio/common/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Automotive team
-xuweilin@google.com
-oscarazu@google.com
-ericjeong@google.com
-keunyoung@google.com
diff --git a/broadcastradio/common/utilsaidl/Utils.cpp b/broadcastradio/common/utilsaidl/Utils.cpp
index 0551bad..de4f529 100644
--- a/broadcastradio/common/utilsaidl/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/Utils.cpp
@@ -204,7 +204,7 @@
 }
 
 bool isValid(const ProgramIdentifier& id) {
-    int64_t val = id.value;
+    uint64_t val = static_cast<uint64_t>(id.value);
     bool valid = true;
 
     auto expect = [&valid](bool condition, const string& message) {
@@ -231,11 +231,11 @@
             expect(val <= 0xFFFFu, "16bit id");
             break;
         case IdentifierType::HD_STATION_ID_EXT: {
-            int64_t stationId = val & 0xFFFFFFFF;  // 32bit
+            uint64_t stationId = val & 0xFFFFFFFF;  // 32bit
             val >>= 32;
-            int64_t subchannel = val & 0xF;  // 4bit
+            uint64_t subchannel = val & 0xF;  // 4bit
             val >>= 4;
-            int64_t freq = val & 0x3FFFF;  // 18bit
+            uint64_t freq = val & 0x3FFFF;  // 18bit
             expect(stationId != 0u, "HD station id != 0");
             expect(subchannel < 8u, "HD subch < 8");
             expect(freq > 100u, "f > 100kHz");
@@ -252,9 +252,9 @@
             break;
         }
         case IdentifierType::DAB_SID_EXT: {
-            int64_t sid = val & 0xFFFFFFFF;  // 32bit
+            uint64_t sid = val & 0xFFFFFFFF;  // 32bit
             val >>= 32;
-            int64_t ecc = val & 0xFF;  // 8bit
+            uint64_t ecc = val & 0xFF;  // 8bit
             expect(sid != 0u, "DAB SId != 0");
             expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1");
             break;
@@ -305,19 +305,19 @@
     return {type, value};
 }
 
-ProgramSelector makeSelectorAmfm(int32_t frequency) {
+ProgramSelector makeSelectorAmfm(uint32_t frequency) {
     ProgramSelector sel = {};
     sel.primaryId = makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, frequency);
     return sel;
 }
 
-ProgramSelector makeSelectorDab(int64_t sidExt) {
+ProgramSelector makeSelectorDab(uint64_t sidExt) {
     ProgramSelector sel = {};
     sel.primaryId = makeIdentifier(IdentifierType::DAB_SID_EXT, sidExt);
     return sel;
 }
 
-ProgramSelector makeSelectorDab(int64_t sidExt, int32_t ensemble, int64_t freq) {
+ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq) {
     ProgramSelector sel = {};
     sel.primaryId = makeIdentifier(IdentifierType::DAB_SID_EXT, sidExt);
     vector<ProgramIdentifier> secondaryIds = {
diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
index ad075f2..ee85a17 100644
--- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
+++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
@@ -137,9 +137,9 @@
 bool isValid(const ProgramSelector& sel);
 
 ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value);
-ProgramSelector makeSelectorAmfm(int32_t frequency);
-ProgramSelector makeSelectorDab(int64_t sidExt);
-ProgramSelector makeSelectorDab(int64_t sidExt, int32_t ensemble, int64_t freq);
+ProgramSelector makeSelectorAmfm(uint32_t frequency);
+ProgramSelector makeSelectorDab(uint64_t sidExt);
+ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq);
 
 bool satisfies(const ProgramFilter& filter, const ProgramSelector& sel);
 
diff --git a/camera/common/default/CameraMetadata.cpp b/camera/common/default/CameraMetadata.cpp
index ed56261..3252e3c 100644
--- a/camera/common/default/CameraMetadata.cpp
+++ b/camera/common/default/CameraMetadata.cpp
@@ -258,7 +258,7 @@
         return res;
     }
     // string.size() doesn't count the null termination character.
-    return updateImpl(tag, (const void*)string.string(), string.size() + 1);
+    return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
 }
 
 status_t CameraMetadata::update(const camera_metadata_ro_entry& entry) {
@@ -455,7 +455,7 @@
     for (size_t i = 0; i < totalSectionCount; ++i) {
         const char* str = (i < ANDROID_SECTION_COUNT)
                                   ? camera_metadata_section_names[i]
-                                  : (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
+                                  : (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
 
         ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
 
diff --git a/camera/common/default/CameraParameters.cpp b/camera/common/default/CameraParameters.cpp
index 37e28a2..3689c90 100644
--- a/camera/common/default/CameraParameters.cpp
+++ b/camera/common/default/CameraParameters.cpp
@@ -204,7 +204,7 @@
 }
 
 void CameraParameters::unflatten(const String8& params) {
-    const char* a = params.string();
+    const char* a = params.c_str();
     const char* b;
 
     mMap.clear();
@@ -263,7 +263,7 @@
 const char* CameraParameters::get(const char* key) const {
     String8 v = mMap.valueFor(String8(key));
     if (v.length() == 0) return 0;
-    return v.string();
+    return v.c_str();
 }
 
 int CameraParameters::getInt(const char* key) const {
@@ -429,7 +429,7 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        ALOGD("%s: %s\n", k.string(), v.string());
+        ALOGD("%s: %s\n", k.c_str(), v.c_str());
     }
 }
 
@@ -443,10 +443,10 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+        snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
         result.append(buffer);
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/camera/common/default/VendorTagDescriptor.cpp b/camera/common/default/VendorTagDescriptor.cpp
index 1282bd0..fba9caa 100644
--- a/camera/common/default/VendorTagDescriptor.cpp
+++ b/camera/common/default/VendorTagDescriptor.cpp
@@ -97,7 +97,7 @@
     if (index < 0) {
         return VENDOR_SECTION_NAME_ERR;
     }
-    return mSections[mTagToSectionMap.valueAt(index)].string();
+    return mSections[mTagToSectionMap.valueAt(index)].c_str();
 }
 
 ssize_t VendorTagDescriptor::getSectionIndex(uint32_t tag) const {
@@ -109,7 +109,7 @@
     if (index < 0) {
         return VENDOR_TAG_NAME_ERR;
     }
-    return mTagToNameMap.valueAt(index).string();
+    return mTagToNameMap.valueAt(index).c_str();
 }
 
 int VendorTagDescriptor::getTagType(uint32_t tag) const {
@@ -128,13 +128,13 @@
                                         /*out*/ uint32_t* tag) const {
     ssize_t index = mReverseMapping.indexOfKey(section);
     if (index < 0) {
-        ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.string());
+        ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.c_str());
         return BAD_VALUE;
     }
 
     ssize_t nameIndex = mReverseMapping[index]->indexOfKey(name);
     if (nameIndex < 0) {
-        ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.string());
+        ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.c_str());
         return BAD_VALUE;
     }
 
@@ -167,7 +167,7 @@
         const char* typeName =
                 (type >= 0 && type < NUM_TYPES) ? camera_metadata_type_names[type] : "UNKNOWN";
         dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2, "",
-                tag, name.string(), type, typeName, sectionName.string());
+                tag, name.c_str(), type, typeName, sectionName.c_str());
     }
 }
 
diff --git a/camera/device/default/Android.bp b/camera/device/default/Android.bp
index b577597..b9f10d6 100644
--- a/camera/device/default/Android.bp
+++ b/camera/device/default/Android.bp
@@ -25,7 +25,10 @@
 
 cc_library_shared {
     name: "camera.device-external-impl",
-    defaults: ["hidl_defaults"],
+    defaults: [
+        "android.hardware.graphics.common-ndk_shared",
+        "hidl_defaults",
+    ],
     proprietary: true,
     srcs: [
         "ExternalCameraDevice.cpp",
@@ -38,7 +41,6 @@
         "android.hardware.camera.common-V1-ndk",
         "android.hardware.camera.device-V1-ndk",
         "android.hardware.graphics.allocator-V1-ndk",
-        "android.hardware.graphics.common-V4-ndk",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index c962974..95a36f0 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -224,10 +224,6 @@
 }
 
 void ExternalCameraDeviceSession::closeOutputThread() {
-    closeOutputThreadImpl();
-}
-
-void ExternalCameraDeviceSession::closeOutputThreadImpl() {
     if (mOutputThread != nullptr) {
         mOutputThread->flush();
         mOutputThread->requestExitAndWait();
@@ -235,6 +231,13 @@
     }
 }
 
+void ExternalCameraDeviceSession::closeBufferRequestThread() {
+    if (mBufferRequestThread != nullptr) {
+        mBufferRequestThread->requestExitAndWait();
+        mBufferRequestThread.reset();
+    }
+}
+
 Status ExternalCameraDeviceSession::initStatus() const {
     Mutex::Autolock _l(mLock);
     Status status = Status::OK;
@@ -248,7 +251,7 @@
 ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
     if (!isClosed()) {
         ALOGE("ExternalCameraDeviceSession deleted before close!");
-        close(/*callerIsDtor*/ true);
+        closeImpl();
     }
 }
 
@@ -1411,19 +1414,16 @@
 }
 
 ScopedAStatus ExternalCameraDeviceSession::close() {
-    close(false);
+    closeImpl();
     return fromStatus(Status::OK);
 }
 
-void ExternalCameraDeviceSession::close(bool callerIsDtor) {
+void ExternalCameraDeviceSession::closeImpl() {
     Mutex::Autolock _il(mInterfaceLock);
     bool closed = isClosed();
     if (!closed) {
-        if (callerIsDtor) {
-            closeOutputThreadImpl();
-        } else {
-            closeOutputThread();
-        }
+        closeOutputThread();
+        closeBufferRequestThread();
 
         Mutex::Autolock _l(mLock);
         // free all buffers
diff --git a/camera/device/default/ExternalCameraDeviceSession.h b/camera/device/default/ExternalCameraDeviceSession.h
index e7eb799..836266f 100644
--- a/camera/device/default/ExternalCameraDeviceSession.h
+++ b/camera/device/default/ExternalCameraDeviceSession.h
@@ -240,9 +240,9 @@
     // To init/close different version of output thread
     void initOutputThread();
     void closeOutputThread();
-    void closeOutputThreadImpl();
+    void closeBufferRequestThread();
 
-    void close(bool callerIsDtor);
+    void closeImpl();
     Status initStatus() const;
     status_t initDefaultRequests();
 
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
index 4fc7437..04db7f3 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
@@ -18,15 +18,16 @@
 //#define LOG_NDEBUG 0
 #include <log/log.h>
 
-#include <regex>
-#include <sys/inotify.h>
+#include <cutils/properties.h>
 #include <errno.h>
 #include <linux/videodev2.h>
-#include <cutils/properties.h>
-#include "ExternalCameraProviderImpl_2_4.h"
+#include <sys/inotify.h>
+#include <regex>
+#include <string>
 #include "ExternalCameraDevice_3_4.h"
 #include "ExternalCameraDevice_3_5.h"
 #include "ExternalCameraDevice_3_6.h"
+#include "ExternalCameraProviderImpl_2_4.h"
 
 namespace android {
 namespace hardware {
@@ -41,10 +42,10 @@
 // "device@<version>/external/<id>"
 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
 const int kMaxDevicePathLen = 256;
-const char* kDevicePath = "/dev/";
-constexpr char kPrefix[] = "video";
-constexpr int kPrefixLen = sizeof(kPrefix) - 1;
-constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+constexpr const char* kDevicePath = "/dev/";
+constexpr const char* kPrefix = "video";
+constexpr int kPrefixLen = std::char_traits<char>::length(kPrefix);
+constexpr int kDevicePrefixLen = std::char_traits<char>::length(kDevicePath) + kPrefixLen;
 
 bool matchDeviceName(int cameraIdOffset,
                      const hidl_string& deviceName, std::string* deviceVersion,
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
index 7c3b982..69318c7 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
@@ -439,7 +439,7 @@
     }
     mVendorTagSections.resize(numSections);
     for (size_t s = 0; s < numSections; s++) {
-        mVendorTagSections[s].sectionName = (*sectionNames)[s].string();
+        mVendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
         mVendorTagSections[s].tags = tagsBySection[s];
     }
     return true;
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 339a142..c8e683c 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -244,7 +244,7 @@
                          std::string* deviceVersion, std::string* cameraId) {
         ::android::String8 pattern;
         pattern.appendFormat(kDeviceNameRE, providerType.c_str());
-        std::regex e(pattern.string());
+        std::regex e(pattern.c_str());
         std::string deviceNameStd(deviceName.c_str());
         std::smatch sm;
         if (std::regex_match(deviceNameStd, sm, e)) {
@@ -8801,8 +8801,7 @@
 void CameraHidlTest::setParameters(
         const sp<::android::hardware::camera::device::V1_0::ICameraDevice> &device,
         const CameraParameters &cameraParams) {
-    Return<Status> returnStatus = device->setParameters(
-            cameraParams.flatten().string());
+    Return<Status> returnStatus = device->setParameters(cameraParams.flatten().c_str());
     ASSERT_TRUE(returnStatus.isOk());
     ASSERT_EQ(Status::OK, returnStatus);
 }
diff --git a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
index b63e3bb..62ce074 100644
--- a/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
+++ b/camera/provider/2.7/default/ExternalCameraProviderImpl_2_7.cpp
@@ -23,6 +23,7 @@
 #include <linux/videodev2.h>
 #include <sys/inotify.h>
 #include <regex>
+#include <string>
 #include "ExternalCameraDevice_3_4.h"
 #include "ExternalCameraDevice_3_5.h"
 #include "ExternalCameraDevice_3_6.h"
@@ -39,10 +40,10 @@
 // "device@<version>/external/<id>"
 const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
 const int kMaxDevicePathLen = 256;
-const char* kDevicePath = "/dev/";
-constexpr char kPrefix[] = "video";
-constexpr int kPrefixLen = sizeof(kPrefix) - 1;
-constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
+constexpr const char* kDevicePath = "/dev/";
+constexpr const char* kPrefix = "video";
+constexpr int kPrefixLen = std::char_traits<char>::length(kPrefix);
+constexpr int kDevicePrefixLen = std::char_traits<char>::length(kDevicePath) + kPrefixLen;
 
 bool matchDeviceName(int cameraIdOffset, const hidl_string& deviceName, std::string* deviceVersion,
                      std::string* cameraDevicePath) {
diff --git a/camera/provider/aidl/vts/Android.bp b/camera/provider/aidl/vts/Android.bp
index 8429b21..59f6c66 100644
--- a/camera/provider/aidl/vts/Android.bp
+++ b/camera/provider/aidl/vts/Android.bp
@@ -68,6 +68,16 @@
         "libgralloctypes",
         "libaidlcommonsupport",
     ],
+
+    require_root: true,
+    test_options: {
+        test_runner_options: [
+            {
+                name: "native-test-timeout",
+                value: "1800000",
+            },
+        ],
+    },
     test_suites: [
         "general-tests",
         "vts",
diff --git a/cas/1.0/default/CasImpl.cpp b/cas/1.0/default/CasImpl.cpp
index 178020e..98e7593 100644
--- a/cas/1.0/default/CasImpl.cpp
+++ b/cas/1.0/default/CasImpl.cpp
@@ -103,8 +103,7 @@
 
 Return<Status> CasImpl::setSessionPrivateData(
         const HidlCasSessionId &sessionId, const HidlCasData& pvtData) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__,
-            sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -113,8 +112,7 @@
 }
 
 Return<Status> CasImpl::closeSession(const HidlCasSessionId &sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__,
-            sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -124,8 +122,7 @@
 
 Return<Status> CasImpl::processEcm(
         const HidlCasSessionId &sessionId, const HidlCasData& ecm) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__,
-            sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
index f79b32d..6b730eb 100644
--- a/cas/1.0/default/DescramblerImpl.cpp
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -62,8 +62,7 @@
 }
 
 Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__,
-            sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
 
     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h
index 45e515a..3d49d9e 100644
--- a/cas/1.0/default/FactoryLoader.h
+++ b/cas/1.0/default/FactoryLoader.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
 #define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
 
+#include <android-base/strings.h>
 #include <dirent.h>
 #include <dlfcn.h>
 #include "SharedLibrary.h"
@@ -98,17 +99,17 @@
     String8 dirPath("/vendor/lib/mediacas");
 #endif
 
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             if (loadFactoryForSchemeFromPath(
                     pluginPath, CA_system_id, library, factory)) {
                 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
@@ -138,10 +139,10 @@
     String8 dirPath("/vendor/lib/mediacas");
 #endif
 
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
@@ -150,7 +151,7 @@
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             queryPluginsFromPath(pluginPath, results);
         }
     }
diff --git a/cas/1.0/default/SharedLibrary.cpp b/cas/1.0/default/SharedLibrary.cpp
index 9c7f385..90c84b8 100644
--- a/cas/1.0/default/SharedLibrary.cpp
+++ b/cas/1.0/default/SharedLibrary.cpp
@@ -29,7 +29,7 @@
 namespace implementation {
 
 SharedLibrary::SharedLibrary(const String8 &path) {
-    mLibHandle = dlopen(path.string(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
diff --git a/cas/1.0/default/TypeConvert.cpp b/cas/1.0/default/TypeConvert.cpp
index cd0efdb..cc25cf5 100644
--- a/cas/1.0/default/TypeConvert.cpp
+++ b/cas/1.0/default/TypeConvert.cpp
@@ -82,7 +82,7 @@
     for (size_t i = 0; i < sessionId.size(); i++) {
         result.appendFormat("%02x ", sessionId[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
index 622ee8f..1a08ebc 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
@@ -5,5 +5,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
index 5df4825..a65160a 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/vts/functional/OWNERS b/cas/1.0/vts/functional/OWNERS
deleted file mode 100644
index 7d8c2ee..0000000
--- a/cas/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 1344
-include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.1/default/CasImpl.cpp b/cas/1.1/default/CasImpl.cpp
index 4cc6017..105e036 100644
--- a/cas/1.1/default/CasImpl.cpp
+++ b/cas/1.1/default/CasImpl.cpp
@@ -125,7 +125,7 @@
 
 Return<Status> CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId,
                                               const HidlCasData& pvtData) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -134,7 +134,7 @@
 }
 
 Return<Status> CasImpl::closeSession(const HidlCasSessionId& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -143,7 +143,7 @@
 }
 
 Return<Status> CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp
index 309cd3c..9d2ead7 100644
--- a/cas/1.1/default/DescramblerImpl.cpp
+++ b/cas/1.1/default/DescramblerImpl.cpp
@@ -59,7 +59,7 @@
 }
 
 Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
 
     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h
index 121f90c..a575df6 100644
--- a/cas/1.1/default/FactoryLoader.h
+++ b/cas/1.1/default/FactoryLoader.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_
 #define ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_
 
+#include <android-base/strings.h>
 #include <dirent.h>
 #include <dlfcn.h>
 #include <media/cas/CasAPI.h>
@@ -90,17 +91,17 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
                 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
                 closedir(pDir);
@@ -127,10 +128,10 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
@@ -139,7 +140,7 @@
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             queryPluginsFromPath(pluginPath, results);
         }
     }
diff --git a/cas/1.1/default/SharedLibrary.cpp b/cas/1.1/default/SharedLibrary.cpp
index ffe4bb9..ac5dbcf 100644
--- a/cas/1.1/default/SharedLibrary.cpp
+++ b/cas/1.1/default/SharedLibrary.cpp
@@ -29,7 +29,7 @@
 namespace implementation {
 
 SharedLibrary::SharedLibrary(const String8& path) {
-    mLibHandle = dlopen(path.string(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
diff --git a/cas/1.1/default/TypeConvert.cpp b/cas/1.1/default/TypeConvert.cpp
index 09ef41a..2ffc79a 100644
--- a/cas/1.1/default/TypeConvert.cpp
+++ b/cas/1.1/default/TypeConvert.cpp
@@ -81,7 +81,7 @@
     for (size_t i = 0; i < sessionId.size(); i++) {
         result.appendFormat("%02x ", sessionId[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
index 0721dc3..9fca8fd 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
@@ -6,5 +6,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc
index 132d943..19fd031 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/vts/functional/OWNERS b/cas/1.1/vts/functional/OWNERS
deleted file mode 100644
index 7d8c2ee..0000000
--- a/cas/1.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 1344
-include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.2/default/CasImpl.cpp b/cas/1.2/default/CasImpl.cpp
index 46dd251..b1038bc 100644
--- a/cas/1.2/default/CasImpl.cpp
+++ b/cas/1.2/default/CasImpl.cpp
@@ -174,7 +174,7 @@
 
 Return<Status> CasImpl::setSessionPrivateData(const HidlCasSessionId& sessionId,
                                               const HidlCasData& pvtData) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -183,7 +183,7 @@
 }
 
 Return<Status> CasImpl::closeSession(const HidlCasSessionId& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -192,7 +192,7 @@
 }
 
 Return<Status> CasImpl::processEcm(const HidlCasSessionId& sessionId, const HidlCasData& ecm) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     std::shared_ptr<CasPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
diff --git a/cas/1.2/default/DescramblerImpl.cpp b/cas/1.2/default/DescramblerImpl.cpp
index 309cd3c..9d2ead7 100644
--- a/cas/1.2/default/DescramblerImpl.cpp
+++ b/cas/1.2/default/DescramblerImpl.cpp
@@ -59,7 +59,7 @@
 }
 
 Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
 
     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
diff --git a/cas/1.2/default/FactoryLoader.h b/cas/1.2/default/FactoryLoader.h
index a374b31..0b05bfc 100644
--- a/cas/1.2/default/FactoryLoader.h
+++ b/cas/1.2/default/FactoryLoader.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_
 #define ANDROID_HARDWARE_CAS_V1_1_FACTORY_LOADER_H_
 
+#include <android-base/strings.h>
 #include <dirent.h>
 #include <dlfcn.h>
 #include <media/cas/CasAPI.h>
@@ -90,17 +91,17 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
                 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
                 closedir(pDir);
@@ -127,10 +128,10 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
@@ -139,7 +140,7 @@
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             queryPluginsFromPath(pluginPath, results);
         }
     }
diff --git a/cas/1.2/default/SharedLibrary.cpp b/cas/1.2/default/SharedLibrary.cpp
index ffe4bb9..ac5dbcf 100644
--- a/cas/1.2/default/SharedLibrary.cpp
+++ b/cas/1.2/default/SharedLibrary.cpp
@@ -29,7 +29,7 @@
 namespace implementation {
 
 SharedLibrary::SharedLibrary(const String8& path) {
-    mLibHandle = dlopen(path.string(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
diff --git a/cas/1.2/default/TypeConvert.cpp b/cas/1.2/default/TypeConvert.cpp
index c4bd0dd..7d27fa1 100644
--- a/cas/1.2/default/TypeConvert.cpp
+++ b/cas/1.2/default/TypeConvert.cpp
@@ -108,7 +108,7 @@
     for (size_t i = 0; i < sessionId.size(); i++) {
         result.appendFormat("%02x ", sessionId[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
index d91fdce..8c2a894 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
@@ -7,5 +7,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service.rc b/cas/1.2/default/android.hardware.cas@1.2-service.rc
index b22971a..4b638bc 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/vts/functional/OWNERS b/cas/1.2/vts/functional/OWNERS
deleted file mode 100644
index 4c55752..0000000
--- a/cas/1.2/vts/functional/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1344
-quxiangfang@google.com
-hgchen@google.com
diff --git a/cas/OWNERS b/cas/OWNERS
index 473c8f26..f6c60aa 100644
--- a/cas/OWNERS
+++ b/cas/OWNERS
@@ -1 +1,4 @@
-include /tv/input/OWNERS
+# Bug component: 1344
+
+hgchen@google.com
+quxiangfang@google.com
\ No newline at end of file
diff --git a/cas/aidl/OWNERS b/cas/aidl/OWNERS
deleted file mode 100755
index 4c55752..0000000
--- a/cas/aidl/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1344
-quxiangfang@google.com
-hgchen@google.com
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
old mode 100755
new mode 100644
index 3c16d57..576016e
--- a/cas/aidl/default/Android.bp
+++ b/cas/aidl/default/Android.bp
@@ -21,6 +21,7 @@
 
     shared_libs: [
         "android.hardware.cas-V1-ndk",
+        "libbase",
         "libbinder_ndk",
         "liblog",
         "libutils",
@@ -48,6 +49,7 @@
     ],
     shared_libs: [
         "android.hardware.cas-V1-ndk",
+        "libbase",
         "libbinder_ndk",
         "liblog",
         "libutils",
@@ -68,6 +70,7 @@
     defaults: ["cas_service_example_defaults"],
     init_rc: ["cas-default-lazy.rc"],
     cflags: ["-DLAZY_SERVICE"],
+    overrides: ["android.hardware.cas-service.example"],
 }
 
 cc_fuzz {
diff --git a/cas/aidl/default/CasImpl.cpp b/cas/aidl/default/CasImpl.cpp
old mode 100755
new mode 100644
index f08fcc0..9885e16
--- a/cas/aidl/default/CasImpl.cpp
+++ b/cas/aidl/default/CasImpl.cpp
@@ -158,7 +158,7 @@
 
 ScopedAStatus CasImpl::setSessionPrivateData(const vector<uint8_t>& sessionId,
                                              const vector<uint8_t>& pvtData) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -167,7 +167,7 @@
 }
 
 ScopedAStatus CasImpl::closeSession(const vector<uint8_t>& sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
@@ -176,7 +176,7 @@
 }
 
 ScopedAStatus CasImpl::processEcm(const vector<uint8_t>& sessionId, const vector<uint8_t>& ecm) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
     shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
         return toStatus(INVALID_OPERATION);
diff --git a/cas/aidl/default/CasImpl.h b/cas/aidl/default/CasImpl.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/DescramblerImpl.cpp b/cas/aidl/default/DescramblerImpl.cpp
old mode 100755
new mode 100644
index a96fd46..d658887
--- a/cas/aidl/default/DescramblerImpl.cpp
+++ b/cas/aidl/default/DescramblerImpl.cpp
@@ -54,7 +54,7 @@
 }
 
 ScopedAStatus DescramblerImpl::setMediaCasSession(const vector<uint8_t>& in_sessionId) {
-    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(in_sessionId).string());
+    ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(in_sessionId).c_str());
 
     shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
     if (holder.get() == nullptr) {
diff --git a/cas/aidl/default/DescramblerImpl.h b/cas/aidl/default/DescramblerImpl.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/FactoryLoader.h b/cas/aidl/default/FactoryLoader.h
old mode 100755
new mode 100644
index 6a562f6..bc3d715
--- a/cas/aidl/default/FactoryLoader.h
+++ b/cas/aidl/default/FactoryLoader.h
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/strings.h>
 #include <dirent.h>
 #include <dlfcn.h>
 #include <media/cas/CasAPI.h>
@@ -86,17 +87,17 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
                 mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
                 closedir(pDir);
@@ -123,10 +124,10 @@
 #else
     String8 dirPath("/vendor/lib/mediacas");
 #endif
-    DIR* pDir = opendir(dirPath.string());
+    DIR* pDir = opendir(dirPath.c_str());
 
     if (pDir == NULL) {
-        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        ALOGE("Failed to open plugin directory %s", dirPath.c_str());
         return false;
     }
 
@@ -135,7 +136,7 @@
     struct dirent* pEntry;
     while ((pEntry = readdir(pDir))) {
         String8 pluginPath = dirPath + "/" + pEntry->d_name;
-        if (pluginPath.getPathExtension() == ".so") {
+        if (base::EndsWith(pluginPath.c_str(), ".so")) {
             queryPluginsFromPath(pluginPath, results);
         }
     }
diff --git a/cas/aidl/default/MediaCasService.cpp b/cas/aidl/default/MediaCasService.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/MediaCasService.h b/cas/aidl/default/MediaCasService.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/SharedLibrary.cpp b/cas/aidl/default/SharedLibrary.cpp
old mode 100755
new mode 100644
index e79f383..c12d17d
--- a/cas/aidl/default/SharedLibrary.cpp
+++ b/cas/aidl/default/SharedLibrary.cpp
@@ -26,7 +26,7 @@
 namespace cas {
 
 SharedLibrary::SharedLibrary(const String8& path) {
-    mLibHandle = dlopen(path.string(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
diff --git a/cas/aidl/default/SharedLibrary.h b/cas/aidl/default/SharedLibrary.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/TypeConvert.cpp b/cas/aidl/default/TypeConvert.cpp
old mode 100755
new mode 100644
index 4f7005f..1f0a46d
--- a/cas/aidl/default/TypeConvert.cpp
+++ b/cas/aidl/default/TypeConvert.cpp
@@ -98,7 +98,7 @@
     for (auto it = sessionId.begin(); it != sessionId.end(); it++) {
         result.appendFormat("%02x ", *it);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
diff --git a/cas/aidl/default/TypeConvert.h b/cas/aidl/default/TypeConvert.h
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/android.hardware.cas-service.xml b/cas/aidl/default/android.hardware.cas-service.xml
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/cas-default-lazy.rc b/cas/aidl/default/cas-default-lazy.rc
old mode 100755
new mode 100644
index 60b59ca..7321cf0
--- a/cas/aidl/default/cas-default-lazy.rc
+++ b/cas/aidl/default/cas-default-lazy.rc
@@ -3,6 +3,7 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
     oneshot
diff --git a/cas/aidl/default/cas-default.rc b/cas/aidl/default/cas-default.rc
old mode 100755
new mode 100644
index e00b9c5..5a60368
--- a/cas/aidl/default/cas-default.rc
+++ b/cas/aidl/default/cas-default.rc
@@ -3,5 +3,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/aidl/default/fuzzer.cpp b/cas/aidl/default/fuzzer.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/default/service.cpp b/cas/aidl/default/service.cpp
old mode 100755
new mode 100644
diff --git a/cas/aidl/vts/functional/OWNERS b/cas/aidl/vts/functional/OWNERS
deleted file mode 100644
index 4c55752..0000000
--- a/cas/aidl/vts/functional/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1344
-quxiangfang@google.com
-hgchen@google.com
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 93b5380..712f28a 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -31,6 +31,7 @@
         "kernel_config_q_4.14",
         "kernel_config_q_4.19",
     ],
+    core_hals: "only",
 }
 
 vintf_compatibility_matrix {
@@ -44,6 +45,7 @@
         "kernel_config_r_4.19",
         "kernel_config_r_5.4",
     ],
+    core_hals: "only",
 }
 
 vintf_compatibility_matrix {
@@ -57,6 +59,7 @@
         "kernel_config_s_5.4",
         "kernel_config_s_5.10",
     ],
+    core_hals: "only",
 }
 
 vintf_compatibility_matrix {
@@ -69,6 +72,7 @@
         "kernel_config_t_5.10",
         "kernel_config_t_5.15",
     ],
+    core_hals: "only",
 }
 
 vintf_compatibility_matrix {
@@ -81,4 +85,18 @@
         "kernel_config_u_5.15",
         "kernel_config_u_6.1",
     ],
+    core_hals: "only",
+}
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.9.xml",
+    stem: "compatibility_matrix.9.xml",
+    srcs: [
+        "compatibility_matrix.9.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_v_5.15",
+        "kernel_config_v_6.1",
+    ],
+    core_hals: "only",
 }
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6e4c419..f1dd956 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -105,6 +105,13 @@
     framework_compatibility_matrix.8.xml \
     framework_compatibility_matrix.device.xml \
 
+# Only allow the use of the unreleased compatibility matrix when we can use unfrozen
+# interfaces (in the `next` release configuration).
+ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
+my_system_matrix_deps += \
+    framework_compatibility_matrix.9.xml
+endif
+
 my_framework_matrix_deps += \
     $(my_system_matrix_deps)
 
diff --git a/compatibility_matrices/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
index c72cbde..4f342b2 100644
--- a/compatibility_matrices/build/vintf_compatibility_matrix.go
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -35,10 +35,10 @@
 	pctx = android.NewPackageContext("android/vintf")
 
 	assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
-		Command:     `${assembleVintfCmd} -i ${inputs} -o ${out}`,
+		Command:     `${assembleVintfCmd} -i ${inputs} -o ${out} ${extraParams}`,
 		CommandDeps: []string{"${assembleVintfCmd}"},
 		Description: "assemble_vintf -i ${inputs}",
-	}, "inputs")
+	}, "inputs", "extraParams")
 
 	xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
 		Command:     `$XmlLintCmd --quiet --schema $xsd $in > /dev/null && touch -a $out`,
@@ -64,6 +64,13 @@
 
 	// list of kernel_config modules to be combined to final output
 	Kernel_configs []string
+
+	// Default is "default" for compatibility matrices on /vendor
+	// and /odm, and "disallow" for compatibility matrices on /system,
+	// /product, and /system_ext.
+	// If value is "only", only android.* HALs are allowed. If value
+	// is "disallow", none of android.* HALs are allowed.
+	Core_hals *string
 }
 
 type vintfCompatibilityMatrixRule struct {
@@ -166,7 +173,8 @@
 		Implicits:   inputPaths,
 		Output:      g.genFile,
 		Args: map[string]string{
-			"inputs": strings.Join(inputPaths.Strings(), ":"),
+			"inputs":      strings.Join(inputPaths.Strings(), ":"),
+			"extraParams": strings.Join(g.getExtraParams(), " "),
 		},
 	})
 	g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
@@ -191,3 +199,23 @@
 		},
 	}
 }
+
+// Return extra parameters to assemble_vintf.
+func (g *vintfCompatibilityMatrixRule) getExtraParams() []string {
+	var extraParams []string
+
+	coreHalsStrategy := proptools.StringDefault(
+		g.properties.Core_hals,
+		g.defaultCoreHalsStrategy(),
+	)
+	extraParams = append(extraParams, "--core-hals", proptools.ShellEscape(coreHalsStrategy))
+	return extraParams
+}
+
+func (g *vintfCompatibilityMatrixRule) defaultCoreHalsStrategy() string {
+	// TODO(b/290408770): default to "disallow" for FCMs
+
+	// For Device (vendor, odm) compatibility matrix, default is
+	// to not check anything.
+	return "default"
+}
diff --git a/compatibility_matrices/bump.py b/compatibility_matrices/bump.py
new file mode 100755
index 0000000..88b7a42
--- /dev/null
+++ b/compatibility_matrices/bump.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 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.
+#
+"""
+Creates the next compatibility matrix.
+
+Requires libvintf Level.h to be updated before executing this script.
+"""
+
+import argparse
+import os
+import pathlib
+import shutil
+import subprocess
+import textwrap
+
+
+def check_call(*args, **kwargs):
+    print(args)
+    subprocess.check_call(*args, **kwargs)
+
+
+def check_output(*args, **kwargs):
+    print(args)
+    return subprocess.check_output(*args, **kwargs)
+
+
+class Bump(object):
+
+    def __init__(self, cmdline_args):
+        self.top = pathlib.Path(os.environ["ANDROID_BUILD_TOP"])
+        self.interfaces_dir = self.top / "hardware/interfaces"
+
+        self.current_level = cmdline_args.current
+        self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
+        self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
+
+        self.next_level = cmdline_args.next
+        self.next_module_name = f"framework_compatibility_matrix.{self.next_level}.xml"
+        self.next_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.next_level}.xml"
+
+        self.level_to_letter = self.get_level_to_letter_mapping()
+        print("Found level mapping in libvintf Level.h:", self.level_to_letter)
+
+    def run(self):
+        self.bump_kernel_configs()
+        self.copy_matrix()
+        self.edit_android_bp()
+        self.edit_android_mk()
+
+    def get_level_to_letter_mapping(self):
+        levels_file = self.top / "system/libvintf/include/vintf/Level.h"
+        with open(levels_file) as f:
+            lines = f.readlines()
+            pairs = [
+                line.split("=", maxsplit=2) for line in lines if "=" in line
+            ]
+            return {
+                level.strip().removesuffix(","): letter.strip()
+                for letter, level in pairs
+            }
+
+    def bump_kernel_configs(self):
+        check_call([
+            self.top / "kernel/configs/tools/bump.py",
+            self.level_to_letter[self.current_level].lower(),
+            self.level_to_letter[self.next_level].lower(),
+        ])
+
+    def copy_matrix(self):
+        shutil.copyfile(self.current_xml, self.next_xml)
+
+    def edit_android_bp(self):
+        android_bp = self.interfaces_dir / "compatibility_matrices/Android.bp"
+
+        with open(android_bp, "r+") as f:
+            if self.next_module_name not in f.read():
+                f.seek(0, 2)  # end of file
+                f.write("\n")
+                f.write(
+                    textwrap.dedent(f"""\
+                        vintf_compatibility_matrix {{
+                            name: "{self.next_module_name}",
+                        }}
+                    """))
+
+        next_kernel_configs = check_output(
+            """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""",
+            cwd=self.top / "kernel/configs" /
+            self.level_to_letter[self.next_level].lower(),
+            text=True,
+            shell=True,
+        ).splitlines()
+        print(next_kernel_configs)
+
+        check_call([
+            "bpmodify", "-w", "-m", self.next_module_name, "-property", "stem",
+            "-str", self.next_xml.name, android_bp
+        ])
+
+        check_call([
+            "bpmodify", "-w", "-m", self.next_module_name, "-property", "srcs",
+            "-a",
+            self.next_xml.relative_to(android_bp.parent), android_bp
+        ])
+
+        check_call([
+            "bpmodify", "-w", "-m", self.next_module_name, "-property",
+            "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp
+        ])
+
+    def edit_android_mk(self):
+        android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk"
+        with open(android_mk) as f:
+            if self.next_module_name in f.read():
+                return
+            f.seek(0)
+            lines = f.readlines()
+        current_module_line_number = None
+        for line_number, line in enumerate(lines):
+            if self.current_module_name in line:
+                current_module_line_number = line_number
+                break
+        assert current_module_line_number is not None
+        lines.insert(current_module_line_number + 1,
+                     f"    {self.next_module_name} \\\n")
+        with open(android_mk, "w") as f:
+            f.write("".join(lines))
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument("current",
+                        type=str,
+                        help="VINTF level of the current version (e.g. 9)")
+    parser.add_argument("next",
+                        type=str,
+                        help="VINTF level of the next version (e.g. 10)")
+    cmdline_args = parser.parse_args()
+
+    Bump(cmdline_args).run()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index b9fb3f4..bb7637a 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -281,9 +281,15 @@
         <version>1.0</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.media.omx</name>
@@ -361,6 +367,7 @@
         <interface>
             <name>ISap</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index b374c8c..dad1558 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -319,11 +319,21 @@
         <version>1.0-1</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.media.omx</name>
         <version>1.0</version>
         <interface>
@@ -399,6 +409,7 @@
         <interface>
             <name>ISap</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml
index 40ae655..23f634d 100644
--- a/compatibility_matrices/compatibility_matrix.6.xml
+++ b/compatibility_matrices/compatibility_matrix.6.xml
@@ -368,11 +368,21 @@
         <version>1.0-2</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.media.omx</name>
         <version>1.0</version>
         <interface>
@@ -454,6 +464,7 @@
         <interface>
             <name>ISap</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.7.xml b/compatibility_matrices/compatibility_matrix.7.xml
index bc5a5c4..fe424bd 100644
--- a/compatibility_matrices/compatibility_matrix.7.xml
+++ b/compatibility_matrices/compatibility_matrix.7.xml
@@ -43,6 +43,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.audiocontrol</name>
+        <version>1-2</version>
         <interface>
             <name>IAudioControl</name>
             <instance>default</instance>
@@ -262,22 +263,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <!-- New, non-Go devices should use 4.0 or the AIDL hal. -->
@@ -430,11 +415,21 @@
         <version>1.0-2</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.media.omx</name>
         <version>1.0</version>
         <interface>
@@ -582,6 +577,7 @@
         <interface>
             <name>ISap</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index c04a499..9e3b8f9 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -52,7 +52,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
          <name>android.hardware.authsecret</name>
          <version>1</version>
          <interface>
@@ -114,7 +114,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.biometrics.face</name>
         <version>3</version>
         <interface>
@@ -122,7 +122,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.biometrics.fingerprint</name>
         <version>3</version>
         <interface>
@@ -231,22 +231,6 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <version>1-2</version>
         <interface>
@@ -329,7 +313,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -338,7 +322,7 @@
             <instance>strongbox</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -361,10 +345,20 @@
         <version>1.0-2</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.memtrack</name>
         <version>1</version>
@@ -373,7 +367,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.neuralnetworks</name>
         <version>1-4</version>
         <interface>
@@ -381,7 +375,7 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.nfc</name>
         <interface>
             <name>INfc</name>
@@ -525,7 +519,7 @@
             <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
         <interface>
@@ -533,7 +527,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.sharedsecret</name>
         <version>1</version>
         <interface>
@@ -685,7 +679,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.uwb</name>
         <version>1</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 2f18a38..06ba953 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -1,4 +1,3 @@
-<!-- WARNING: This file is unused in the Android 14 branch. -->
 <compatibility-matrix version="1.0" type="framework" level="9">
     <hal format="hidl" optional="true">
         <name>android.hardware.audio</name>
@@ -53,7 +52,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
          <name>android.hardware.authsecret</name>
          <version>1</version>
          <interface>
@@ -95,7 +94,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.vehicle</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IVehicle</name>
             <instance>default</instance>
@@ -115,15 +114,16 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.biometrics.face</name>
         <version>3</version>
         <interface>
             <name>IFace</name>
             <instance>default</instance>
+            <instance>virtual</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.biometrics.fingerprint</name>
         <version>3</version>
         <interface>
@@ -132,14 +132,6 @@
             <instance>virtual</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.bluetooth</name>
-        <version>1.0-1</version>
-        <interface>
-            <name>IBluetoothHci</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.bluetooth</name>
         <interface>
@@ -194,7 +186,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.contexthub</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IContextHub</name>
             <instance>default</instance>
@@ -225,29 +217,13 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.gnss</name>
-        <version>2-3</version>
+        <version>2-4</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <version>1-2</version>
         <interface>
@@ -257,24 +233,12 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.graphics.composer3</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IComposer</name>
             <instance>default</instance>
         </interface>
     </hal>
-    <!-- Either the native or the HIDL mapper HAL must exist on the device -->
-    <hal format="hidl" optional="true">
-        <name>android.hardware.graphics.mapper</name>
-        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
-        <version>2.1</version>
-        <version>3.0</version>
-        <version>4.0</version>
-        <interface>
-            <name>IMapper</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.health</name>
         <version>1-2</version>
@@ -330,7 +294,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -339,7 +303,7 @@
             <instance>strongbox</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -361,6 +325,25 @@
         <version>1.0-2</version>
         <interface>
             <name>IComponentStore</name>
+            <instance>software</instance>
+            <regex-instance>default[0-9]*</regex-instance>
+            <regex-instance>vendor[0-9]*_software</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1</version>
+        <interface>
+            <name>IComponentStore</name>
             <regex-instance>default[0-9]*</regex-instance>
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
@@ -373,7 +356,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.neuralnetworks</name>
         <version>1-4</version>
         <interface>
@@ -381,7 +364,7 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.nfc</name>
         <interface>
             <name>INfc</name>
@@ -390,7 +373,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.power</name>
-        <version>4</version>
+        <version>5</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -406,7 +389,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
@@ -414,7 +397,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.data</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioData</name>
             <instance>slot1</instance>
@@ -424,7 +407,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.messaging</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioMessaging</name>
             <instance>slot1</instance>
@@ -434,7 +417,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.modem</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioModem</name>
             <instance>slot1</instance>
@@ -444,7 +427,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.network</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioNetwork</name>
             <instance>slot1</instance>
@@ -454,7 +437,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.sim</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioSim</name>
             <instance>slot1</instance>
@@ -474,7 +457,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.voice</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IRadioVoice</name>
             <instance>slot1</instance>
@@ -484,7 +467,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.ims</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>IRadioIms</name>
             <instance>slot1</instance>
@@ -504,20 +487,12 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.radio.ims.media</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>IImsMedia</name>
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.renderscript</name>
-        <version>1.0</version>
-        <interface>
-            <name>IDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.rebootescrow</name>
         <version>1</version>
@@ -535,7 +510,7 @@
             <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
         <interface>
@@ -543,7 +518,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.sharedsecret</name>
         <version>1</version>
         <interface>
@@ -560,14 +535,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.soundtrigger</name>
-        <version>2.3</version>
-        <interface>
-            <name>ISoundTriggerHw</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
          <name>android.hardware.soundtrigger3</name>
          <version>1</version>
@@ -576,22 +543,6 @@
              <instance>default</instance>
          </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.tetheroffload.config</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOffloadConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.tetheroffload.control</name>
-        <version>1.1</version>
-        <interface>
-            <name>IOffloadControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.tetheroffload</name>
         <version>1</version>
@@ -608,6 +559,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true" updatable-via-apex="true">
+        <name>android.hardware.threadnetwork</name>
+        <version>1</version>
+        <interface>
+            <name>IThreadChip</name>
+            <regex-instance>chip[0-9]+</regex-instance>
+        </interface>
+    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.tv.hdmi.cec</name>
         <version>1</version>
@@ -695,7 +654,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.uwb</name>
         <version>1</version>
         <interface>
@@ -719,7 +678,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <!-- Either the native or the HIDL mapper HAL must exist on the device -->
+    <!-- The native mapper HAL must exist on the device -->
     <hal format="native" optional="true">
         <name>mapper</name>
         <version>5.0</version>
@@ -727,12 +686,4 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.threadnetwork</name>
-        <version>1</version>
-        <interface>
-            <name>IThreadChip</name>
-            <regex-instance>chip[0-9]+</regex-instance>
-        </interface>
-    </hal>
 </compatibility-matrix>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 3bc1786..d92c0b9 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <functional>
 #include <string>
 #include <vector>
 
@@ -23,9 +24,7 @@
 namespace android::vintf::details {
 
 // The predicate to VintfObject::checkMissingHalsInMatrices.
-bool ShouldCheckMissingHalsInFcm(const std::string& package) {
-    using std::placeholders::_1;
-
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion) {
     static std::vector<std::string> included_prefixes{
             // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
             // matrix is checked.
@@ -50,29 +49,11 @@
             "android.hardware.media.bufferpool@1.0",
             "android.hardware.media.bufferpool@2.0",
             "android.hardware.radio.config@1.2",
-            // AIDL
-            "android.hardware.audio.common",
-            "android.hardware.audio.core.sounddose",
-            "android.hardware.biometrics.common",
-            "android.hardware.camera.metadata",
-            "android.hardware.camera.device",
-            "android.hardware.camera.common",
-            "android.hardware.common",
-            "android.hardware.common.fmq",
-            "android.hardware.graphics.common",
-            "android.hardware.input.common",
-            "android.hardware.keymaster",
-            "android.hardware.media.bufferpool2",
-            "android.hardware.radio",
-            "android.hardware.threadnetwork",
-            "android.hardware.uwb.fira_android",
 
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
             "android.hardware.fastboot@1.0",
             "android.hardware.fastboot@1.1",
-            // Fastboot AIDL
-            "android.hardware.fastboot",
 
             // Deprecated HALs.
             // HIDL
@@ -103,14 +84,10 @@
             "android.hardware.thermal@1.0",
             "android.hardware.thermal@1.1",
             "android.hardware.wifi.offload@1.0",
-
-            // Under hardware/interfaces/staging, still in development
-            // AIDL
-            "android.hardware.media.c2",
     };
 
     auto package_has_prefix = [&](const std::string& prefix) {
-        return android::base::StartsWith(package, prefix);
+        return android::base::StartsWith(packageAndVersion, prefix);
     };
 
     // Only check packageAndVersions that are in the include list and not in the exclude list.
@@ -118,7 +95,69 @@
         return false;
     }
 
-    if (std::find(excluded_exact.begin(), excluded_exact.end(), package) != excluded_exact.end()) {
+    if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+        excluded_exact.end()) {
+        return false;
+    }
+
+    return !std::any_of(excluded_prefixes.begin(), excluded_prefixes.end(), package_has_prefix);
+}
+
+// The predicate to VintfObject::checkMissingHalsInMatrices.
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion) {
+    static std::vector<std::string> included_prefixes{
+            // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
+            // matrix is checked.
+            "android.hardware.",
+    };
+
+    static std::vector<std::string> excluded_prefixes{
+            // Packages without top level interfaces (including types-only packages) are exempted.
+            "android.hardware.audio.common@",
+            "android.hardware.biometrics.common@",
+            "android.hardware.camera.metadata@",
+            "android.hardware.camera.device@",
+            "android.hardware.camera.common@",
+            "android.hardware.common@",
+            "android.hardware.common.fmq@",
+            "android.hardware.gnss.measurement_corrections@",
+            "android.hardware.gnss.visibility_control@",
+            "android.hardware.graphics.common@",
+            "android.hardware.input.common@",
+            "android.hardware.keymaster@",
+            "android.hardware.media.bufferpool2@",
+            "android.hardware.radio@",
+            "android.hardware.uwb.fira_android@",
+
+            // Test packages are exempted.
+            "android.hardware.tests.",
+
+            // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
+            // does not depend on this HAL, hence it is not declared in any manifests or matrices.
+            "android.hardware.fastboot@",
+    };
+
+    static std::vector<std::string> excluded_exact{
+            // Packages without top level interfaces (including types-only packages) are exempted.
+
+            // AIDL
+            "android.hardware.audio.core.sounddose@1",
+
+            // Deprecated HALs.
+            "android.hardware.bluetooth.audio@1",
+    };
+
+    auto package_has_prefix = [&](const std::string& prefix) {
+        return android::base::StartsWith(packageAndVersion, prefix);
+    };
+
+    // Only check packageAndVersions that are in the include list and not in the exclude list.
+    if (!std::any_of(included_prefixes.begin(), included_prefixes.end(), package_has_prefix)) {
+        return false;
+    }
+
+    if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+        excluded_exact.end()) {
         return false;
     }
 
diff --git a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
index f74c217..e7ef4a0 100644
--- a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
+++ b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
@@ -24,7 +24,8 @@
 // Determine whether VINTF checks |package| is missing from FCMs.
 // |package| can be a HIDL package and version like
 // "android.hardware.foo@1.0", or an AIDL package name like
-// "android.hardware.foo".
-bool ShouldCheckMissingHalsInFcm(const std::string& package);
+// "android.hardware.foo@1".
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion);
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion);
 
 }  // namespace android::vintf::details
diff --git a/configstore/1.0/vts/functional/OWNERS b/configstore/OWNERS
similarity index 97%
rename from configstore/1.0/vts/functional/OWNERS
rename to configstore/OWNERS
index edfa1b0..70ad434 100644
--- a/configstore/1.0/vts/functional/OWNERS
+++ b/configstore/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 24939
+
 lpy@google.com
diff --git a/contexthub/aidl/Android.bp b/contexthub/aidl/Android.bp
index 814bf3b..cf10529 100644
--- a/contexthub/aidl/Android.bp
+++ b/contexthub/aidl/Android.bp
@@ -34,6 +34,9 @@
         ndk: {
             apps_enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
@@ -46,6 +49,6 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
index 6163cfc..d0099ff 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHubCallback.aidl
@@ -39,5 +39,6 @@
   void handleContextHubAsyncEvent(in android.hardware.contexthub.AsyncEventType evt);
   void handleTransactionResult(in int transactionId, in boolean success);
   void handleNanSessionRequest(in android.hardware.contexthub.NanSessionRequest request);
+  byte[16] getUuid();
   const int CONTEXTHUB_NAN_TRANSACTION_TIMEOUT_MS = 10000;
 }
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
index bfcb51e..41fb266 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHubCallback.aidl
@@ -91,6 +91,14 @@
     void handleNanSessionRequest(in NanSessionRequest request);
 
     /**
+     * This callback is passed to the HAL implementation to allow the HAL to request a UUID that
+     * uniquely identifies an IContextHubCallback.
+     *
+     * @return a byte array representating the UUID
+     */
+    byte[16] getUuid();
+
+    /**
      * Amount of time, in milliseconds, that a handleNanSessionRequest can be pending before the
      * Contexthub service must respond.
      */
diff --git a/contexthub/aidl/default/Android.bp b/contexthub/aidl/default/Android.bp
index 6ee7407..74bac69 100644
--- a/contexthub/aidl/default/Android.bp
+++ b/contexthub/aidl/default/Android.bp
@@ -29,7 +29,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.contexthub-V2-ndk",
+        "android.hardware.contexthub-V3-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -50,7 +50,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.contexthub-V2-ndk",
+        "android.hardware.contexthub-V3-ndk",
     ],
     static_libs: [
         "libcontexthubexampleimpl",
diff --git a/contexthub/aidl/default/contexthub-default.xml b/contexthub/aidl/default/contexthub-default.xml
index 930f672..2f8ddc8 100644
--- a/contexthub/aidl/default/contexthub-default.xml
+++ b/contexthub/aidl/default/contexthub-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.contexthub</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IContextHub</name>
             <instance>default</instance>
diff --git a/contexthub/aidl/vts/Android.bp b/contexthub/aidl/vts/Android.bp
index 1534b40..b166baf 100644
--- a/contexthub/aidl/vts/Android.bp
+++ b/contexthub/aidl/vts/Android.bp
@@ -32,7 +32,7 @@
         "libbinder",
     ],
     static_libs: [
-        "android.hardware.contexthub-V2-cpp",
+        "android.hardware.contexthub-V3-cpp",
         "VtsHalContexthubUtils",
     ],
     test_suites: [
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
index c1cc07c..e780857 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -48,6 +48,10 @@
 using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
 using ::android::hardware::contexthub::vts_utils::waitForCallback;
 
+// 6612b522-b717-41c8-b48d-c0b1cc64e142
+const std::array<uint8_t, 16> kUuid = {0x66, 0x12, 0xb5, 0x22, 0xb7, 0x17, 0x41, 0xc8,
+                                       0xb4, 0x8d, 0xc0, 0xb1, 0xcc, 0x64, 0xe1, 0x42};
+
 class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
   public:
     virtual void SetUp() override {
@@ -126,6 +130,11 @@
     Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
         return Status::ok();
     }
+
+    Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
+        *out_uuid = kUuid;
+        return Status::ok();
+    }
 };
 
 TEST_P(ContextHubAidl, TestRegisterCallback) {
@@ -157,6 +166,11 @@
         return Status::ok();
     }
 
+    Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
+        *out_uuid = kUuid;
+        return Status::ok();
+    }
+
     std::promise<std::vector<NanoappInfo>> promise;
 };
 
@@ -223,6 +237,11 @@
         return Status::ok();
     }
 
+    Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
+        *out_uuid = kUuid;
+        return Status::ok();
+    }
+
     uint32_t expectedTransactionId = 0;
     std::promise<bool> promise;
 };
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index cbdab4f..45aba7b 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -134,6 +134,7 @@
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hidl.memory@1.0",
+        "libbase",
         "libcutils",
         "libhidlbase",
         "libhidlmemory",
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index 809f694..dfa5d22 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -98,8 +98,7 @@
                 break;
             }
         }
-        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
-                 defaultUrl.string());
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType, defaultUrl.c_str());
         return Void();
     }
 
@@ -219,7 +218,7 @@
         String8 legacyValue;
         status_t status = mLegacyPlugin->getPropertyString(
                 String8(propertyName.c_str()), legacyValue);
-        _hidl_cb(toStatus(status), legacyValue.string());
+        _hidl_cb(toStatus(status), legacyValue.c_str());
         return Void();
     }
 
diff --git a/drm/1.0/default/OWNERS b/drm/1.0/default/OWNERS
deleted file mode 100644
index ecb421c..0000000
--- a/drm/1.0/default/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-edwinwong@google.com
-fredgc@google.com
-jtinker@google.com
-kylealexander@google.com
-rfrias@google.com
-robertshih@google.com
diff --git a/drm/1.0/default/SharedLibrary.cpp b/drm/1.0/default/SharedLibrary.cpp
index 0a942cd..c9b5389 100644
--- a/drm/1.0/default/SharedLibrary.cpp
+++ b/drm/1.0/default/SharedLibrary.cpp
@@ -26,7 +26,7 @@
 namespace helper {
 
 SharedLibrary::SharedLibrary(const String8& path) {
-    mLibHandle = dlopen(path.string(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
diff --git a/drm/1.0/default/include/PluginLoader.h b/drm/1.0/default/include/PluginLoader.h
index 0c45fb3..5130b16 100644
--- a/drm/1.0/default/include/PluginLoader.h
+++ b/drm/1.0/default/include/PluginLoader.h
@@ -18,6 +18,8 @@
 #define PLUGIN_LOADER_H_
 
 #include "SharedLibrary.h"
+
+#include <android-base/strings.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -39,14 +41,14 @@
          */
         String8 pluginDir(dir);
 
-        DIR* pDir = opendir(pluginDir.string());
+        DIR* pDir = opendir(pluginDir.c_str());
         if (pDir == NULL) {
-            ALOGE("Failed to find plugin directory %s", pluginDir.string());
+            ALOGE("Failed to find plugin directory %s", pluginDir.c_str());
         } else {
             struct dirent* pEntry;
             while ((pEntry = readdir(pDir))) {
                 String8 file(pEntry->d_name);
-                if (file.getPathExtension() == ".so") {
+                if (base::EndsWith(file.c_str(), ".so")) {
                     String8 path = pluginDir + "/" + pEntry->d_name;
                     T *plugin = loadOne(path, entry);
                     if (plugin) {
diff --git a/drm/1.0/vts/OWNERS b/drm/1.0/vts/OWNERS
deleted file mode 100644
index ecb421c..0000000
--- a/drm/1.0/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-edwinwong@google.com
-fredgc@google.com
-jtinker@google.com
-kylealexander@google.com
-rfrias@google.com
-robertshih@google.com
diff --git a/drm/1.0/vts/functional/OWNERS b/drm/1.0/vts/functional/OWNERS
deleted file mode 100644
index 0b13790..0000000
--- a/drm/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 49079
-jtinker@google.com
-robertshih@google.com
-edwinwong@google.com
\ No newline at end of file
diff --git a/drm/1.1/vts/OWNERS b/drm/1.1/vts/OWNERS
deleted file mode 100644
index ecb421c..0000000
--- a/drm/1.1/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-edwinwong@google.com
-fredgc@google.com
-jtinker@google.com
-kylealexander@google.com
-rfrias@google.com
-robertshih@google.com
diff --git a/drm/1.1/vts/functional/OWNERS b/drm/1.1/vts/functional/OWNERS
deleted file mode 100644
index 0b13790..0000000
--- a/drm/1.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 49079
-jtinker@google.com
-robertshih@google.com
-edwinwong@google.com
\ No newline at end of file
diff --git a/drm/1.2/vts/OWNERS b/drm/1.2/vts/OWNERS
deleted file mode 100644
index ecb421c..0000000
--- a/drm/1.2/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-edwinwong@google.com
-fredgc@google.com
-jtinker@google.com
-kylealexander@google.com
-rfrias@google.com
-robertshih@google.com
diff --git a/drm/1.2/vts/functional/OWNERS b/drm/1.2/vts/functional/OWNERS
deleted file mode 100644
index 0b13790..0000000
--- a/drm/1.2/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 49079
-jtinker@google.com
-robertshih@google.com
-edwinwong@google.com
\ No newline at end of file
diff --git a/drm/1.4/vts/OWNERS b/drm/1.4/vts/OWNERS
deleted file mode 100644
index 3a0672e..0000000
--- a/drm/1.4/vts/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-conglin@google.com
-edwinwong@google.com
-fredgc@google.com
-jtinker@google.com
-juce@google.com
-kylealexander@google.com
-rfrias@google.com
-robertshih@google.com
-sigquit@google.com
diff --git a/drm/1.3/vts/OWNERS b/drm/OWNERS
similarity index 62%
rename from drm/1.3/vts/OWNERS
rename to drm/OWNERS
index 3a0672e..c06472a 100644
--- a/drm/1.3/vts/OWNERS
+++ b/drm/OWNERS
@@ -1,9 +1,12 @@
+# Bug component: 49079
+
 conglin@google.com
-edwinwong@google.com
 fredgc@google.com
-jtinker@google.com
 juce@google.com
+kelzhan@google.com
 kylealexander@google.com
+mattfedd@google.com
 rfrias@google.com
 robertshih@google.com
 sigquit@google.com
+vickymin@google.com
diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp
index fb04d84..afcb603 100644
--- a/drm/aidl/Android.bp
+++ b/drm/aidl/Android.bp
@@ -23,7 +23,7 @@
             sdk_version: "module_current",
         },
         ndk: {
-            min_sdk_version: "UpsideDownCake",
+            min_sdk_version: "34",
         },
     },
     double_loadable: true,
diff --git a/drm/aidl/OWNERS b/drm/aidl/OWNERS
index fe69725..e69de29 100644
--- a/drm/aidl/OWNERS
+++ b/drm/aidl/OWNERS
@@ -1,3 +0,0 @@
-# Bug component: 49079
-kelzhan@google.com
-robertshih@google.com
diff --git a/drm/aidl/vts/OWNERS b/drm/aidl/vts/OWNERS
index fe69725..e69de29 100644
--- a/drm/aidl/vts/OWNERS
+++ b/drm/aidl/vts/OWNERS
@@ -1,3 +0,0 @@
-# Bug component: 49079
-kelzhan@google.com
-robertshih@google.com
diff --git a/dumpstate/OWNERS b/dumpstate/OWNERS
new file mode 100644
index 0000000..4c9173e
--- /dev/null
+++ b/dumpstate/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 298624585
+
+include platform/frameworks/native:/cmds/dumpstate/OWNERS
diff --git a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
index c89243b..032f7e2 100644
--- a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
+++ b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
@@ -221,6 +221,47 @@
 }
 
 /**
+ * Ensure that passwords containing a NUL byte aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, PasswordIsBinaryData) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> rightPassword = {'A', 'B', 'C', '\0', 'D', 'E', 'F'};
+    std::vector<uint8_t> wrongPassword = {'A', 'B', 'C', '\0', '\0', '\0', '\0'};
+
+    ALOGI("Testing Enroll+Verify of password with embedded NUL (expected success)");
+    enrollNewPassword(rightPassword, enrollRsp, true);
+    verifyPassword(rightPassword, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing Verify of wrong password (expected failure)");
+    verifyPassword(wrongPassword, enrollRsp.data, 1, verifyRsp, false);
+
+    ALOGI("PasswordIsBinaryData test done");
+}
+
+/**
+ * Ensure that long passwords aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, LongPassword) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> password;
+
+    password.resize(64);  // maximum length used by Android
+    memset(password.data(), 'A', password.size());
+
+    ALOGI("Testing Enroll+Verify of long password (expected success)");
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing Verify of wrong password (expected failure)");
+    password[password.size() - 1] ^= 1;
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+
+    ALOGI("LongPassword test done");
+}
+
+/**
  * Ensure we can securely update password (keep the same
  * secure user_id) if we prove we know old password
  */
diff --git a/gnss/1.0/default/OWNERS b/gnss/1.0/default/OWNERS
deleted file mode 100644
index 6c25bd7..0000000
--- a/gnss/1.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
diff --git a/gnss/1.0/vts/OWNERS b/gnss/1.0/vts/OWNERS
deleted file mode 100644
index 937d70a..0000000
--- a/gnss/1.0/vts/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
-
-# VTS team
-yim@google.com
-trong@google.com
\ No newline at end of file
diff --git a/gnss/1.0/vts/functional/OWNERS b/gnss/1.0/vts/functional/OWNERS
deleted file mode 100644
index b831eb4..0000000
--- a/gnss/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 393449
-yuhany@google.com
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 300e8de..697cb91 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -27,7 +27,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V3-ndk",
+        "android.hardware.gnss-V4-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/1.1/default/OWNERS b/gnss/1.1/default/OWNERS
deleted file mode 100644
index a3d8577..0000000
--- a/gnss/1.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
-yuhany@google.com
diff --git a/gnss/1.1/vts/OWNERS b/gnss/1.1/vts/OWNERS
deleted file mode 100644
index 3ed36da..0000000
--- a/gnss/1.1/vts/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
-yuhany@google.com
-
-# VTS team
-yim@google.com
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index 2414cbc..f9fcbf1 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -36,7 +36,7 @@
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@common-vts-lib",
-        "android.hardware.gnss-V3-cpp",
+        "android.hardware.gnss-V4-cpp",
     ],
     shared_libs: [
         "android.hardware.gnss.measurement_corrections@1.0",
diff --git a/gnss/1.1/vts/functional/OWNERS b/gnss/1.1/vts/functional/OWNERS
deleted file mode 100644
index b831eb4..0000000
--- a/gnss/1.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 393449
-yuhany@google.com
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 83bc2cc..35c2e37 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -50,7 +50,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V3-ndk",
+        "android.hardware.gnss-V4-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.0/default/OWNERS b/gnss/2.0/default/OWNERS
deleted file mode 100644
index 8da956c..0000000
--- a/gnss/2.0/default/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
-yuhany@google.com
-aadmal@google.com
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index e8db886..0b54308 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -39,7 +39,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@2.1",
         "android.hardware.gnss@common-vts-lib",
-        "android.hardware.gnss-V3-cpp",
+        "android.hardware.gnss-V4-cpp",
     ],
     test_suites: [
         "general-tests",
diff --git a/gnss/2.0/vts/functional/OWNERS b/gnss/2.0/vts/functional/OWNERS
deleted file mode 100644
index b831eb4..0000000
--- a/gnss/2.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 393449
-yuhany@google.com
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 4a4ce54..1bb7512 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -44,7 +44,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
-        "android.hardware.gnss-V3-ndk",
+        "android.hardware.gnss-V4-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.1/default/OWNERS b/gnss/2.1/default/OWNERS
deleted file mode 100644
index b7b4a2e..0000000
--- a/gnss/2.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-gomo@google.com
-smalkos@google.com
-wyattriley@google.com
-yuhany@google.com
diff --git a/gnss/2.1/vts/OWNERS b/gnss/2.1/vts/OWNERS
deleted file mode 100644
index b7b4a2e..0000000
--- a/gnss/2.1/vts/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-gomo@google.com
-smalkos@google.com
-wyattriley@google.com
-yuhany@google.com
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index 76f9d07..9906b27 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -40,7 +40,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@2.1",
         "android.hardware.gnss@common-vts-lib",
-        "android.hardware.gnss-V3-cpp",
+        "android.hardware.gnss-V4-cpp",
     ],
     shared_libs: [
         "libvintf",
diff --git a/gnss/2.1/vts/functional/OWNERS b/gnss/2.1/vts/functional/OWNERS
deleted file mode 100644
index b831eb4..0000000
--- a/gnss/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 393449
-yuhany@google.com
diff --git a/gnss/2.0/vts/OWNERS b/gnss/OWNERS
similarity index 68%
rename from gnss/2.0/vts/OWNERS
rename to gnss/OWNERS
index 0a7ce6c..57982e7 100644
--- a/gnss/2.0/vts/OWNERS
+++ b/gnss/OWNERS
@@ -1,8 +1,8 @@
-wyattriley@google.com
+# Bug component: 393449
+
 gomo@google.com
 smalkos@google.com
-yuhany@google.com
-aadmal@google.com
-
-# VTS team
+trong@google.com
+wyattriley@google.com
 yim@google.com
+yuhany@google.com
diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp
index cb2c001..611c7e0 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -52,6 +52,6 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
diff --git a/gnss/aidl/OWNERS b/gnss/aidl/OWNERS
deleted file mode 100644
index b7b4a2e..0000000
--- a/gnss/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-gomo@google.com
-smalkos@google.com
-wyattriley@google.com
-yuhany@google.com
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
index 559ed29..5d7f51e 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
@@ -38,6 +38,6 @@
   int flags;
   long timestampNs;
   double timeUncertaintyNs;
-  const int HAS_TIMESTAMP_NS = 1;
-  const int HAS_TIME_UNCERTAINTY_NS = 2;
+  const int HAS_TIMESTAMP_NS = (1 << 0) /* 1 */;
+  const int HAS_TIME_UNCERTAINTY_NS = (1 << 1) /* 2 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
index a8454dd..63edd44 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
@@ -46,11 +46,11 @@
   double driftUncertaintyNsps;
   int hwClockDiscontinuityCount;
   android.hardware.gnss.GnssSignalType referenceSignalTypeForIsb;
-  const int HAS_LEAP_SECOND = 1;
-  const int HAS_TIME_UNCERTAINTY = 2;
-  const int HAS_FULL_BIAS = 4;
-  const int HAS_BIAS = 8;
-  const int HAS_BIAS_UNCERTAINTY = 16;
-  const int HAS_DRIFT = 32;
-  const int HAS_DRIFT_UNCERTAINTY = 64;
+  const int HAS_LEAP_SECOND = (1 << 0) /* 1 */;
+  const int HAS_TIME_UNCERTAINTY = (1 << 1) /* 2 */;
+  const int HAS_FULL_BIAS = (1 << 2) /* 4 */;
+  const int HAS_BIAS = (1 << 3) /* 8 */;
+  const int HAS_BIAS_UNCERTAINTY = (1 << 4) /* 16 */;
+  const int HAS_DRIFT = (1 << 5) /* 32 */;
+  const int HAS_DRIFT_UNCERTAINTY = (1 << 6) /* 64 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl
index ed9dcfa..e64d98a 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssLocation.aidl
@@ -47,12 +47,12 @@
   double bearingAccuracyDegrees;
   long timestampMillis;
   android.hardware.gnss.ElapsedRealtime elapsedRealtime;
-  const int HAS_LAT_LONG = 1;
-  const int HAS_ALTITUDE = 2;
-  const int HAS_SPEED = 4;
-  const int HAS_BEARING = 8;
-  const int HAS_HORIZONTAL_ACCURACY = 16;
-  const int HAS_VERTICAL_ACCURACY = 32;
-  const int HAS_SPEED_ACCURACY = 64;
-  const int HAS_BEARING_ACCURACY = 128;
+  const int HAS_LAT_LONG = 0x0001;
+  const int HAS_ALTITUDE = 0x0002;
+  const int HAS_SPEED = 0x0004;
+  const int HAS_BEARING = 0x0008;
+  const int HAS_HORIZONTAL_ACCURACY = 0x0010;
+  const int HAS_VERTICAL_ACCURACY = 0x0020;
+  const int HAS_SPEED_ACCURACY = 0x0040;
+  const int HAS_BEARING_ACCURACY = 0x0080;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
index 8a44887..a2594af 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
@@ -61,39 +61,39 @@
   double satelliteInterSignalBiasUncertaintyNs;
   android.hardware.gnss.SatellitePvt satellitePvt;
   android.hardware.gnss.CorrelationVector[] correlationVectors;
-  const int HAS_SNR = 1;
-  const int HAS_CARRIER_FREQUENCY = 512;
-  const int HAS_CARRIER_CYCLES = 1024;
-  const int HAS_CARRIER_PHASE = 2048;
-  const int HAS_CARRIER_PHASE_UNCERTAINTY = 4096;
-  const int HAS_AUTOMATIC_GAIN_CONTROL = 8192;
-  const int HAS_FULL_ISB = 65536;
-  const int HAS_FULL_ISB_UNCERTAINTY = 131072;
-  const int HAS_SATELLITE_ISB = 262144;
-  const int HAS_SATELLITE_ISB_UNCERTAINTY = 524288;
-  const int HAS_SATELLITE_PVT = 1048576;
-  const int HAS_CORRELATION_VECTOR = 2097152;
+  const int HAS_SNR = (1 << 0) /* 1 */;
+  const int HAS_CARRIER_FREQUENCY = (1 << 9) /* 512 */;
+  const int HAS_CARRIER_CYCLES = (1 << 10) /* 1024 */;
+  const int HAS_CARRIER_PHASE = (1 << 11) /* 2048 */;
+  const int HAS_CARRIER_PHASE_UNCERTAINTY = (1 << 12) /* 4096 */;
+  const int HAS_AUTOMATIC_GAIN_CONTROL = (1 << 13) /* 8192 */;
+  const int HAS_FULL_ISB = (1 << 16) /* 65536 */;
+  const int HAS_FULL_ISB_UNCERTAINTY = (1 << 17) /* 131072 */;
+  const int HAS_SATELLITE_ISB = (1 << 18) /* 262144 */;
+  const int HAS_SATELLITE_ISB_UNCERTAINTY = (1 << 19) /* 524288 */;
+  const int HAS_SATELLITE_PVT = (1 << 20) /* 1048576 */;
+  const int HAS_CORRELATION_VECTOR = (1 << 21) /* 2097152 */;
   const int STATE_UNKNOWN = 0;
-  const int STATE_CODE_LOCK = 1;
-  const int STATE_BIT_SYNC = 2;
-  const int STATE_SUBFRAME_SYNC = 4;
-  const int STATE_TOW_DECODED = 8;
-  const int STATE_MSEC_AMBIGUOUS = 16;
-  const int STATE_SYMBOL_SYNC = 32;
-  const int STATE_GLO_STRING_SYNC = 64;
-  const int STATE_GLO_TOD_DECODED = 128;
-  const int STATE_BDS_D2_BIT_SYNC = 256;
-  const int STATE_BDS_D2_SUBFRAME_SYNC = 512;
-  const int STATE_GAL_E1BC_CODE_LOCK = 1024;
-  const int STATE_GAL_E1C_2ND_CODE_LOCK = 2048;
-  const int STATE_GAL_E1B_PAGE_SYNC = 4096;
-  const int STATE_SBAS_SYNC = 8192;
-  const int STATE_TOW_KNOWN = 16384;
-  const int STATE_GLO_TOD_KNOWN = 32768;
-  const int STATE_2ND_CODE_LOCK = 65536;
+  const int STATE_CODE_LOCK = (1 << 0) /* 1 */;
+  const int STATE_BIT_SYNC = (1 << 1) /* 2 */;
+  const int STATE_SUBFRAME_SYNC = (1 << 2) /* 4 */;
+  const int STATE_TOW_DECODED = (1 << 3) /* 8 */;
+  const int STATE_MSEC_AMBIGUOUS = (1 << 4) /* 16 */;
+  const int STATE_SYMBOL_SYNC = (1 << 5) /* 32 */;
+  const int STATE_GLO_STRING_SYNC = (1 << 6) /* 64 */;
+  const int STATE_GLO_TOD_DECODED = (1 << 7) /* 128 */;
+  const int STATE_BDS_D2_BIT_SYNC = (1 << 8) /* 256 */;
+  const int STATE_BDS_D2_SUBFRAME_SYNC = (1 << 9) /* 512 */;
+  const int STATE_GAL_E1BC_CODE_LOCK = (1 << 10) /* 1024 */;
+  const int STATE_GAL_E1C_2ND_CODE_LOCK = (1 << 11) /* 2048 */;
+  const int STATE_GAL_E1B_PAGE_SYNC = (1 << 12) /* 4096 */;
+  const int STATE_SBAS_SYNC = (1 << 13) /* 8192 */;
+  const int STATE_TOW_KNOWN = (1 << 14) /* 16384 */;
+  const int STATE_GLO_TOD_KNOWN = (1 << 15) /* 32768 */;
+  const int STATE_2ND_CODE_LOCK = (1 << 16) /* 65536 */;
   const int ADR_STATE_UNKNOWN = 0;
-  const int ADR_STATE_VALID = 1;
-  const int ADR_STATE_RESET = 2;
-  const int ADR_STATE_CYCLE_SLIP = 4;
-  const int ADR_STATE_HALF_CYCLE_RESOLVED = 8;
+  const int ADR_STATE_VALID = (1 << 0) /* 1 */;
+  const int ADR_STATE_RESET = (1 << 1) /* 2 */;
+  const int ADR_STATE_CYCLE_SLIP = (1 << 2) /* 4 */;
+  const int ADR_STATE_HALF_CYCLE_RESOLVED = (1 << 3) /* 8 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
index 4a49547..a17f933 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
@@ -42,6 +42,7 @@
   const @utf8InCpp String CODE_TYPE_B = "B";
   const @utf8InCpp String CODE_TYPE_C = "C";
   const @utf8InCpp String CODE_TYPE_D = "D";
+  const @utf8InCpp String CODE_TYPE_E = "E";
   const @utf8InCpp String CODE_TYPE_I = "I";
   const @utf8InCpp String CODE_TYPE_L = "L";
   const @utf8InCpp String CODE_TYPE_M = "M";
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
index c782b6f..c8634ec 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
@@ -40,8 +40,8 @@
   void setSetId(in android.hardware.gnss.IAGnssRil.SetIdType type, in @utf8InCpp String setid);
   void updateNetworkState(in android.hardware.gnss.IAGnssRil.NetworkAttributes attributes);
   void injectNiSuplMessageData(in byte[] msgData, in int slotIndex);
-  const int NETWORK_CAPABILITY_NOT_METERED = 1;
-  const int NETWORK_CAPABILITY_NOT_ROAMING = 2;
+  const int NETWORK_CAPABILITY_NOT_METERED = 0x01;
+  const int NETWORK_CAPABILITY_NOT_ROAMING = 0x02;
   @Backing(type="int") @VintfStability
   enum AGnssRefLocationType {
     GSM_CELLID = 1,
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 0e6405e..d1aaf2c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -77,19 +77,19 @@
   }
   @Backing(type="int") @VintfStability
   enum GnssAidingData {
-    EPHEMERIS = 1,
-    ALMANAC = 2,
-    POSITION = 4,
-    TIME = 8,
-    IONO = 16,
-    UTC = 32,
-    HEALTH = 64,
-    SVDIR = 128,
-    SVSTEER = 256,
-    SADATA = 512,
-    RTI = 1024,
-    CELLDB_INFO = 32768,
-    ALL = 65535,
+    EPHEMERIS = 0x0001,
+    ALMANAC = 0x0002,
+    POSITION = 0x0004,
+    TIME = 0x0008,
+    IONO = 0x0010,
+    UTC = 0x0020,
+    HEALTH = 0x0040,
+    SVDIR = 0x0080,
+    SVSTEER = 0x0100,
+    SADATA = 0x0200,
+    RTI = 0x0400,
+    CELLDB_INFO = 0x8000,
+    ALL = 0xFFFF,
   }
   @VintfStability
   parcelable PositionModeOptions {
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
index d82aa1f..a021f55 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssBatching.aidl
@@ -41,7 +41,7 @@
   void flush();
   void stop();
   void cleanup();
-  const int WAKEUP_ON_FIFO_FULL = 1;
+  const int WAKEUP_ON_FIFO_FULL = 0x01;
   @VintfStability
   parcelable Options {
     long periodNanos;
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index 0247182..61710d3 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
@@ -46,22 +46,22 @@
   void gnssRequestTimeCb();
   void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
   void gnssSetSignalTypeCapabilitiesCb(in android.hardware.gnss.GnssSignalType[] gnssSignalTypes);
-  const int CAPABILITY_SCHEDULING = 1;
-  const int CAPABILITY_MSB = 2;
-  const int CAPABILITY_MSA = 4;
-  const int CAPABILITY_SINGLE_SHOT = 8;
-  const int CAPABILITY_ON_DEMAND_TIME = 16;
-  const int CAPABILITY_GEOFENCING = 32;
-  const int CAPABILITY_MEASUREMENTS = 64;
-  const int CAPABILITY_NAV_MESSAGES = 128;
-  const int CAPABILITY_LOW_POWER_MODE = 256;
-  const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
-  const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1024;
-  const int CAPABILITY_ANTENNA_INFO = 2048;
-  const int CAPABILITY_CORRELATION_VECTOR = 4096;
-  const int CAPABILITY_SATELLITE_PVT = 8192;
-  const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
-  const int CAPABILITY_ACCUMULATED_DELTA_RANGE = 32768;
+  const int CAPABILITY_SCHEDULING = (1 << 0) /* 1 */;
+  const int CAPABILITY_MSB = (1 << 1) /* 2 */;
+  const int CAPABILITY_MSA = (1 << 2) /* 4 */;
+  const int CAPABILITY_SINGLE_SHOT = (1 << 3) /* 8 */;
+  const int CAPABILITY_ON_DEMAND_TIME = (1 << 4) /* 16 */;
+  const int CAPABILITY_GEOFENCING = (1 << 5) /* 32 */;
+  const int CAPABILITY_MEASUREMENTS = (1 << 6) /* 64 */;
+  const int CAPABILITY_NAV_MESSAGES = (1 << 7) /* 128 */;
+  const int CAPABILITY_LOW_POWER_MODE = (1 << 8) /* 256 */;
+  const int CAPABILITY_SATELLITE_BLOCKLIST = (1 << 9) /* 512 */;
+  const int CAPABILITY_MEASUREMENT_CORRECTIONS = (1 << 10) /* 1024 */;
+  const int CAPABILITY_ANTENNA_INFO = (1 << 11) /* 2048 */;
+  const int CAPABILITY_CORRELATION_VECTOR = (1 << 12) /* 4096 */;
+  const int CAPABILITY_SATELLITE_PVT = (1 << 13) /* 8192 */;
+  const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = (1 << 14) /* 16384 */;
+  const int CAPABILITY_ACCUMULATED_DELTA_RANGE = (1 << 15) /* 32768 */;
   @Backing(type="int") @VintfStability
   enum GnssStatusValue {
     NONE = 0,
@@ -73,10 +73,10 @@
   @Backing(type="int") @VintfStability
   enum GnssSvFlags {
     NONE = 0,
-    HAS_EPHEMERIS_DATA = 1,
-    HAS_ALMANAC_DATA = 2,
-    USED_IN_FIX = 4,
-    HAS_CARRIER_FREQUENCY = 8,
+    HAS_EPHEMERIS_DATA = (1 << 0) /* 1 */,
+    HAS_ALMANAC_DATA = (1 << 1) /* 2 */,
+    USED_IN_FIX = (1 << 2) /* 4 */,
+    HAS_CARRIER_FREQUENCY = (1 << 3) /* 8 */,
   }
   @VintfStability
   parcelable GnssSvInfo {
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
index 1d6399e..70df11a 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
@@ -42,11 +42,11 @@
   void setEmergencySuplPdn(in boolean enable);
   void setEsExtensionSec(in int emergencyExtensionSeconds);
   void setBlocklist(in android.hardware.gnss.BlocklistedSource[] blocklist);
-  const int SUPL_MODE_MSB = 1;
-  const int SUPL_MODE_MSA = 2;
-  const int LPP_PROFILE_USER_PLANE = 1;
-  const int LPP_PROFILE_CONTROL_PLANE = 2;
-  const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 1;
-  const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 2;
-  const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 4;
+  const int SUPL_MODE_MSB = 0x01;
+  const int SUPL_MODE_MSA = 0x02;
+  const int LPP_PROFILE_USER_PLANE = 0x01;
+  const int LPP_PROFILE_CONTROL_PLANE = 0x02;
+  const int GLONASS_POS_PROTOCOL_RRC_CPLANE = 0x01;
+  const int GLONASS_POS_PROTOCOL_RRLP_UPLANE = 0x02;
+  const int GLONASS_POS_PROTOCOL_LPP_UPLANE = 0x04;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl
index df5dc2d..90f9ebc 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssGeofenceCallback.aidl
@@ -41,15 +41,15 @@
   void gnssGeofenceRemoveCb(in int geofenceId, in int status);
   void gnssGeofencePauseCb(in int geofenceId, in int status);
   void gnssGeofenceResumeCb(in int geofenceId, in int status);
-  const int ENTERED = 1;
-  const int EXITED = 2;
-  const int UNCERTAIN = 4;
-  const int UNAVAILABLE = 1;
-  const int AVAILABLE = 2;
+  const int ENTERED = (1 << 0) /* 1 */;
+  const int EXITED = (1 << 1) /* 2 */;
+  const int UNCERTAIN = (1 << 2) /* 4 */;
+  const int UNAVAILABLE = (1 << 0) /* 1 */;
+  const int AVAILABLE = (1 << 1) /* 2 */;
   const int OPERATION_SUCCESS = 0;
-  const int ERROR_TOO_MANY_GEOFENCES = -100;
-  const int ERROR_ID_EXISTS = -101;
-  const int ERROR_ID_UNKNOWN = -102;
-  const int ERROR_INVALID_TRANSITION = -103;
-  const int ERROR_GENERIC = -149;
+  const int ERROR_TOO_MANY_GEOFENCES = (-100) /* -100 */;
+  const int ERROR_ID_EXISTS = (-101) /* -101 */;
+  const int ERROR_ID_UNKNOWN = (-102) /* -102 */;
+  const int ERROR_INVALID_TRANSITION = (-103) /* -103 */;
+  const int ERROR_GENERIC = (-149) /* -149 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
index c65cff2..57d0e68 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
@@ -44,26 +44,26 @@
     int messageId;
     int submessageId;
     byte[] data;
-    const int STATUS_PARITY_PASSED = 1;
-    const int STATUS_PARITY_REBUILT = 2;
+    const int STATUS_PARITY_PASSED = (1 << 0) /* 1 */;
+    const int STATUS_PARITY_REBUILT = (1 << 1) /* 2 */;
     const int STATUS_UNKNOWN = 0;
     @Backing(type="int") @VintfStability
     enum GnssNavigationMessageType {
       UNKNOWN = 0,
-      GPS_L1CA = 257,
-      GPS_L2CNAV = 258,
-      GPS_L5CNAV = 259,
-      SBS = 513,
-      GPS_CNAV2 = 260,
-      GLO_L1CA = 769,
-      QZS_L1CA = 1025,
-      BDS_D1 = 1281,
-      BDS_D2 = 1282,
-      BDS_CNAV1 = 1283,
-      BDS_CNAV2 = 1284,
-      GAL_I = 1537,
-      GAL_F = 1538,
-      IRN_L5CA = 1793,
+      GPS_L1CA = 0x0101,
+      GPS_L2CNAV = 0x0102,
+      GPS_L5CNAV = 0x0103,
+      SBS = 0x0201,
+      GPS_CNAV2 = 0x0104,
+      GLO_L1CA = 0x0301,
+      QZS_L1CA = 0x0401,
+      BDS_D1 = 0x0501,
+      BDS_D2 = 0x0502,
+      BDS_CNAV1 = 0x0503,
+      BDS_CNAV2 = 0x0504,
+      GAL_I = 0x0601,
+      GAL_F = 0x0602,
+      IRN_L5CA = 0x0701,
     }
   }
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
index d35c77f..07b10ad 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
@@ -37,10 +37,10 @@
 interface IGnssPowerIndicationCallback {
   void setCapabilitiesCb(in int capabilities);
   oneway void gnssPowerStatsCb(in android.hardware.gnss.GnssPowerStats gnssPowerStats);
-  const int CAPABILITY_TOTAL = 1;
-  const int CAPABILITY_SINGLEBAND_TRACKING = 2;
-  const int CAPABILITY_MULTIBAND_TRACKING = 4;
-  const int CAPABILITY_SINGLEBAND_ACQUISITION = 8;
-  const int CAPABILITY_MULTIBAND_ACQUISITION = 16;
-  const int CAPABILITY_OTHER_MODES = 32;
+  const int CAPABILITY_TOTAL = (1 << 0) /* 1 */;
+  const int CAPABILITY_SINGLEBAND_TRACKING = (1 << 1) /* 2 */;
+  const int CAPABILITY_MULTIBAND_TRACKING = (1 << 2) /* 4 */;
+  const int CAPABILITY_SINGLEBAND_ACQUISITION = (1 << 3) /* 8 */;
+  const int CAPABILITY_MULTIBAND_ACQUISITION = (1 << 4) /* 16 */;
+  const int CAPABILITY_OTHER_MODES = (1 << 5) /* 32 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
index 5fd411f..ae65f39 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
@@ -46,9 +46,9 @@
   long timeOfEphemerisSeconds;
   int issueOfDataEphemeris;
   android.hardware.gnss.SatellitePvt.SatelliteEphemerisSource ephemerisSource = android.hardware.gnss.SatellitePvt.SatelliteEphemerisSource.OTHER;
-  const int HAS_POSITION_VELOCITY_CLOCK_INFO = 1;
-  const int HAS_IONO = 2;
-  const int HAS_TROPO = 4;
+  const int HAS_POSITION_VELOCITY_CLOCK_INFO = (1 << 0) /* 1 */;
+  const int HAS_IONO = (1 << 1) /* 2 */;
+  const int HAS_TROPO = (1 << 2) /* 4 */;
   @Backing(type="int") @VintfStability
   enum SatelliteEphemerisSource {
     DEMODULATED = 0,
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
index 4126702..61909d0 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/IMeasurementCorrectionsCallback.aidl
@@ -36,7 +36,7 @@
 @VintfStability
 interface IMeasurementCorrectionsCallback {
   void setCapabilitiesCb(in int capabilities);
-  const int CAPABILITY_LOS_SATS = 1;
-  const int CAPABILITY_EXCESS_PATH_LENGTH = 2;
-  const int CAPABILITY_REFLECTING_PLANE = 4;
+  const int CAPABILITY_LOS_SATS = (1 << 0) /* 1 */;
+  const int CAPABILITY_EXCESS_PATH_LENGTH = (1 << 1) /* 2 */;
+  const int CAPABILITY_REFLECTING_PLANE = (1 << 2) /* 4 */;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
index ebbe684..72d32e4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/measurement_corrections/SingleSatCorrection.aidl
@@ -44,10 +44,10 @@
   float combinedExcessPathLengthUncertaintyMeters;
   float combinedAttenuationDb;
   android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo[] excessPathInfos;
-  const int SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY = 1;
-  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH = 2;
-  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC = 4;
-  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION = 16;
+  const int SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY = 0x0001;
+  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH = 0x0002;
+  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC = 0x0004;
+  const int SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION = 0x0010;
   @VintfStability
   parcelable ExcessPathInfo {
     int excessPathInfoFlags;
@@ -55,9 +55,9 @@
     float excessPathLengthUncertaintyMeters;
     android.hardware.gnss.measurement_corrections.ReflectingPlane reflectingPlane;
     float attenuationDb;
-    const int EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH = 1;
-    const int EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC = 2;
-    const int EXCESS_PATH_INFO_HAS_REFLECTING_PLANE = 4;
-    const int EXCESS_PATH_INFO_HAS_ATTENUATION = 8;
+    const int EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH = 0x0001;
+    const int EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC = 0x0002;
+    const int EXCESS_PATH_INFO_HAS_REFLECTING_PLANE = 0x0004;
+    const int EXCESS_PATH_INFO_HAS_ATTENUATION = 0x0008;
   }
 }
diff --git a/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl
index 241971f..c66d9e8 100644
--- a/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssSignalType.aidl
@@ -46,27 +46,36 @@
     double carrierFrequencyHz;
 
     /**
-     * GNSS signal code type "A" representing GALILEO E1A, GALILEO E6A, IRNSS L5A, IRNSS SA.
+     * GNSS signal code type "A" representing GALILEO E1A, GALILEO E6A, IRNSS L5A SPS, IRNSS SA SPS,
+     * GLONASS G1a L1OCd, GLONASS G2a L2CSI.
      */
     const @utf8InCpp String CODE_TYPE_A = "A";
 
     /**
-     * GNSS signal code type "B" representing GALILEO E1B, GALILEO E6B, IRNSS L5B, IRNSS SB.
+     * GNSS signal code type "B" representing GALILEO E1B, GALILEO E6B, IRNSS L5B RS (D),
+     * IRNSS SB RS (D), GLONASS G1a L1OCp, GLONASS G2a L2OCp, QZSS L1Sb.
      */
     const @utf8InCpp String CODE_TYPE_B = "B";
 
     /**
      * GNSS signal code type "C" representing GPS L1 C/A,  GPS L2 C/A, GLONASS G1 C/A,
-     * GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
+     * GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C RS (P),
+     * IRNSS SC RS (P).
      */
     const @utf8InCpp String CODE_TYPE_C = "C";
 
     /**
-     * GNSS signal code type "D" representing BDS B1C D.
+     * GNSS signal code type "D" representing GPS L2 (L1(C/A) + (P2-P1) (semi-codeless)),
+     * QZSS L5S(I), BDS B1C Data, BDS B2a Data, BDS B2b Data, BDS B2 (B2a+B2b) Data, BDS B3a Data.
      */
     const @utf8InCpp String CODE_TYPE_D = "D";
 
     /**
+     * GNSS signal code type "E" representing QZSS L1 C/B, QZSS L6E.
+     */
+    const @utf8InCpp String CODE_TYPE_E = "E";
+
+    /**
      * GNSS signal code type "I" representing GPS L5 I, GLONASS G3 I, GALILEO E5a I, GALILEO E5b I,
      * GALILEO E5a+b I, SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
      */
@@ -74,7 +83,7 @@
 
     /**
      * GNSS signal code type "L" representing GPS L1C (P), GPS L2C (L), QZSS L1C (P), QZSS L2C (L),
-     * LEX(6) L.
+     * QZSS L6P, BDS B1a Pilot.
      */
     const @utf8InCpp String CODE_TYPE_L = "L";
 
@@ -89,7 +98,9 @@
     const @utf8InCpp String CODE_TYPE_N = "N";
 
     /**
-     * GNSS signal code type "P" representing GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P, BDS B1C P.
+     * GNSS signal code type "P" representing GPS L1P, GPS L2P, GLONASS G1P, GLONASS G2P,
+     * BDS B1C Pilot, BDS B2a Pilot, BDS B2b Pilot, BDS B2 (B2a+B2b) Pilot, BDS B3a Pilot,
+     * QZSS L5S(Q).
      */
     const @utf8InCpp String CODE_TYPE_P = "P";
 
@@ -101,7 +112,7 @@
 
     /**
      * GNSS signal code type "S" represents GPS L1C (D), GPS L2C (M), QZSS L1C (D), QZSS L2C (M),
-     * LEX(6) S.
+     * QZSS L6D, BDS B1a Data.
      */
     const @utf8InCpp String CODE_TYPE_S = "S";
 
@@ -112,9 +123,11 @@
 
     /**
      * GNSS signal code type "X" representing GPS L1C (D+P), GPS L2C (M+L), GPS L5 (I+Q),
-     * GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b(I+Q),
-     * GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q),
-     * LEX(6) (S+L), BDS B1 (I+Q), BDS B1C (D+P), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
+     * GLONASS G1a L1OCd+L1OCp, GLONASS G2a L2CSI+L2OCp, GLONASS G3 (I+Q), GALILEO E1 (B+C),
+     * GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO E5a+b (I+Q), GALILEO E6 (B+C), SBAS L5 (I+Q),
+     * QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q), QZSS L6 (D+P), BDS B1 (I+Q),
+     * BDS B1C Data+Pilot, BDS B2a Data+Pilot, BDS B2 (I+Q), BDS B2 (B2a+B2b) Data+Pilot,
+     * BDS B3 (I+Q), IRNSS L5 (B+C), IRNSS S (B+C).
      */
     const @utf8InCpp String CODE_TYPE_X = "X";
 
@@ -124,7 +137,9 @@
     const @utf8InCpp String CODE_TYPE_Y = "Y";
 
     /**
-     * GNSS signal code type "Z" representing GALILEO E1 (A+B+C), GALILEO E6 (A+B+C), QZSS L1-SAIF.
+     * GNSS signal code type "Z" representing GALILEO E1 (A+B+C), GALILEO E6 (A+B+C),
+     * QZSS L1S/L1-SAIF, QZSS L5S (I+Q), QZSS L6 (D+E), BDS B1A Data+Pilot, BDS B2b Data+Pilot,
+     * BDS B3a Data+Pilot.
      */
     const @utf8InCpp String CODE_TYPE_Z = "Z";
 
@@ -142,10 +157,11 @@
      * The value is one of the constant Strings with prefix CODE_TYPE_ defined in this parcelable.
      *
      * This is used to specify the observation descriptor defined in GNSS Observation Data File
-     * Header Section Description in the RINEX standard (Version 3.XX). In RINEX Version 3.03,
-     * in Appendix Table A2 Attributes are listed as uppercase letters (for instance, "A" for
-     * "A channel"). In the future, if for instance a code "G" was added in the official RINEX
-     * standard, "G" could be specified here.
+     * Header Section Description in the RINEX standard (Version 4.00) e.g., in Tables 9-16 (see
+     * https://igs.org/wg/rinex/#documents-formats). In cases where the code type does not align
+     * with the above listed values, the code type from the most recent version of RINEX should be
+     * used. In the future, if for instance a code "G" was added in the official RINEX standard,
+     * "G" could be specified here.
      */
     @utf8InCpp String codeType;
 }
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index ca5a41f..542796f 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -50,7 +50,7 @@
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
-        "android.hardware.gnss-V3-ndk",
+        "android.hardware.gnss-V4-ndk",
     ],
     srcs: [
         "AGnssRil.cpp",
diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml
index 73b841e..c01069e 100644
--- a/gnss/aidl/default/gnss-default.xml
+++ b/gnss/aidl/default/gnss-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.gnss</name>
-        <version>3</version>
+        <version>4</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index 2a09a56..fd1d853 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -51,7 +51,7 @@
         "libbinder",
     ],
     static_libs: [
-        "android.hardware.gnss-V3-cpp",
+        "android.hardware.gnss-V4-cpp",
         "android.hardware.gnss@common-vts-lib",
     ],
     test_suites: [
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 4f5e6a0..5e2cbe3 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -486,8 +486,6 @@
 
     auto status = aidl_gnss_hal_->startSvStatus();
     EXPECT_TRUE(status.isOk());
-    ASSERT_TRUE(aidl_gnss_cb_->sv_info_list_timestamps_millis_cbq_.size() ==
-                aidl_gnss_cb_->sv_info_list_cbq_.size());
     long lastElapsedRealtimeMillis = 0;
     for (int i = 0; i < numMeasurementEvents; i++) {
         long timeStamp;
diff --git a/gnss/common/OWNERS b/gnss/common/OWNERS
deleted file mode 100644
index 3ed36da..0000000
--- a/gnss/common/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-wyattriley@google.com
-gomo@google.com
-smalkos@google.com
-yuhany@google.com
-
-# VTS team
-yim@google.com
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 4cf17a6..208bc59 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -57,6 +57,6 @@
         "android.hardware.gnss@2.1",
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
-        "android.hardware.gnss-V3-ndk",
+        "android.hardware.gnss-V4-ndk",
     ],
 }
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index b5325b2..ed5674c 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -44,7 +44,7 @@
         "android.hardware.gnss@2.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.measurement_corrections@1.1",
-        "android.hardware.gnss-V3-cpp",
+        "android.hardware.gnss-V4-cpp",
     ],
     static_libs: [
         "libgtest",
diff --git a/graphics/Android.bp b/graphics/Android.bp
index 2fbcb41..8a69f09 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -53,13 +53,13 @@
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_static",
     static_libs: [
-        "android.hardware.graphics.composer3-V2-ndk",
+        "android.hardware.graphics.composer3-V3-ndk",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_shared",
     shared_libs: [
-        "android.hardware.graphics.composer3-V2-ndk",
+        "android.hardware.graphics.composer3-V3-ndk",
     ],
 }
diff --git a/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
index 50aa2b7..7194ebe 100644
--- a/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
+++ b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
@@ -23,7 +23,14 @@
 @VintfStability
 parcelable BufferDescriptorInfo {
     /**
-     * The name of the buffer in ASCII. Useful for debugging/tracing.
+     * The name of the buffer in null-terminated ASCII. Useful for debugging/tracing.
+     *
+     * NOTE: While a well behaved client will ensure it passes a null-terminated string
+     *       within the 128-byte limit, the IAllocator service implementation should be
+     *       be defensive against malformed input. As such, it is recommended that
+     *       IAllocator implementations proactively do `name[127] = 0` upon receiving
+     *       an allocation request to enusre that the string is definitely
+     *       null-terminated regardless of what the client sent.
      */
     byte[128] name;
 
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 02334e8..142c7c1 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -43,7 +43,7 @@
             enabled: true,
         },
     },
-    frozen: true,
+    frozen: false,
     versions_with_info: [
         {
             version: "1",
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
index d3ab44f..d42a6d5 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
@@ -35,31 +35,31 @@
 /* @hide */
 @Backing(type="long") @VintfStability
 enum BufferUsage {
-  CPU_READ_MASK = 15,
+  CPU_READ_MASK = 0xf,
   CPU_READ_NEVER = 0,
   CPU_READ_RARELY = 2,
   CPU_READ_OFTEN = 3,
-  CPU_WRITE_MASK = 240,
-  CPU_WRITE_NEVER = 0,
-  CPU_WRITE_RARELY = 32,
-  CPU_WRITE_OFTEN = 48,
-  GPU_TEXTURE = 256,
-  GPU_RENDER_TARGET = 512,
-  COMPOSER_OVERLAY = 2048,
-  COMPOSER_CLIENT_TARGET = 4096,
-  PROTECTED = 16384,
-  COMPOSER_CURSOR = 32768,
-  VIDEO_ENCODER = 65536,
-  CAMERA_OUTPUT = 131072,
-  CAMERA_INPUT = 262144,
-  RENDERSCRIPT = 1048576,
-  VIDEO_DECODER = 4194304,
-  SENSOR_DIRECT_DATA = 8388608,
-  GPU_DATA_BUFFER = 16777216,
-  GPU_CUBE_MAP = 33554432,
-  GPU_MIPMAP_COMPLETE = 67108864,
-  HW_IMAGE_ENCODER = 134217728,
-  FRONT_BUFFER = 4294967296,
-  VENDOR_MASK = -268435456,
-  VENDOR_MASK_HI = -281474976710656,
+  CPU_WRITE_MASK = (0xf << 4) /* 240 */,
+  CPU_WRITE_NEVER = (0 << 4) /* 0 */,
+  CPU_WRITE_RARELY = (2 << 4) /* 32 */,
+  CPU_WRITE_OFTEN = (3 << 4) /* 48 */,
+  GPU_TEXTURE = (1 << 8) /* 256 */,
+  GPU_RENDER_TARGET = (1 << 9) /* 512 */,
+  COMPOSER_OVERLAY = (1 << 11) /* 2048 */,
+  COMPOSER_CLIENT_TARGET = (1 << 12) /* 4096 */,
+  PROTECTED = (1 << 14) /* 16384 */,
+  COMPOSER_CURSOR = (1 << 15) /* 32768 */,
+  VIDEO_ENCODER = (1 << 16) /* 65536 */,
+  CAMERA_OUTPUT = (1 << 17) /* 131072 */,
+  CAMERA_INPUT = (1 << 18) /* 262144 */,
+  RENDERSCRIPT = (1 << 20) /* 1048576 */,
+  VIDEO_DECODER = (1 << 22) /* 4194304 */,
+  SENSOR_DIRECT_DATA = (1 << 23) /* 8388608 */,
+  GPU_DATA_BUFFER = (1 << 24) /* 16777216 */,
+  GPU_CUBE_MAP = (1 << 25) /* 33554432 */,
+  GPU_MIPMAP_COMPLETE = (1 << 26) /* 67108864 */,
+  HW_IMAGE_ENCODER = (1 << 27) /* 134217728 */,
+  FRONT_BUFFER = (1L << 32) /* 4294967296 */,
+  VENDOR_MASK = (0xf << 28) /* -268435456 */,
+  VENDOR_MASK_HI = ((1L * 0xffff) << 48) /* -281474976710656 */,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
index b8af644..784fc17 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
@@ -39,4 +39,6 @@
   UNKNOWN = 1,
   SITED_INTERSTITIAL = 2,
   COSITED_HORIZONTAL = 3,
+  COSITED_VERTICAL = 4,
+  COSITED_BOTH = 5,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
index 563b6c1..d9ff5aa 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
@@ -35,65 +35,65 @@
 /* @hide */
 @Backing(type="int") @VintfStability
 enum Dataspace {
-  UNKNOWN = 0,
-  ARBITRARY = 1,
+  UNKNOWN = 0x0,
+  ARBITRARY = 0x1,
   STANDARD_SHIFT = 16,
-  STANDARD_MASK = 4128768,
-  STANDARD_UNSPECIFIED = 0,
-  STANDARD_BT709 = 65536,
-  STANDARD_BT601_625 = 131072,
-  STANDARD_BT601_625_UNADJUSTED = 196608,
-  STANDARD_BT601_525 = 262144,
-  STANDARD_BT601_525_UNADJUSTED = 327680,
-  STANDARD_BT2020 = 393216,
-  STANDARD_BT2020_CONSTANT_LUMINANCE = 458752,
-  STANDARD_BT470M = 524288,
-  STANDARD_FILM = 589824,
-  STANDARD_DCI_P3 = 655360,
-  STANDARD_ADOBE_RGB = 720896,
+  STANDARD_MASK = (63 << 16) /* 4128768 */,
+  STANDARD_UNSPECIFIED = (0 << 16) /* 0 */,
+  STANDARD_BT709 = (1 << 16) /* 65536 */,
+  STANDARD_BT601_625 = (2 << 16) /* 131072 */,
+  STANDARD_BT601_625_UNADJUSTED = (3 << 16) /* 196608 */,
+  STANDARD_BT601_525 = (4 << 16) /* 262144 */,
+  STANDARD_BT601_525_UNADJUSTED = (5 << 16) /* 327680 */,
+  STANDARD_BT2020 = (6 << 16) /* 393216 */,
+  STANDARD_BT2020_CONSTANT_LUMINANCE = (7 << 16) /* 458752 */,
+  STANDARD_BT470M = (8 << 16) /* 524288 */,
+  STANDARD_FILM = (9 << 16) /* 589824 */,
+  STANDARD_DCI_P3 = (10 << 16) /* 655360 */,
+  STANDARD_ADOBE_RGB = (11 << 16) /* 720896 */,
   TRANSFER_SHIFT = 22,
-  TRANSFER_MASK = 130023424,
-  TRANSFER_UNSPECIFIED = 0,
-  TRANSFER_LINEAR = 4194304,
-  TRANSFER_SRGB = 8388608,
-  TRANSFER_SMPTE_170M = 12582912,
-  TRANSFER_GAMMA2_2 = 16777216,
-  TRANSFER_GAMMA2_6 = 20971520,
-  TRANSFER_GAMMA2_8 = 25165824,
-  TRANSFER_ST2084 = 29360128,
-  TRANSFER_HLG = 33554432,
+  TRANSFER_MASK = (31 << 22) /* 130023424 */,
+  TRANSFER_UNSPECIFIED = (0 << 22) /* 0 */,
+  TRANSFER_LINEAR = (1 << 22) /* 4194304 */,
+  TRANSFER_SRGB = (2 << 22) /* 8388608 */,
+  TRANSFER_SMPTE_170M = (3 << 22) /* 12582912 */,
+  TRANSFER_GAMMA2_2 = (4 << 22) /* 16777216 */,
+  TRANSFER_GAMMA2_6 = (5 << 22) /* 20971520 */,
+  TRANSFER_GAMMA2_8 = (6 << 22) /* 25165824 */,
+  TRANSFER_ST2084 = (7 << 22) /* 29360128 */,
+  TRANSFER_HLG = (8 << 22) /* 33554432 */,
   RANGE_SHIFT = 27,
-  RANGE_MASK = 939524096,
-  RANGE_UNSPECIFIED = 0,
-  RANGE_FULL = 134217728,
-  RANGE_LIMITED = 268435456,
-  RANGE_EXTENDED = 402653184,
-  SRGB_LINEAR = 138477568,
-  SCRGB_LINEAR = 406913024,
-  SRGB = 142671872,
-  SCRGB = 411107328,
-  JFIF = 146931712,
-  BT601_625 = 281149440,
-  BT601_525 = 281280512,
-  BT709 = 281083904,
-  DCI_P3_LINEAR = 139067392,
-  DCI_P3 = 155844608,
-  DISPLAY_P3_LINEAR = 139067392,
-  DISPLAY_P3 = 143261696,
-  ADOBE_RGB = 151715840,
-  BT2020_LINEAR = 138805248,
-  BT2020 = 147193856,
-  BT2020_PQ = 163971072,
-  DEPTH = 4096,
-  SENSOR = 4097,
-  BT2020_ITU = 281411584,
-  BT2020_ITU_PQ = 298188800,
-  BT2020_ITU_HLG = 302383104,
-  BT2020_HLG = 168165376,
-  DISPLAY_BT2020 = 142999552,
-  DYNAMIC_DEPTH = 4098,
-  JPEG_APP_SEGMENTS = 4099,
-  HEIF = 4100,
-  JPEG_R = 4101,
-  BT709_FULL_RANGE = 146866176,
+  RANGE_MASK = (7 << 27) /* 939524096 */,
+  RANGE_UNSPECIFIED = (0 << 27) /* 0 */,
+  RANGE_FULL = (1 << 27) /* 134217728 */,
+  RANGE_LIMITED = (2 << 27) /* 268435456 */,
+  RANGE_EXTENDED = (3 << 27) /* 402653184 */,
+  SRGB_LINEAR = (((1 << 16) | (1 << 22)) | (1 << 27)) /* 138477568 */,
+  SCRGB_LINEAR = (((1 << 16) | (1 << 22)) | (3 << 27)) /* 406913024 */,
+  SRGB = (((1 << 16) | (2 << 22)) | (1 << 27)) /* 142671872 */,
+  SCRGB = (((1 << 16) | (2 << 22)) | (3 << 27)) /* 411107328 */,
+  JFIF = (((2 << 16) | (3 << 22)) | (1 << 27)) /* 146931712 */,
+  BT601_625 = (((2 << 16) | (3 << 22)) | (2 << 27)) /* 281149440 */,
+  BT601_525 = (((4 << 16) | (3 << 22)) | (2 << 27)) /* 281280512 */,
+  BT709 = (((1 << 16) | (3 << 22)) | (2 << 27)) /* 281083904 */,
+  DCI_P3_LINEAR = (((10 << 16) | (1 << 22)) | (1 << 27)) /* 139067392 */,
+  DCI_P3 = (((10 << 16) | (5 << 22)) | (1 << 27)) /* 155844608 */,
+  DISPLAY_P3_LINEAR = (((10 << 16) | (1 << 22)) | (1 << 27)) /* 139067392 */,
+  DISPLAY_P3 = (((10 << 16) | (2 << 22)) | (1 << 27)) /* 143261696 */,
+  ADOBE_RGB = (((11 << 16) | (4 << 22)) | (1 << 27)) /* 151715840 */,
+  BT2020_LINEAR = (((6 << 16) | (1 << 22)) | (1 << 27)) /* 138805248 */,
+  BT2020 = (((6 << 16) | (3 << 22)) | (1 << 27)) /* 147193856 */,
+  BT2020_PQ = (((6 << 16) | (7 << 22)) | (1 << 27)) /* 163971072 */,
+  DEPTH = 0x1000,
+  SENSOR = 0x1001,
+  BT2020_ITU = (((6 << 16) | (3 << 22)) | (2 << 27)) /* 281411584 */,
+  BT2020_ITU_PQ = (((6 << 16) | (7 << 22)) | (2 << 27)) /* 298188800 */,
+  BT2020_ITU_HLG = (((6 << 16) | (8 << 22)) | (2 << 27)) /* 302383104 */,
+  BT2020_HLG = (((6 << 16) | (8 << 22)) | (1 << 27)) /* 168165376 */,
+  DISPLAY_BT2020 = (((6 << 16) | (2 << 22)) | (1 << 27)) /* 142999552 */,
+  DYNAMIC_DEPTH = 0x1002,
+  JPEG_APP_SEGMENTS = 0x1003,
+  HEIF = 0x1004,
+  JPEG_R = 0x1005,
+  BT709_FULL_RANGE = (((1 << 16) | (3 << 22)) | (1 << 27)) /* 146866176 */,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
index 1817769..0fe9493 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -32,7 +32,10 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.graphics.common;
-/* @hide */
+/**
+ * @hide
+ * @deprecated : Use instead android.hardware.HardwareBuffer in frameworks/base
+ */
 @VintfStability
 parcelable HardwareBuffer {
   android.hardware.graphics.common.HardwareBufferDescription description;
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
index 68857e8..ed84a44 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
@@ -36,36 +36,36 @@
 @Backing(type="int") @VintfStability
 enum PixelFormat {
   UNSPECIFIED = 0,
-  RGBA_8888 = 1,
-  RGBX_8888 = 2,
-  RGB_888 = 3,
-  RGB_565 = 4,
-  BGRA_8888 = 5,
-  YCBCR_422_SP = 16,
-  YCRCB_420_SP = 17,
-  YCBCR_422_I = 20,
-  RGBA_FP16 = 22,
-  RAW16 = 32,
-  BLOB = 33,
-  IMPLEMENTATION_DEFINED = 34,
-  YCBCR_420_888 = 35,
-  RAW_OPAQUE = 36,
-  RAW10 = 37,
-  RAW12 = 38,
-  RGBA_1010102 = 43,
-  Y8 = 538982489,
-  Y16 = 540422489,
-  YV12 = 842094169,
-  DEPTH_16 = 48,
-  DEPTH_24 = 49,
-  DEPTH_24_STENCIL_8 = 50,
-  DEPTH_32F = 51,
-  DEPTH_32F_STENCIL_8 = 52,
-  STENCIL_8 = 53,
-  YCBCR_P010 = 54,
-  HSV_888 = 55,
-  R_8 = 56,
-  R_16_UINT = 57,
-  RG_1616_UINT = 58,
-  RGBA_10101010 = 59,
+  RGBA_8888 = 0x1,
+  RGBX_8888 = 0x2,
+  RGB_888 = 0x3,
+  RGB_565 = 0x4,
+  BGRA_8888 = 0x5,
+  YCBCR_422_SP = 0x10,
+  YCRCB_420_SP = 0x11,
+  YCBCR_422_I = 0x14,
+  RGBA_FP16 = 0x16,
+  RAW16 = 0x20,
+  BLOB = 0x21,
+  IMPLEMENTATION_DEFINED = 0x22,
+  YCBCR_420_888 = 0x23,
+  RAW_OPAQUE = 0x24,
+  RAW10 = 0x25,
+  RAW12 = 0x26,
+  RGBA_1010102 = 0x2B,
+  Y8 = 0x20203859,
+  Y16 = 0x20363159,
+  YV12 = 0x32315659,
+  DEPTH_16 = 0x30,
+  DEPTH_24 = 0x31,
+  DEPTH_24_STENCIL_8 = 0x32,
+  DEPTH_32F = 0x33,
+  DEPTH_32F_STENCIL_8 = 0x34,
+  STENCIL_8 = 0x35,
+  YCBCR_P010 = 0x36,
+  HSV_888 = 0x37,
+  R_8 = 0x38,
+  R_16_UINT = 0x39,
+  RG_1616_UINT = 0x3a,
+  RGBA_10101010 = 0x3b,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
index 8ba9381..e306751 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
@@ -35,12 +35,12 @@
 /* @hide */
 @Backing(type="long") @VintfStability
 enum PlaneLayoutComponentType {
-  Y = 1,
-  CB = 2,
-  CR = 4,
-  R = 1024,
-  G = 2048,
-  B = 4096,
-  RAW = 1048576,
-  A = 1073741824,
+  Y = (1 << 0) /* 1 */,
+  CB = (1 << 1) /* 2 */,
+  CR = (1 << 2) /* 4 */,
+  R = (1 << 10) /* 1024 */,
+  G = (1 << 11) /* 2048 */,
+  B = (1 << 12) /* 4096 */,
+  RAW = (1 << 20) /* 1048576 */,
+  A = (1 << 30) /* 1073741824 */,
 }
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
index 986d089..dbed57d 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
@@ -36,9 +36,9 @@
 @Backing(type="int") @VintfStability
 enum Transform {
   NONE = 0,
-  FLIP_H = 1,
-  FLIP_V = 2,
-  ROT_90 = 4,
-  ROT_180 = 3,
-  ROT_270 = 7,
+  FLIP_H = (1 << 0) /* 1 */,
+  FLIP_V = (1 << 1) /* 2 */,
+  ROT_90 = (1 << 2) /* 4 */,
+  ROT_180 = (FLIP_H | FLIP_V) /* 3 */,
+  ROT_270 = ((FLIP_H | FLIP_V) | ROT_90) /* 7 */,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
index 12bc441..0d1a094 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
@@ -24,35 +24,47 @@
 @Backing(type="long")
 enum BufferUsage {
     /** bit 0-3 is an enum */
-    CPU_READ_MASK                      = 0xf,
+    CPU_READ_MASK = 0xf,
     /** buffer is never read by CPU */
-    CPU_READ_NEVER                     = 0,
+    CPU_READ_NEVER = 0,
     /** buffer is rarely read by CPU */
-    CPU_READ_RARELY                    = 2,
+    CPU_READ_RARELY = 2,
     /** buffer is often read by CPU */
-    CPU_READ_OFTEN                     = 3,
+    CPU_READ_OFTEN = 3,
 
     /** bit 4-7 is an enum */
-    CPU_WRITE_MASK                     = 0xf << 4,
+    CPU_WRITE_MASK = 0xf << 4,
     /** buffer is never written by CPU */
-    CPU_WRITE_NEVER                    = 0 << 4,
+    CPU_WRITE_NEVER = 0 << 4,
     /** buffer is rarely written by CPU */
-    CPU_WRITE_RARELY                   = 2 << 4,
+    CPU_WRITE_RARELY = 2 << 4,
     /** buffer is often written by CPU */
-    CPU_WRITE_OFTEN                    = 3 << 4,
+    CPU_WRITE_OFTEN = 3 << 4,
 
-    /** buffer is used as a GPU texture */
-    GPU_TEXTURE                        = 1 << 8,
+    /**
+     * Buffer may be used as a GPU texture
+     *
+     * Buffers allocated with this flag must be
+     * texturable both in EGL/GL & Vulkan via
+     * their respective external memory extensions
+     */
+    GPU_TEXTURE = 1 << 8,
 
-    /** buffer is used as a GPU render target */
-    GPU_RENDER_TARGET                  = 1 << 9,
+    /**
+     * Buffer may be used as a GPU render target
+     *
+     * Buffers allocated with this flag must be
+     * renderable both in EGL/GL & Vulkan via
+     * their respective external memory extensions
+     */
+    GPU_RENDER_TARGET = 1 << 9,
 
     /** bit 10 must be zero */
 
     /** buffer is used as a composer HAL overlay layer */
-    COMPOSER_OVERLAY                   = 1 << 11,
+    COMPOSER_OVERLAY = 1 << 11,
     /** buffer is used as a composer HAL client target */
-    COMPOSER_CLIENT_TARGET             = 1 << 12,
+    COMPOSER_CLIENT_TARGET = 1 << 12,
 
     /** bit 13 must be zero */
 
@@ -61,86 +73,86 @@
      * contents (or information derived from the contents) into unprotected
      * memory.
      */
-    PROTECTED                          = 1 << 14,
+    PROTECTED = 1 << 14,
 
     /** buffer is used as a hwcomposer HAL cursor layer */
-    COMPOSER_CURSOR                    = 1 << 15,
+    COMPOSER_CURSOR = 1 << 15,
 
     /** buffer is used as a video encoder input */
-    VIDEO_ENCODER                      = 1 << 16,
+    VIDEO_ENCODER = 1 << 16,
 
     /** buffer is used as a camera HAL output */
-    CAMERA_OUTPUT                      = 1 << 17,
+    CAMERA_OUTPUT = 1 << 17,
 
     /** buffer is used as a camera HAL input */
-    CAMERA_INPUT                       = 1 << 18,
+    CAMERA_INPUT = 1 << 18,
 
     /** bit 19 must be zero */
 
     /** buffer is used as a renderscript allocation */
-    RENDERSCRIPT                       = 1 << 20,
+    RENDERSCRIPT = 1 << 20,
 
     /** bit 21 must be zero */
 
     /** buffer is used as a video decoder output */
-    VIDEO_DECODER                      = 1 << 22,
+    VIDEO_DECODER = 1 << 22,
 
     /** buffer is used as a sensor direct report output */
-    SENSOR_DIRECT_DATA                 = 1 << 23,
+    SENSOR_DIRECT_DATA = 1 << 23,
 
     /**
      * buffer is used as as an OpenGL shader storage or uniform
      * buffer object
      */
-    GPU_DATA_BUFFER                    = 1 << 24,
+    GPU_DATA_BUFFER = 1 << 24,
 
     /** buffer is used as a cube map texture */
-    GPU_CUBE_MAP                       = 1 << 25,
+    GPU_CUBE_MAP = 1 << 25,
 
     /** buffer contains a complete mipmap hierarchy */
-    GPU_MIPMAP_COMPLETE                = 1 << 26,
+    GPU_MIPMAP_COMPLETE = 1 << 26,
 
     /**
      * Buffer is used as input for HEIC encoder.
      */
-    HW_IMAGE_ENCODER                   = 1 << 27,
+    HW_IMAGE_ENCODER = 1 << 27,
 
     /* Bits 28-31 are reserved for vendor usage */
 
     /**
-    * Buffer is used for front-buffer rendering.
-    *
-    * To satisfy an allocation with this usage, the resulting buffer
-    * must operate as equivalent to shared memory for all targets.
-    *
-    * For CPU_USAGE_* other than NEVER, this means the buffer must
-    * "lock in place". The buffers must be directly accessible via mapping.
-    *
-    * For GPU_RENDER_TARGET the buffer must behave equivalent to a
-    * single-buffered EGL surface. For example glFlush must perform
-    * a flush, same as if the default framebuffer was single-buffered.
-    *
-    * For COMPOSER_* the HWC must not perform any caching for this buffer
-    * when submitted for composition. HWCs do not need to do any form
-    * of auto-refresh, and they are allowed to cache composition results between
-    * presents from SF (such as for panel self-refresh), but for any given
-    * present the buffer must be composited from even if it otherwise appears
-    * to be the same as a previous composition.
-    *
-    * If the GPU & HWC supports EGL_SINGLE_BUFFER, then it is recommended that
-    * FRONT_BUFFER usage is supported for the same formats as supported by
-    * EGL_SINGLE_BUFFER. In particular, it is recommended that the following
-    * combination is supported when possible:
-    *    Format = RGBA_8888
-    *    Usage = FRONT_BUFFER | GPU_RENDER_TARGET | COMPOSER_OVERLAY
-    *
-    */
-    FRONT_BUFFER                       = 1L << 32,
+     * Buffer is used for front-buffer rendering.
+     *
+     * To satisfy an allocation with this usage, the resulting buffer
+     * must operate as equivalent to shared memory for all targets.
+     *
+     * For CPU_USAGE_* other than NEVER, this means the buffer must
+     * "lock in place". The buffers must be directly accessible via mapping.
+     *
+     * For GPU_RENDER_TARGET the buffer must behave equivalent to a
+     * single-buffered EGL surface. For example glFlush must perform
+     * a flush, same as if the default framebuffer was single-buffered.
+     *
+     * For COMPOSER_* the HWC must not perform any caching for this buffer
+     * when submitted for composition. HWCs do not need to do any form
+     * of auto-refresh, and they are allowed to cache composition results between
+     * presents from SF (such as for panel self-refresh), but for any given
+     * present the buffer must be composited from even if it otherwise appears
+     * to be the same as a previous composition.
+     *
+     * If the GPU & HWC supports EGL_SINGLE_BUFFER, then it is recommended that
+     * FRONT_BUFFER usage is supported for the same formats as supported by
+     * EGL_SINGLE_BUFFER. In particular, it is recommended that the following
+     * combination is supported when possible:
+     *    Format = RGBA_8888
+     *    Usage = FRONT_BUFFER | GPU_RENDER_TARGET | COMPOSER_OVERLAY
+     *
+     */
+    FRONT_BUFFER = 1L << 32,
 
     /** bits 28-31 are reserved for vendor extensions */
-    VENDOR_MASK                        = 0xf << 28,
+    VENDOR_MASK = 0xf << 28,
 
     /** bits 33-47 must be zero and are reserved for future versions */
     /** bits 48-63 are reserved for vendor extensions */
-    VENDOR_MASK_HI                     = (1L * 0xffff) << 48,
+    VENDOR_MASK_HI = (1L * 0xffff) << 48,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl
index ac44853..7da45da 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl
@@ -37,4 +37,12 @@
      * Cb and Cr are vertically sited interstitially.
      * This is used by 4:2:0 for MPEG-2 frame pictures. */
     COSITED_HORIZONTAL = 3,
+
+    /* Cb and Cr are horizontally sited interstitially with a luma sample.
+     * Cb and Cr are vertically sited coincident. */
+    COSITED_VERTICAL = 4,
+
+    /* Cb and Cr are both horizontally & vertically sited coincident
+     * with a luma sample. */
+    COSITED_BOTH = 5,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
index 3ff0a65..4b6613e 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
@@ -23,11 +23,26 @@
     /**
      * Default-assumption data space, when not explicitly specified.
      *
-     * It is safest to assume the buffer is an image with sRGB primaries and
-     * encoding ranges, but the consumer and/or the producer of the data may
-     * simply be using defaults. No automatic gamma transform should be
-     * expected, except for a possible display gamma transform when drawn to a
-     * screen.
+     * IAllocator implementations must not assume a particular dataspace interpretation when
+     * allocating a buffer. That is, the dataspace stored on a buffer's metadata must
+     * explicitly be UNKNOWN at the time of allocation. All other vendor implementations (for
+     * example, IComposer) are suggested to assume that the buffer is an image that conforms
+     * to the recommendations outlined by STANDARD_UNSPECIFIED, TRANSFER_UNSPECIFIED, and
+     * RANGE_UNSPECIFIED in order to avoid obviously-broken behavior.
+     *
+     * This means:
+     * - RGB buffers may be assumed to follow sRGB (IEC 61966-2.1)
+     * - YCbCr buffers smaller than 720p may be assumed to follow BT. 601-7
+     * - YCbCr buffers at least 720p may be assumed to follow BT. 709-6
+     * - Y buffers are full range with an undefined transfer and primaries
+     * - All other buffer formats may be treated in an implementation-defined manner
+     *
+     * It is the framework's - and application's - responsibility to communicate
+     * an accurate dataspace for any buffers throughout the system to guarantee
+     * well-defined behavior. For the framework, this means translating UNKNOWN
+     * dataspaces to a chosen default, and setting gralloc metadata on the buffer
+     * accordingly. For the application, this means signaling a defined dataspace
+     * to any framework apis.
      */
     UNKNOWN = 0x0,
 
diff --git a/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
index 50306dc..ac95b1c 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -20,11 +20,13 @@
 import android.hardware.graphics.common.HardwareBufferDescription;
 
 /**
- * Stable AIDL counterpart of AHardwareBuffer.
+ * [Deprecated] Stable AIDL counterpart of AHardwareBuffer.
  *
- * @note This is different from the public HardwareBuffer.
- * @sa +ndk libnativewindow#AHardwareBuffer
+ * @note This is different from the public HardwareBuffer. As the public
+         HardwareBuffer now supports being used in stable-aidl interfaces,
+         that is strongly preferred for new usages.
  * @hide
+ * @deprecated: Use instead android.hardware.HardwareBuffer in frameworks/base
  */
 @VintfStability
 parcelable HardwareBuffer {
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index 499d3b9..336d15d 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -679,6 +679,10 @@
 
     uint32_t read() { return mData[mDataRead++]; }
 
+    bool isReadSizeValid(uint32_t size) const {
+        return mDataRead * sizeof(uint32_t) + size <= mDataSize;
+    }
+
     int32_t readSigned() {
         int32_t val;
         memcpy(&val, &mData[mDataRead++], sizeof(val));
@@ -760,7 +764,7 @@
     std::unique_ptr<uint32_t[]> mData;
     uint32_t mDataRead;
 
-   private:
+  private:
     std::unique_ptr<CommandQueueType> mQueue;
     uint32_t mDataMaxSize;
 
diff --git a/graphics/composer/2.1/utils/resources/Android.bp b/graphics/composer/2.1/utils/resources/Android.bp
index 9eb23fa..4052003 100644
--- a/graphics/composer/2.1/utils/resources/Android.bp
+++ b/graphics/composer/2.1/utils/resources/Android.bp
@@ -29,20 +29,15 @@
     vendor_available: true,
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
         "libcutils",
         "libhardware", // TODO remove hwcomposer2.h dependency
         "libhidlbase",
         "liblog",
+        "libui",
         "libutils",
     ],
     export_shared_lib_headers: [
         "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
         "libhardware",
         "libhidlbase",
         "liblog",
diff --git a/graphics/composer/2.1/utils/resources/ComposerResources.cpp b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
index e52bf71..80bfb7a 100644
--- a/graphics/composer/2.1/utils/resources/ComposerResources.cpp
+++ b/graphics/composer/2.1/utils/resources/ComposerResources.cpp
@@ -18,6 +18,8 @@
 
 #include "composer-resources/2.1/ComposerResources.h"
 
+#include <ui/GraphicBufferMapper.h>
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -25,23 +27,10 @@
 namespace V2_1 {
 namespace hal {
 
+ComposerHandleImporter::ComposerHandleImporter() : mMapper{GraphicBufferMapper::get()} {}
+
 bool ComposerHandleImporter::init() {
-    mMapper4 = mapper::V4_0::IMapper::getService();
-    if (mMapper4) {
-        return true;
-    }
-    ALOGI_IF(!mMapper4, "failed to get mapper 4.0 service, falling back to mapper 3.0");
-
-    mMapper3 = mapper::V3_0::IMapper::getService();
-    if (mMapper3) {
-        return true;
-    }
-    ALOGI_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");
-
-    mMapper2 = mapper::V2_0::IMapper::getService();
-    ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
-
-    return mMapper2 != nullptr;
+    return true;
 }
 
 Error ComposerHandleImporter::importBuffer(const native_handle_t* rawHandle,
@@ -51,51 +40,17 @@
         return Error::NONE;
     }
 
-    const native_handle_t* bufferHandle;
-    if (mMapper2) {
-        mapper::V2_0::Error error;
-        mMapper2->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
-            error = tmpError;
-            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
-        });
-        if (error != mapper::V2_0::Error::NONE) {
-            return Error::NO_RESOURCES;
-        }
+    status_t status = mMapper.importBufferNoValidate(rawHandle, outBufferHandle);
+    if (status == STATUS_OK) {
+        return Error::NONE;
+    } else {
+        return Error::NO_RESOURCES;
     }
-    if (mMapper3) {
-        mapper::V3_0::Error error;
-        mMapper3->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
-            error = tmpError;
-            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
-        });
-        if (error != mapper::V3_0::Error::NONE) {
-            return Error::NO_RESOURCES;
-        }
-    }
-    if (mMapper4) {
-        mapper::V4_0::Error error;
-        mMapper4->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
-            error = tmpError;
-            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
-        });
-        if (error != mapper::V4_0::Error::NONE) {
-            return Error::NO_RESOURCES;
-        }
-    }
-
-    *outBufferHandle = bufferHandle;
-    return Error::NONE;
 }
 
 void ComposerHandleImporter::freeBuffer(const native_handle_t* bufferHandle) {
     if (bufferHandle) {
-        if (mMapper2) {
-            mMapper2->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
-        } else if (mMapper3) {
-            mMapper3->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
-        } else if (mMapper4) {
-            mMapper4->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
-        }
+        mMapper.freeBuffer(bufferHandle);
     }
 }
 
diff --git a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
index de78a59..9838118 100644
--- a/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
@@ -27,12 +27,10 @@
 
 #include <android/hardware/graphics/composer/2.1/types.h>
 
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
 #include <log/log.h>
 
 namespace android {
+class GraphicBufferMapper;
 namespace hardware {
 namespace graphics {
 namespace composer {
@@ -42,6 +40,7 @@
 // wrapper for IMapper to import buffers and sideband streams
 class ComposerHandleImporter {
   public:
+    ComposerHandleImporter();
     bool init();
 
     Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle);
@@ -50,9 +49,7 @@
     void freeStream(const native_handle_t* streamHandle);
 
   private:
-    sp<mapper::V2_0::IMapper> mMapper2;
-    sp<mapper::V3_0::IMapper> mMapper3;
-    sp<mapper::V4_0::IMapper> mMapper4;
+    GraphicBufferMapper& mMapper;
 };
 
 class ComposerHandleCache {
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
index 7b6a0e6..3bc127f 100644
--- a/graphics/composer/2.1/utils/vts/Android.bp
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -26,7 +26,6 @@
 cc_library_static {
     name: "android.hardware.graphics.composer@2.1-vts",
     defaults: [
-        "android.hardware.graphics.allocator-ndk_static",
         "hidl_defaults",
     ],
     srcs: [
@@ -34,18 +33,15 @@
         "GraphicsComposerCallback.cpp",
         "TestCommandReader.cpp",
     ],
+    shared_libs: [
+        "libui",
+    ],
     static_libs: [
         "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libgtest",
     ],
     export_static_lib_headers: [
         "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 4603dd1..8b89784 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -308,113 +308,6 @@
     writer->reset();
 }
 
-NativeHandleWrapper::~NativeHandleWrapper() {
-    if (mHandle) {
-        mGralloc.freeBuffer(mHandle);
-    }
-}
-
-Gralloc::Gralloc() {
-    [this] {
-        ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>(
-                                        /*aidlAllocatorServiceName*/ IAllocator::descriptor +
-                                                std::string("/default"),
-                                        /*hidlAllocatorServiceName*/ "default",
-                                        /*mapperServiceName*/ "default",
-                                        /*errOnFailure=*/false));
-        if (!mGralloc4->hasAllocator() || mGralloc4->getMapper() == nullptr) {
-            mGralloc4 = nullptr;
-            ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
-                                                                           /*errOnFailure=*/false));
-            if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) {
-                mGralloc3 = nullptr;
-                ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
-            }
-        }
-    }();
-}
-
-const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                            PixelFormat format, uint64_t usage, bool import,
-                                            uint32_t* outStride) {
-    const native_handle_t* handle;
-    if (mGralloc4) {
-        IMapper4::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        info.usage = usage;
-        handle = mGralloc4->allocate(info, import, outStride);
-    } else if (mGralloc3) {
-        IMapper3::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        info.usage = usage;
-        handle = mGralloc3->allocate(info, import, outStride);
-    } else {
-        IMapper2::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = format;
-        info.usage = usage;
-        handle = mGralloc2->allocate(info, import, outStride);
-    }
-    return NativeHandleWrapper(*this, handle);
-}
-
-void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-                    const AccessRegion& accessRegionRect, int acquireFence) {
-    if (mGralloc4) {
-        IMapper4::Rect accessRegion;
-        accessRegion.left = accessRegionRect.left;
-        accessRegion.top = accessRegionRect.top;
-        accessRegion.width = accessRegionRect.width;
-        accessRegion.height = accessRegionRect.height;
-        return mGralloc4->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
-    } else if (mGralloc3) {
-        IMapper3::Rect accessRegion;
-        accessRegion.left = accessRegionRect.left;
-        accessRegion.top = accessRegionRect.top;
-        accessRegion.width = accessRegionRect.width;
-        accessRegion.height = accessRegionRect.height;
-        int32_t bytesPerPixel;
-        int32_t bytesPerStride;
-        return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel,
-                               &bytesPerStride);
-    } else {
-        IMapper2::Rect accessRegion;
-        accessRegion.left = accessRegionRect.left;
-        accessRegion.top = accessRegionRect.top;
-        accessRegion.width = accessRegionRect.width;
-        accessRegion.height = accessRegionRect.height;
-        return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
-    }
-}
-
-int Gralloc::unlock(const native_handle_t* bufferHandle) {
-    if (mGralloc4) {
-        return mGralloc4->unlock(bufferHandle);
-    } else if (mGralloc3) {
-        return mGralloc3->unlock(bufferHandle);
-    } else {
-        return mGralloc2->unlock(bufferHandle);
-    }
-}
-
-void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
-    if (mGralloc4) {
-        mGralloc4->freeBuffer(bufferHandle);
-    } else if (mGralloc3) {
-        mGralloc3->freeBuffer(bufferHandle);
-    } else {
-        mGralloc2->freeBuffer(bufferHandle);
-    }
-}
-
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index f8ea661..c0aacb5 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -25,9 +25,6 @@
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/TestCommandReader.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
 #include <utils/StrongPointer.h>
 
 #include "gtest/gtest.h"
@@ -43,13 +40,6 @@
 using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::Hdr;
 using android::hardware::graphics::common::V1_0::PixelFormat;
-using IMapper2 = android::hardware::graphics::mapper::V2_0::IMapper;
-using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
-using IMapper4 = android::hardware::graphics::mapper::V4_0::IMapper;
-using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
-using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
-using Gralloc4 = android::hardware::graphics::mapper::V4_0::vts::Gralloc;
-using IAllocator = aidl::android::hardware::graphics::allocator::IAllocator;
 
 class ComposerClient;
 
@@ -129,52 +119,6 @@
     const sp<IComposerClient> mClient;
 };
 
-class AccessRegion {
-  public:
-    int32_t left;
-    int32_t top;
-    int32_t width;
-    int32_t height;
-};
-
-class Gralloc;
-
-// RAII wrapper around native_handle_t*
-class NativeHandleWrapper {
-  public:
-    NativeHandleWrapper(Gralloc& gralloc, const native_handle_t* handle)
-        : mGralloc(gralloc), mHandle(handle) {}
-
-    ~NativeHandleWrapper();
-
-    const native_handle_t* get() { return mHandle; }
-
-  private:
-    Gralloc& mGralloc;
-    const native_handle_t* mHandle;
-};
-
-class Gralloc {
-  public:
-    explicit Gralloc();
-
-    const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                       PixelFormat format, uint64_t usage, bool import = true,
-                                       uint32_t* outStride = nullptr);
-
-    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-               const AccessRegion& accessRegionRect, int acquireFence);
-
-    int unlock(const native_handle_t* bufferHandle);
-
-    void freeBuffer(const native_handle_t* bufferHandle);
-
-  protected:
-    std::shared_ptr<Gralloc2> mGralloc2 = nullptr;
-    std::shared_ptr<Gralloc3> mGralloc3 = nullptr;
-    std::shared_ptr<Gralloc4> mGralloc4 = nullptr;
-};
-
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 0f6d7e8..0706341 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -27,7 +27,6 @@
     name: "VtsHalGraphicsComposerV2_1TargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
-        "android.hardware.graphics.allocator-ndk_static",
     ],
     tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
@@ -38,22 +37,12 @@
         "libbinder_ndk",
         "libfmq",
         "libsync",
+        "libui",
         "android.hardware.common-V2-ndk",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libaidlcommonsupport",
     ],
     header_libs: [
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 9444d89..b67cfc2 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -25,9 +25,7 @@
 #include <hardware/hwcomposer2.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
 
 #include <unistd.h>
 
@@ -52,7 +50,6 @@
 using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
-using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
@@ -651,7 +648,6 @@
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
         Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
         mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
                                                              IComposerClient::Attribute::WIDTH);
@@ -666,13 +662,17 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    NativeHandleWrapper allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
+    sp<GraphicBuffer> allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
 
-    NativeHandleWrapper allocate(uint32_t width, uint32_t height) {
-        uint64_t usage =
+    sp<GraphicBuffer> allocate(int32_t width, int32_t height) {
+        auto result = sp<GraphicBuffer>::make(
+                width, height, static_cast<int32_t>(PixelFormat::RGBA_8888), /*layerCount*/ 1,
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
-                                      BufferUsage::COMPOSER_OVERLAY);
-        return mGralloc->allocate(width, height, 1, PixelFormat::RGBA_8888, usage);
+                                      BufferUsage::COMPOSER_OVERLAY));
+        if (result->initCheck() != STATUS_OK) {
+            return nullptr;
+        }
+        return result;
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -681,9 +681,6 @@
     std::unique_ptr<TestCommandReader> mReader;
     int32_t mDisplayWidth;
     int32_t mDisplayHeight;
-
-   private:
-     std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
@@ -729,11 +726,11 @@
         display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
                                                         kBufferSlotCount, &format));
 
-    std::unique_ptr<NativeHandleWrapper> handle;
-    ASSERT_NO_FATAL_FAILURE(handle.reset(new NativeHandleWrapper(allocate())));
+    auto handle = allocate();
+    ASSERT_TRUE(handle);
 
     mWriter->selectDisplay(display);
-    mWriter->setOutputBuffer(0, handle->get(), -1);
+    mWriter->setOutputBuffer(0, handle->handle, -1);
     execute();
 }
 
@@ -802,7 +799,7 @@
     mWriter->setLayerZOrder(10);
     mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
     mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
-    mWriter->setLayerBuffer(0, handle.get(), -1);
+    mWriter->setLayerBuffer(0, handle->handle, -1);
     mWriter->setLayerDataspace(Dataspace::UNKNOWN);
 
     mWriter->validateDisplay();
@@ -820,7 +817,7 @@
     mWriter->selectLayer(layer);
     auto handle2 = allocate();
     ASSERT_NE(nullptr, handle2.get());
-    mWriter->setLayerBuffer(0, handle2.get(), -1);
+    mWriter->setLayerBuffer(0, handle2->handle, -1);
     mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
     mWriter->presentDisplay();
     execute();
@@ -840,7 +837,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(0, handle.get(), -1);
+    mWriter->setLayerBuffer(0, handle->handle, -1);
     mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
     mWriter->setLayerDisplayFrame(displayFrame);
     mWriter->setLayerPlaneAlpha(1);
@@ -881,7 +878,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(0, handle.get(), -1);
+    mWriter->setLayerBuffer(0, handle->handle, -1);
     execute();
 }
 
@@ -905,7 +902,7 @@
     mWriter->selectLayer(layer);
     mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
     mWriter->setLayerDisplayFrame(displayFrame);
-    mWriter->setLayerBuffer(0, handle1.get(), -1);
+    mWriter->setLayerBuffer(0, handle1->handle, -1);
     mWriter->setLayerDataspace(Dataspace::UNKNOWN);
     mWriter->validateDisplay();
     execute();
@@ -928,7 +925,7 @@
     mWriter->selectLayer(layer);
     mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
     mWriter->setLayerDisplayFrame(displayFrame);
-    mWriter->setLayerBuffer(1, handle2.get(), -1);
+    mWriter->setLayerBuffer(1, handle2->handle, -1);
     mWriter->setLayerDataspace(Dataspace::UNKNOWN);
     mWriter->validateDisplay();
     execute();
@@ -951,7 +948,7 @@
     mWriter->selectLayer(layer);
     mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
     mWriter->setLayerDisplayFrame(displayFrame);
-    mWriter->setLayerBuffer(2, handle3.get(), -1);
+    mWriter->setLayerBuffer(2, handle3->handle, -1);
     mWriter->setLayerDataspace(Dataspace::UNKNOWN);
     mWriter->validateDisplay();
     execute();
@@ -968,10 +965,10 @@
     // Ensure we can clear multiple buffer slots and then restore the active buffer at the end
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(0, clearSlotBuffer.get(), -1);
+    mWriter->setLayerBuffer(0, clearSlotBuffer->handle, -1);
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(1, clearSlotBuffer.get(), -1);
+    mWriter->setLayerBuffer(1, clearSlotBuffer->handle, -1);
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
     mWriter->setLayerBuffer(2, nullptr, -1);
@@ -1113,7 +1110,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerSidebandStream(handle.get());
+    mWriter->setLayerSidebandStream(handle->handle);
     execute();
 }
 
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index d11592f..a923923 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -26,7 +26,6 @@
 cc_library_static {
     name: "android.hardware.graphics.composer@2.2-vts",
     defaults: [
-        "android.hardware.graphics.allocator-ndk_static",
         "android.hardware.graphics.composer3-ndk_static",
         "hidl_defaults",
         "librenderengine_deps",
@@ -42,7 +41,6 @@
     static_libs: [
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
-        "android.hardware.graphics.mapper@2.1-vts",
         "libarect",
         "libgtest",
         "libmath",
@@ -50,15 +48,10 @@
         "librenderengine",
         "libshaders",
         "libtonemap",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0",
-        "android.hardware.graphics.mapper@4.0-vts",
     ],
     export_static_lib_headers: [
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
-        "android.hardware.graphics.mapper@2.1-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.2-command-buffer",
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index d4f0281..d041064 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -179,66 +179,6 @@
     return matrix;
 }
 
-Gralloc::Gralloc() {
-    [this] {
-        ALOGD("Attempting to initialize gralloc4");
-        ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>(
-                                        /*aidlAllocatorServiceName*/ IAllocator::descriptor +
-                                                std::string("/default"),
-                                        /*hidlAllocatorServiceName*/ "default",
-                                        /*mapperServiceName*/ "default",
-                                        /*errOnFailure=*/false));
-        if (mGralloc4->getMapper() == nullptr || !mGralloc4->hasAllocator()) {
-            mGralloc4 = nullptr;
-            ALOGD("Failed to initialize gralloc4, initializing gralloc3");
-            ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
-                                                                           /*errOnFailure=*/false));
-            if (mGralloc3->getMapper() == nullptr || mGralloc3->getAllocator() == nullptr) {
-                mGralloc3 = nullptr;
-                ALOGD("Failed to initialize gralloc3, initializing gralloc2_1");
-                mGralloc2_1 = std::make_shared<Gralloc2_1>(/*errOnFailure*/ false);
-                if (!mGralloc2_1->getMapper()) {
-                    mGralloc2_1 = nullptr;
-                    ALOGD("Failed to initialize gralloc2_1, initializing gralloc2");
-                    ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
-                }
-            }
-        }
-    }();
-}
-
-bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle, uint32_t width,
-                                 uint32_t height, uint32_t layerCount, PixelFormat format,
-                                 uint64_t usage, uint32_t stride) {
-    if (mGralloc4) {
-        IMapper4::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        info.usage = usage;
-        return mGralloc4->validateBufferSize(bufferHandle, info, stride);
-    } else if (mGralloc3) {
-        IMapper3::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        info.usage = usage;
-        return mGralloc3->validateBufferSize(bufferHandle, info, stride);
-    } else if (mGralloc2_1) {
-        IMapper2_1::BufferDescriptorInfo info{};
-        info.width = width;
-        info.height = height;
-        info.layerCount = layerCount;
-        info.format = static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format);
-        info.usage = usage;
-        return mGralloc2_1->validateBufferSize(bufferHandle, info, stride);
-    } else {
-        return true;
-    }
-}
-
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index a1794af..9ba34f1 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -187,12 +187,11 @@
 }
 
 ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
-                               const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
-                               uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
+                               uint32_t width, uint32_t height, PixelFormat pixelFormat,
+                               Dataspace dataspace) {
     mDisplay = display;
 
     mComposerClient = client;
-    mGralloc = gralloc;
 
     mPixelFormat = pixelFormat;
     mDataspace = dataspace;
@@ -202,20 +201,12 @@
     mLayerCount = 1;
     mFormat = mPixelFormat;
     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
-
-    mAccessRegion.top = 0;
-    mAccessRegion.left = 0;
-    mAccessRegion.width = width;
-    mAccessRegion.height = height;
 }
 
 void ReadbackBuffer::setReadbackBuffer() {
-    mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
-            mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                               /*import*/ true, &mStride)));
-    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
-                                                  mLayerCount, mFormat, mUsage, mStride));
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
+    mBuffer = sp<GraphicBuffer>::make(mWidth, mHeight, (int32_t)mFormat, mLayerCount, mUsage);
+    ASSERT_EQ(STATUS_OK, mBuffer->initCheck());
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBuffer->handle, -1));
 }
 
 void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
@@ -223,15 +214,14 @@
     int32_t fenceHandle;
     ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
 
-    void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
+    void* bufData = nullptr;
+    int32_t stride = mBuffer->stride;
+    status_t status = mBuffer->lockAsync(mUsage, &bufData, fenceHandle);
+    ASSERT_EQ(STATUS_OK, status);
     ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
-    ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
+    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
                                         mPixelFormat);
-    int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
-    if (unlockFence != -1) {
-        sync_wait(unlockFence, -1);
-        close(unlockFence);
-    }
+    EXPECT_EQ(STATUS_OK, mBuffer->unlock());
 }
 
 void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
@@ -251,12 +241,10 @@
 }
 
 TestBufferLayer::TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
-                                 const std::shared_ptr<Gralloc>& gralloc,
                                  TestRenderEngine& renderEngine, Display display, int32_t width,
                                  int32_t height, PixelFormat format,
                                  IComposerClient::Composition composition)
     : TestLayer{client, display}, mRenderEngine(renderEngine) {
-    mGralloc = gralloc;
     mComposition = composition;
     mWidth = width;
     mHeight = height;
@@ -265,11 +253,6 @@
     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
                                    BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE);
 
-    mAccessRegion.top = 0;
-    mAccessRegion.left = 0;
-    mAccessRegion.width = width;
-    mAccessRegion.height = height;
-
     setSourceCrop({0, 0, (float)width, (float)height});
 }
 
@@ -277,15 +260,13 @@
     TestLayer::write(writer);
     writer->setLayerCompositionType(mComposition);
     writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
-    if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence);
+    if (mBuffer) writer->setLayerBuffer(0, mBuffer->handle, -1);
 }
 
 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
     layerSettings.source.buffer.buffer = std::make_shared<renderengine::impl::ExternalTexture>(
-            new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
-                              static_cast<int32_t>(mFormat), 1, mUsage, mStride),
-            mRenderEngine.getInternalRenderEngine(),
+            mBuffer, mRenderEngine.getInternalRenderEngine(),
             renderengine::impl::ExternalTexture::Usage::READABLE);
 
     layerSettings.source.buffer.usePremultipliedAlpha =
@@ -304,24 +285,18 @@
 }
 
 void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
-    void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1);
-    ASSERT_NO_FATAL_FAILURE(
-            ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
-    mFillFence = mGralloc->unlock(mBufferHandle->get());
-    if (mFillFence != -1) {
-        sync_wait(mFillFence, -1);
-        close(mFillFence);
-    }
+    void* bufData = nullptr;
+    status_t status = mBuffer->lock(mUsage, &bufData);
+    ASSERT_EQ(STATUS_OK, status);
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, mBuffer->stride, bufData,
+                                                       mFormat, expectedColors));
+    EXPECT_EQ(STATUS_OK, mBuffer->unlock());
 }
 
 void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
-    mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
-            mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                               /*import*/ true, &mStride)));
-    ASSERT_NE(nullptr, mBufferHandle->get());
+    mBuffer = sp<GraphicBuffer>::make(mWidth, mHeight, (int32_t)mFormat, mLayerCount, mUsage);
+    ASSERT_EQ(STATUS_OK, mBuffer->initCheck());
     ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
-    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
-                                                  mLayerCount, mFormat, mUsage, mStride));
 }
 
 void TestBufferLayer::setDataspace(Dataspace dataspace,
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 1700b2a..6960d06 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -24,7 +24,6 @@
 namespace V2_2 {
 namespace vts {
 
-using mapper::V2_1::IMapper;
 using renderengine::DisplaySettings;
 using renderengine::LayerSettings;
 using renderengine::RenderEngineCreationArgs;
@@ -72,7 +71,7 @@
     auto texture = std::make_shared<renderengine::impl::ExternalTexture>(
             mGraphicBuffer, *mRenderEngine, renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     auto result = mRenderEngine
-                          ->drawLayers(mDisplaySettings, compositionLayers, texture, true,
+                          ->drawLayers(mDisplaySettings, compositionLayers, texture,
                                        std::move(bufferFence))
                           .get();
     if (result.ok()) {
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 02d7bdb..3e26d94 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -26,7 +26,6 @@
 #include <android/hardware/graphics/composer/2.2/IComposerClient.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -41,14 +40,6 @@
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
-using IMapper2_1 = android::hardware::graphics::mapper::V2_1::IMapper;
-using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
-using IMapper4 = android::hardware::graphics::mapper::V4_0::IMapper;
-using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
-using Gralloc2_1 = android::hardware::graphics::mapper::V2_1::vts::Gralloc;
-using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
-using Gralloc4 = android::hardware::graphics::mapper::V4_0::vts::Gralloc;
-using IAllocator = aidl::android::hardware::graphics::allocator::IAllocator;
 
 class ComposerClient;
 
@@ -92,28 +83,6 @@
     const sp<IComposerClient> mClient;
 };
 
-class Gralloc : public V2_1::vts::Gralloc {
-  public:
-    using NativeHandleWrapper = V2_1::vts::NativeHandleWrapper;
-
-    Gralloc();
-    const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                       PixelFormat format, uint64_t usage, bool import = true,
-                                       uint32_t* outStride = nullptr) {
-        return V2_1::vts::Gralloc::allocate(
-                width, height, layerCount,
-                static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format), usage,
-                import, outStride);
-    }
-
-    bool validateBufferSize(const native_handle_t* bufferHandle, uint32_t width, uint32_t height,
-                            uint32_t layerCount, PixelFormat format, uint64_t usage,
-                            uint32_t stride);
-
-  protected:
-    std::shared_ptr<Gralloc2_1> mGralloc2_1 = nullptr;
-};
-
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
index 58efde9..aa6932a 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -22,7 +22,6 @@
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
 #include <renderengine/RenderEngine.h>
 
 #include <memory>
@@ -38,12 +37,9 @@
 using common::V1_1::BufferUsage;
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
-using IMapper2_1 = mapper::V2_1::IMapper;
-using Gralloc2_1 = mapper::V2_1::vts::Gralloc;
 using renderengine::LayerSettings;
 using V2_1::Display;
 using V2_1::Layer;
-using V2_1::vts::AccessRegion;
 using V2_1::vts::TestCommandReader;
 
 static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
@@ -113,9 +109,8 @@
 class TestBufferLayer : public TestLayer {
   public:
     TestBufferLayer(
-            const std::shared_ptr<ComposerClient>& client, const std::shared_ptr<Gralloc>& gralloc,
-            TestRenderEngine& renderEngine, Display display, int32_t width, int32_t height,
-            PixelFormat format,
+            const std::shared_ptr<ComposerClient>& client, TestRenderEngine& renderEngine,
+            Display display, int32_t width, int32_t height, PixelFormat format,
             IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
 
     void write(const std::shared_ptr<CommandWriterBase>& writer) override;
@@ -135,15 +130,11 @@
     uint32_t mLayerCount;
     PixelFormat mFormat;
     uint64_t mUsage;
-    AccessRegion mAccessRegion;
-    uint32_t mStride;
 
   protected:
     IComposerClient::Composition mComposition;
-    std::shared_ptr<Gralloc> mGralloc;
     TestRenderEngine& mRenderEngine;
-    int32_t mFillFence;
-    std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle;
+    sp<GraphicBuffer> mBuffer;
 };
 
 class ReadbackHelper {
@@ -179,9 +170,8 @@
 
 class ReadbackBuffer {
   public:
-    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
-                   const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
-                   PixelFormat pixelFormat, Dataspace dataspace);
+    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client, uint32_t width,
+                   uint32_t height, PixelFormat pixelFormat, Dataspace dataspace);
 
     void setReadbackBuffer();
 
@@ -193,13 +183,10 @@
     uint32_t mLayerCount;
     PixelFormat mFormat;
     uint64_t mUsage;
-    AccessRegion mAccessRegion;
-    uint32_t mStride;
-    std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle = nullptr;
+    sp<GraphicBuffer> mBuffer;
     PixelFormat mPixelFormat;
     Dataspace mDataspace;
     Display mDisplay;
-    std::shared_ptr<Gralloc> mGralloc;
     std::shared_ptr<ComposerClient> mComposerClient;
 };
 
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
index 26027d3..09b89ff 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/RenderEngineVts.h
@@ -22,7 +22,6 @@
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -34,10 +33,8 @@
 namespace V2_2 {
 namespace vts {
 
-using mapper::V2_1::IMapper;
 using renderengine::DisplaySettings;
 using renderengine::RenderEngineCreationArgs;
-using vts::Gralloc;
 
 class TestRenderEngine {
   public:
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 3476376..a781712 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -27,7 +27,6 @@
     name: "VtsHalGraphicsComposerV2_2TargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
-        "android.hardware.graphics.allocator-ndk_static",
         "android.hardware.graphics.composer3-ndk_static",
         "librenderengine_deps",
     ],
@@ -54,24 +53,13 @@
         "libsync",
         "libui",
         "android.hardware.common-V2-ndk",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.2-vts",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libaidlcommonsupport",
         "libgtest",
         "librenderengine",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index e2a0f4d..74d2f03 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -26,7 +26,6 @@
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -45,9 +44,7 @@
 using common::V1_1::PixelFormat;
 using V2_1::Config;
 using V2_1::Display;
-using V2_1::vts::NativeHandleWrapper;
 using V2_1::vts::TestCommandReader;
-using vts::Gralloc;
 
 class GraphicsCompositionTestBase : public ::testing::Test {
   protected:
@@ -79,20 +76,19 @@
         // set up command writer/reader and gralloc
         mWriter = std::make_shared<CommandWriterBase>(1024);
         mReader = std::make_unique<TestCommandReader>();
-        mGralloc = std::make_shared<Gralloc>();
 
         ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
 
         ASSERT_NO_FATAL_FAILURE(
                 mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
                         renderengine::RenderEngineCreationArgs::Builder()
-                            .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
-                            .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
-                            .setUseColorManagerment(true)
-                            .setEnableProtectedContext(false)
-                            .setPrecacheToneMapperShaderOnly(false)
-                            .setContextPriority(renderengine::RenderEngine::ContextPriority::HIGH)
-                            .build())));
+                                .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
+                                .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
+                                .setEnableProtectedContext(false)
+                                .setPrecacheToneMapperShaderOnly(false)
+                                .setContextPriority(
+                                        renderengine::RenderEngine::ContextPriority::HIGH)
+                                .build())));
 
         renderengine::DisplaySettings clientCompositionDisplay;
         clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
@@ -143,7 +139,6 @@
     std::vector<ColorMode> mTestColorModes;
     std::shared_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
-    std::shared_ptr<Gralloc> mGralloc;
     std::unique_ptr<TestRenderEngine> mTestRenderEngine;
 
     bool mHasReadbackBuffer;
@@ -220,7 +215,7 @@
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -272,7 +267,7 @@
 
         mWriter->selectDisplay(mPrimaryDisplay);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
@@ -285,9 +280,9 @@
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
                                        BLUE);
 
-        auto layer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
-                mDisplayHeight, PixelFormat::RGBA_8888);
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+                                                       mPrimaryDisplay, mDisplayWidth,
+                                                       mDisplayHeight, PixelFormat::RGBA_8888);
         layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
         layer->setZOrder(10);
         layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -352,15 +347,16 @@
         // This following buffer call should have no effect
         uint64_t usage =
                 static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
-        NativeHandleWrapper bufferHandle =
-                mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
-        mWriter->setLayerBuffer(0, bufferHandle.get(), -1);
+        sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(
+                mDisplayWidth, mDisplayHeight, (int32_t)PixelFormat::RGBA_8888, 1, usage);
+        ASSERT_EQ(STATUS_OK, buffer->initCheck());
+        mWriter->setLayerBuffer(0, buffer->handle, -1);
 
         // expected color for each pixel
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -419,16 +415,16 @@
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
                                        BLUE);
 
-        auto layer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
-                mDisplayHeight, PixelFormat::RGBA_FP16);
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+                                                       mPrimaryDisplay, mDisplayWidth,
+                                                       mDisplayHeight, PixelFormat::RGBA_FP16);
         layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
         layer->setZOrder(10);
         layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
@@ -462,25 +458,20 @@
             }
 
             // create client target buffer
-            uint32_t clientStride;
-            NativeHandleWrapper clientBufferHandle =
-                    mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount,
-                                       clientFormat, clientUsage, /*import*/ true, &clientStride);
-            ASSERT_NE(nullptr, clientBufferHandle.get());
+            sp<GraphicBuffer> clientBuffer =
+                    sp<GraphicBuffer>::make(layer->mWidth, layer->mHeight, (int32_t)clientFormat,
+                                            layer->mLayerCount, clientUsage);
+            ASSERT_EQ(STATUS_OK, clientBuffer->initCheck());
 
-            void* clientBufData =
-                    mGralloc->lock(clientBufferHandle.get(), clientUsage, layer->mAccessRegion, -1);
+            void* clientBufData = nullptr;
+            ASSERT_EQ(STATUS_OK, clientBuffer->lock(clientUsage, &clientBufData));
 
             ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight,
-                                                               clientStride, clientBufData,
+                                                               clientBuffer->stride, clientBufData,
                                                                clientFormat, expectedColors));
-            int clientFence = mGralloc->unlock(clientBufferHandle.get());
-            if (clientFence != -1) {
-                sync_wait(clientFence, -1);
-                close(clientFence);
-            }
+            clientBuffer->unlock();
 
-            mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
+            mWriter->setClientTarget(0, clientBuffer->handle, -1, clientDataspace,
                                      std::vector<IComposerClient::Rect>(1, damage));
 
             layer->setToClientComposition(mWriter);
@@ -531,12 +522,12 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         auto deviceLayer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
+                mComposerClient, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
                 mDisplayHeight / 2, PixelFormat::RGBA_8888);
         std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth *
                                                          deviceLayer->mHeight);
@@ -573,8 +564,8 @@
         }
 
         auto clientLayer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, clientWidth,
-                clientHeight, PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
+                mComposerClient, *mTestRenderEngine, mPrimaryDisplay, clientWidth, clientHeight,
+                PixelFormat::RGBA_FP16, IComposerClient::Composition::DEVICE);
         IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
         clientLayer->setDisplayFrame(clientFrame);
         clientLayer->setZOrder(0);
@@ -590,27 +581,22 @@
         }
         // create client target buffer
         ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
-        uint32_t clientStride;
-        NativeHandleWrapper clientBufferHandle =
-                mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount,
-                                   clientFormat, clientUsage, /*import*/ true, &clientStride);
-        ASSERT_NE(nullptr, clientBufferHandle.get());
+        sp<GraphicBuffer> clientBuffer =
+                sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight, (int32_t)clientFormat,
+                                        clientLayer->mLayerCount, clientUsage);
+        ASSERT_EQ(STATUS_OK, clientBuffer->initCheck());
 
-        void* clientBufData = mGralloc->lock(clientBufferHandle.get(), clientUsage,
-                                             {0, 0, mDisplayWidth, mDisplayHeight}, -1);
+        void* clientBufData = nullptr;
+        ASSERT_EQ(STATUS_OK, clientBuffer->lock(clientUsage, &clientBufData));
 
         std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
         ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight,
-                                                           clientStride, clientBufData,
+                                                           clientBuffer->stride, clientBufData,
                                                            clientFormat, clientColors));
-        int clientFence = mGralloc->unlock(clientBufferHandle.get());
-        if (clientFence != -1) {
-            sync_wait(clientFence, -1);
-            close(clientFence);
-        }
+        EXPECT_EQ(STATUS_OK, clientBuffer->unlock());
 
-        mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
+        mWriter->setClientTarget(0, clientBuffer->handle, -1, clientDataspace,
                                  std::vector<IComposerClient::Rect>(1, clientFrame));
         clientLayer->setToClientComposition(mWriter);
         mWriter->validateDisplay();
@@ -655,9 +641,9 @@
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
 
-        auto layer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
-                mDisplayHeight, PixelFormat::RGBA_8888);
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+                                                       mPrimaryDisplay, mDisplayWidth,
+                                                       mDisplayHeight, PixelFormat::RGBA_8888);
         layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
         layer->setZOrder(10);
         layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -665,7 +651,7 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -742,7 +728,7 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
 
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
@@ -803,9 +789,9 @@
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight},
                                        BLUE);
 
-        auto layer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
-                mDisplayHeight, PixelFormat::RGBA_8888);
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+                                                       mPrimaryDisplay, mDisplayWidth,
+                                                       mDisplayHeight, PixelFormat::RGBA_8888);
         layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
         layer->setZOrder(10);
         layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -819,7 +805,7 @@
         // update expected colors to match crop
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
@@ -886,7 +872,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -955,9 +941,9 @@
         backgroundLayer->setZOrder(0);
         backgroundLayer->setColor(mBackgroundColor);
 
-        auto layer = std::make_shared<TestBufferLayer>(
-                mComposerClient, mGralloc, *mTestRenderEngine, mPrimaryDisplay, mDisplayWidth,
-                mDisplayHeight, PixelFormat::RGBA_8888);
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
+                                                       mPrimaryDisplay, mDisplayWidth,
+                                                       mDisplayHeight, PixelFormat::RGBA_8888);
         layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
         layer->setZOrder(10);
         layer->setDataspace(Dataspace::UNKNOWN, mWriter);
@@ -1043,7 +1029,7 @@
         setUpLayers(IComposerClient::BlendMode::NONE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
@@ -1102,7 +1088,7 @@
         setUpLayers(IComposerClient::BlendMode::COVERAGE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
@@ -1153,7 +1139,7 @@
         setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
@@ -1193,7 +1179,7 @@
         IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength,
                                           mSideLength};
 
-        mLayer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, *mTestRenderEngine,
+        mLayer = std::make_shared<TestBufferLayer>(mComposerClient, *mTestRenderEngine,
                                                    mPrimaryDisplay, mSideLength, mSideLength,
                                                    PixelFormat::RGBA_8888);
         mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
@@ -1236,7 +1222,7 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         mLayer->setTransform(Transform::FLIP_H);
@@ -1291,7 +1277,7 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -1346,7 +1332,7 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
                                       mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 13ae089..2bd287b 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -18,14 +18,13 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
 
 namespace android {
 namespace hardware {
@@ -40,7 +39,6 @@
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
-using V2_1::vts::NativeHandleWrapper;
 
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
@@ -141,8 +139,6 @@
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<V2_1::vts::TestCommandReader>();
     }
@@ -152,20 +148,10 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    NativeHandleWrapper allocate() {
-        uint64_t usage =
-                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
-        return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
-                                  PixelFormat::RGBA_8888, usage);
-    }
-
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
-
-   private:
-    std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
@@ -437,13 +423,11 @@
     uint64_t usage =
             static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
-    std::unique_ptr<Gralloc> gralloc;
-    std::unique_ptr<NativeHandleWrapper> buffer;
-    ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
-            gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
+    sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight,
+                                                       (int32_t)mReadbackPixelFormat, 1, usage);
+    ASSERT_EQ(STATUS_OK, buffer->initCheck());
 
-    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->get(), -1);
+    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->handle, -1);
 }
 
 /**
@@ -460,14 +444,12 @@
     uint64_t usage =
             static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
-    std::unique_ptr<Gralloc> gralloc;
-    std::unique_ptr<NativeHandleWrapper> buffer;
-    ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
-            gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
+    sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(mDisplayWidth, mDisplayHeight,
+                                                       (int32_t)mReadbackPixelFormat, 1, usage);
+    ASSERT_EQ(STATUS_OK, buffer->initCheck());
 
-    Error error =
-            mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->get(), nullptr);
+    Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->handle,
+                                                               nullptr);
     ASSERT_EQ(Error::BAD_DISPLAY, error);
 }
 
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
index b372804..99429db 100644
--- a/graphics/composer/2.3/utils/vts/Android.bp
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -26,7 +26,6 @@
 cc_library_static {
     name: "android.hardware.graphics.composer@2.3-vts",
     defaults: [
-        "android.hardware.graphics.allocator-ndk_static",
         "hidl_defaults",
     ],
     srcs: [
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 13f2b11..0d3c27d 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -27,7 +27,6 @@
     name: "VtsHalGraphicsComposerV2_3TargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
-        "android.hardware.graphics.allocator-ndk_static",
     ],
     tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
@@ -40,25 +39,14 @@
         "libhidlbase",
         "libsync",
         "android.hardware.common-V2-ndk",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.2-vts",
         "android.hardware.graphics.composer@2.3",
         "android.hardware.graphics.composer@2.3-vts",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libaidlcommonsupport",
     ],
     header_libs: [
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index ecfe66c..c072ef0 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -21,7 +21,6 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
@@ -29,7 +28,6 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
 
 namespace android {
 namespace hardware {
@@ -43,7 +41,6 @@
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::PixelFormat;
-using V2_2::vts::Gralloc;
 
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
@@ -128,8 +125,6 @@
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<V2_1::vts::TestCommandReader>();
     }
@@ -143,9 +138,6 @@
 
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
-
-   private:
-    std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
index 697d6b8..3b5ce5a 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
@@ -90,6 +90,9 @@
         }
 
         const uint32_t keySize = read();
+        if (!isReadSizeValid(keySize)) {
+            return false;
+        }
         std::string key;
         key.resize(keySize);
         readBlob(keySize, key.data());
@@ -97,6 +100,9 @@
         const bool mandatory = read();
 
         const uint32_t valueSize = read();
+        if (!isReadSizeValid(valueSize)) {
+            return false;
+        }
         std::vector<uint8_t> value(valueSize);
         readBlob(valueSize, value.data());
 
diff --git a/graphics/composer/2.4/utils/vts/Android.bp b/graphics/composer/2.4/utils/vts/Android.bp
index d2b2ffa..c39b5eb1 100644
--- a/graphics/composer/2.4/utils/vts/Android.bp
+++ b/graphics/composer/2.4/utils/vts/Android.bp
@@ -26,7 +26,6 @@
 cc_library_static {
     name: "android.hardware.graphics.composer@2.4-vts",
     defaults: [
-        "android.hardware.graphics.allocator-ndk_static",
         "hidl_defaults",
     ],
     srcs: [
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index b4ab259..52624b4 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -27,7 +27,6 @@
     name: "VtsHalGraphicsComposerV2_4TargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
-        "android.hardware.graphics.allocator-ndk_static",
     ],
     tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
@@ -38,16 +37,10 @@
         "libbinder_ndk",
         "libfmq",
         "libsync",
+        "libui",
         "android.hardware.common-V2-ndk",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
@@ -56,10 +49,6 @@
         "android.hardware.graphics.composer@2.3-vts",
         "android.hardware.graphics.composer@2.4",
         "android.hardware.graphics.composer@2.4-vts",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libaidlcommonsupport",
     ],
     header_libs: [
diff --git a/graphics/composer/2.4/vts/functional/AndroidTest.xml b/graphics/composer/2.4/vts/functional/AndroidTest.xml
index 773db93..7626995 100644
--- a/graphics/composer/2.4/vts/functional/AndroidTest.xml
+++ b/graphics/composer/2.4/vts/functional/AndroidTest.xml
@@ -31,6 +31,6 @@
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalGraphicsComposerV2_4TargetTest" />
-        <option name="native-test-timeout" value="900000"/>
+        <option name="native-test-timeout" value="1800000"/>
     </test>
 </configuration>
diff --git a/graphics/composer/2.4/vts/functional/TEST_MAPPING b/graphics/composer/2.4/vts/functional/TEST_MAPPING
new file mode 100644
index 0000000..aedac5b
--- /dev/null
+++ b/graphics/composer/2.4/vts/functional/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalGraphicsComposerV2_4TargetTest"
+    }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "VtsHalGraphicsComposerV2_4TargetTest"
+    }
+  ]
+}
+
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 35225d9..7ae917b 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -22,7 +22,6 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
 #include <composer-vts/2.4/ComposerVts.h>
 #include <composer-vts/2.4/GraphicsComposerCallback.h>
@@ -30,9 +29,7 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
-#include <mapper-vts/2.0/MapperVts.h>
-#include <mapper-vts/3.0/MapperVts.h>
-#include <mapper-vts/4.0/MapperVts.h>
+#include <ui/GraphicBuffer.h>
 #include <utils/Timers.h>
 
 namespace android {
@@ -51,9 +48,7 @@
 using common::V1_2::Dataspace;
 using common::V1_2::PixelFormat;
 using V2_1::Layer;
-using V2_1::vts::NativeHandleWrapper;
 using V2_2::Transform;
-using V2_2::vts::Gralloc;
 
 using ContentType = IComposerClient::ContentType;
 using DisplayCapability = IComposerClient::DisplayCapability;
@@ -103,8 +98,6 @@
         }
         mComposerCallback->setVsyncAllowed(false);
 
-        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<TestCommandReader>();
     }
@@ -157,12 +150,15 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    NativeHandleWrapper allocate(int32_t width, int32_t height) {
-        return mGralloc->allocate(
-                width, height, /*layerCount*/ 1,
-                static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
+    sp<GraphicBuffer> allocate(int32_t width, int32_t height) {
+        auto result = sp<GraphicBuffer>::make(
+                width, height, static_cast<int32_t>(PixelFormat::RGBA_8888), /*layerCount*/ 1,
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY));
+        if (result->initCheck() != STATUS_OK) {
+            return nullptr;
+        }
+        return result;
     }
 
     struct TestParameters {
@@ -256,7 +252,6 @@
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
     sp<GraphicsComposerCallback> mComposerCallback;
-    std::unique_ptr<Gralloc> mGralloc;
 };
 
 TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
@@ -458,7 +453,7 @@
         mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
         mWriter->setLayerSurfaceDamage(
                 std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
-        mWriter->setLayerBuffer(0, handle.get(), -1);
+        mWriter->setLayerBuffer(0, handle->handle, -1);
         mWriter->setLayerDataspace(Dataspace::UNKNOWN);
 
         mWriter->validateDisplay();
@@ -476,7 +471,7 @@
         ASSERT_NE(nullptr, handle.get());
 
         mWriter->selectLayer(layer);
-        mWriter->setLayerBuffer(0, handle.get(), -1);
+        mWriter->setLayerBuffer(0, handle->handle, -1);
         mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
         mWriter->validateDisplay();
         execute();
@@ -544,10 +539,12 @@
                       setActiveConfigWithConstraints(display, config2, constraints, &timeline));
 
             EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
-            // Refresh rate should change within a reasonable time
-            constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s;  // 1 second
-            EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
-                        kReasonableTimeForChange.count());
+            if (configGroup1 == configGroup2) {
+                // Refresh rate should change within a reasonable time
+                constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s;
+                EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
+                            kReasonableTimeForChange.count());
+            }
 
             if (timeline.refreshRequired) {
                 if (params.refreshMiss) {
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 40448ec..c105ad4 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -31,7 +31,7 @@
         enabled: true,
         support_system_process: true,
     },
-    frozen: true,
+    frozen: false,
     vndk_use_version: "1",
     srcs: [
         "android/hardware/graphics/composer3/*.aidl",
@@ -54,6 +54,9 @@
                 enabled: true,
             },
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
index 662240e..cce35e7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -45,4 +45,5 @@
   boolean acceptDisplayChanges;
   boolean presentDisplay;
   boolean presentOrValidateDisplay;
+  int frameIntervalNs;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl
new file mode 100644
index 0000000..040afd7
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayConfiguration.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable DisplayConfiguration {
+  int configId;
+  int width;
+  int height;
+  @nullable android.hardware.graphics.composer3.DisplayConfiguration.Dpi dpi;
+  int configGroup;
+  int vsyncPeriod;
+  @nullable android.hardware.graphics.composer3.VrrConfig vrrConfig;
+  parcelable Dpi {
+    float x;
+    float y;
+  }
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index cb85a88..bc27cc7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -42,8 +42,14 @@
   int getActiveConfig(long display);
   android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
   float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
+  /**
+   * @deprecated use getDisplayConfigurations instead. Returns a display attribute value for a particular display configuration. For legacy support getDisplayAttribute should return valid values for any requested DisplayAttribute, and for all of the configs obtained either through getDisplayConfigs or getDisplayConfigurations.
+   */
   int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
   android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
+  /**
+   * @deprecated use getDisplayConfigurations instead. For legacy support getDisplayConfigs should return at least one valid config. All the configs returned from the getDisplayConfigs should also be returned from getDisplayConfigurations.
+   */
   int[] getDisplayConfigs(long display);
   android.hardware.graphics.composer3.DisplayConnectionType getDisplayConnectionType(long display);
   android.hardware.graphics.composer3.DisplayIdentification getDisplayIdentificationData(long display);
@@ -79,6 +85,8 @@
   android.hardware.graphics.common.HdrConversionCapability[] getHdrConversionCapabilities();
   android.hardware.graphics.common.Hdr setHdrConversionStrategy(in android.hardware.graphics.common.HdrConversionStrategy conversionStrategy);
   void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
+  android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
+  oneway void notifyExpectedPresent(long display, in android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
   const int EX_BAD_CONFIG = 1;
   const int EX_BAD_DISPLAY = 2;
   const int EX_BAD_LAYER = 3;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
new file mode 100644
index 0000000..bb2569f
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@VintfStability
+parcelable VrrConfig {
+  int minFrameIntervalNs;
+  @nullable android.hardware.graphics.composer3.VrrConfig.FrameIntervalPowerHint[] frameIntervalPowerHints;
+  @nullable android.hardware.graphics.composer3.VrrConfig.NotifyExpectedPresentConfig notifyExpectedPresentConfig;
+  parcelable FrameIntervalPowerHint {
+    int frameIntervalNs;
+    int averageRefreshPeriodNs;
+  }
+  parcelable NotifyExpectedPresentConfig {
+    int notifyExpectedPresentHeadsUpNs;
+    int notifyExpectedPresentTimeoutNs;
+  }
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
index ea54a89..0bd72a3 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.aidl
@@ -39,14 +39,12 @@
     /**
      * The stage in which dimming operations should be performed when compositing
      * the client target.
+     *
      * Note that with a COLORIMETRIC RenderIntent, DimmingSpace must be LINEAR. That is, dimming
-     * is defined to occur in linear space.
-     * However, some composer implementations may, with other vendor-defined RenderIntents,
-     * configure their hardware such as image quality adjustments is intended to occur after
-     * composition. In this scenario, if the dimming operation were applied in linear space,
-     * then the resulting dimming operation may comepl those image quality adjustments to
-     * incorrectly alter the gamma curve. To avoid this issue, those implementations must opt to
-     * dim in gamma space.
+     * is defined to occur in linear space. However, some composer implementations may, with
+     * other vendor-defined RenderIntents, apply certain image quality adjustments that are
+     * sensitive to gamma shift when dimming in linear space. To avoid this issue, those
+     * implementations must opt to dim in gamma space.
      */
     DimmingStage dimmingStage;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
index 4f69aee..02c1389 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -174,4 +174,15 @@
      * or perform a VALIDATE_DISPLAY action instead.
      */
     boolean presentOrValidateDisplay;
+
+    /**
+     * If a value greater than 0 is set, it provides a hint about the next frame(s)
+     * cadence. This parameter represents the time in nanoseconds of when to expect the
+     * next frames to arrive. For example. frameIntervalNs=33333333 indicates that the
+     * cadence of the next frames is 30Hz.
+     *
+     * The implementation should take the necessary steps to present the next frames as
+     * close as possible to the cadence.
+     */
+    int frameIntervalNs;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
new file mode 100644
index 0000000..09c42dc
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2023, 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.
+ */
+
+package android.hardware.graphics.composer3;
+import android.hardware.graphics.composer3.VrrConfig;
+
+@VintfStability
+parcelable DisplayConfiguration {
+    /**
+     * The config id, to be used with IComposerClient.setActiveConfig.
+     */
+    int configId;
+
+    /**
+     * Dimensions in pixels
+     */
+    int width;
+    int height;
+
+    /**
+     * Dots per inch.
+     * If the DPI for a configuration is unavailable or is
+     * considered unreliable, the device may set null instead.
+     */
+    parcelable Dpi {
+        float x;
+        float y;
+    }
+    @nullable Dpi dpi;
+
+    /**
+     * The configuration group ID this config is associated to.
+     * Switching between configurations within the same group may be
+     * done seamlessly in some conditions via
+     * setActiveConfigWithConstraints. Configurations which share the
+     * same config group are similar in all attributes except for the
+     * vsync period.
+     */
+    int configGroup;
+
+    /**
+     * Vsync period in nanoseconds. This period represents the internal
+     * frequency of the display. IComposerCallback.onVsync is expected
+     * to be called on each vsync event. For non-VRR configurations, a
+     * frame can be presented on each vsync event.
+     *
+     * A present fence, retrieved from CommandResultPayload.presentFence
+     * must be signaled on a vsync boundary.
+     */
+    int vsyncPeriod;
+
+    /**
+     * Represents the specific configurations for VRR (Variable Refresh Rate) display modes.
+     * Non-VRR modes should set this to null.
+     */
+    @nullable VrrConfig vrrConfig;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 4e77f86..725c947 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -22,12 +22,14 @@
 import android.hardware.graphics.common.HdrConversionStrategy;
 import android.hardware.graphics.common.Transform;
 import android.hardware.graphics.composer3.ClientTargetProperty;
+import android.hardware.graphics.composer3.ClockMonotonicTimestamp;
 import android.hardware.graphics.composer3.ColorMode;
 import android.hardware.graphics.composer3.CommandResultPayload;
 import android.hardware.graphics.composer3.ContentType;
 import android.hardware.graphics.composer3.DisplayAttribute;
 import android.hardware.graphics.composer3.DisplayCapability;
 import android.hardware.graphics.composer3.DisplayCommand;
+import android.hardware.graphics.composer3.DisplayConfiguration;
 import android.hardware.graphics.composer3.DisplayConnectionType;
 import android.hardware.graphics.composer3.DisplayContentSample;
 import android.hardware.graphics.composer3.DisplayContentSamplingAttributes;
@@ -234,9 +236,18 @@
     float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
 
     /**
+     * @deprecated use getDisplayConfigurations instead.
+     *
      * Returns a display attribute value for a particular display
      * configuration.
      *
+     * For legacy support getDisplayAttribute should return valid values for any requested
+     * DisplayAttribute, and for all of the configs obtained either through getDisplayConfigs
+     * or getDisplayConfigurations.
+     *
+     * @see getDisplayConfigurations
+     * @see getDisplayConfigs
+     *
      * @param display is the display to query.
      * @param config is the display configuration for which to return
      *        attribute values.
@@ -263,15 +274,12 @@
     DisplayCapability[] getDisplayCapabilities(long display);
 
     /**
-     * Returns handles for all of the valid display configurations on this
-     * display.
-     * This should never return INVALID_CONFIGURATION as a valid value.
+     * @deprecated use getDisplayConfigurations instead.
+     * For legacy support getDisplayConfigs should return at least one valid config.
+     * All the configs returned from the getDisplayConfigs should also be returned
+     * from getDisplayConfigurations.
      *
-     * @param display is the display to query.
-     *
-     * @return is an array of configuration handles.
-     *
-     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
+     * @see getDisplayConfigurations
      */
     int[] getDisplayConfigs(long display);
 
@@ -864,4 +872,45 @@
      *        false when refresh rate callback is disabled.
      */
     void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
+
+    /**
+     * Returns all of the valid display configurations.
+     * getDisplayConfigurations is the superset of getDisplayConfigs and
+     * getDisplayConfigs should return at least one config.
+     *
+     * @param display is the display for which the configurations are requested.
+     * @param maxFrameIntervalNs refers to the largest frameInterval to be set for
+     * VrrConfig.frameIntervalPowerHints in nanoseconds
+     *
+     * @see getDisplayConfigs
+     */
+    DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
+
+    /**
+     * Provides an early hint for a frame that is likely to be presented.
+     * This is used for the implementation to take the necessary steps to ensure that
+     * the next frame(s) could be presented as close as possible to the expectedPresentTime and
+     * according to the frameIntervalNs cadence.
+     * See DisplayCommand.expectedPresentTime and DisplayCommand.frameIntervalNs.
+     *
+     * The framework will call this function based on the parameters specified in
+     * DisplayConfiguration.VrrConfig:
+     * - notifyExpectedPresentTimeoutNs specifies the idle time from the previous present command
+     * where the framework must send the early hint for the next frame.
+     * - notifyExpectedPresentHeadsUpNs specifies minimal time that framework must send
+     * the early hint before the next frame.
+     *
+     * The framework can omit calling this API when the next present command matches
+     * the cadence of the previous present command frameIntervalNs.
+     *
+     * If DisplayConfiguration.notifyExpectedPresentConfig is null, this function will never be
+     * called.
+     *
+     * @param display is the display for which the notifyExpectedPresent is called.
+     * @param expectedPresentTime is the expectedPresentTime that will be provided in the next
+     * present command
+     * @param frameIntervalNs is a hint about the cadence of the next frames in nanoseconds.
+     */
+    oneway void notifyExpectedPresent(
+            long display, in ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
new file mode 100644
index 0000000..3b241ba
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2023, 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.
+ */
+
+package android.hardware.graphics.composer3;
+
+@VintfStability
+parcelable VrrConfig {
+    /**
+     * The minimal time (in nanoseconds) that needs to pass between the previously presented frame
+     * and when the next frame can be presented.
+     */
+    int minFrameIntervalNs;
+
+    /**
+     * An optional mapping between frame intervals, and the physical display refresh period on
+     * average. This provides useful information to the framework when picking a specific frame rate
+     * (which is a divisor of the vsync rate) about the real display refresh rate, which could be
+     * used for power optimizations. The implementation should populate this map for frame rates
+     * that requires the display to run at a higher refresh rate due to self refresh frames. The
+     * lowest frame rate provided should be according to the parameter `maxFrameIntervalNs`
+     * specified in IComposerClient.getDisplayConfigurations, as the framework would generally not
+     * try to run at a lower frame rate.
+     */
+    parcelable FrameIntervalPowerHint {
+        int frameIntervalNs;
+        int averageRefreshPeriodNs;
+    }
+    @nullable FrameIntervalPowerHint[] frameIntervalPowerHints;
+
+    parcelable NotifyExpectedPresentConfig {
+        /**
+         * The minimal time in nanoseconds that IComposerClient.notifyExpectedPresent needs to be
+         * called ahead of an expectedPresentTime provided on a presentDisplay command.
+         */
+        int notifyExpectedPresentHeadsUpNs;
+
+        /**
+         * The time in nanoseconds that represents a timeout from the previous presentDisplay, which
+         * after this point the display needs a call to IComposerClient.notifyExpectedPresent before
+         * sending the next frame. If set to 0, there is no need to call
+         * IComposerClient.notifyExpectedPresent for timeout.
+         */
+        int notifyExpectedPresentTimeoutNs;
+    }
+
+    /**
+     * Parameters for when to call IComposerClient.notifyExpectedPresent.
+     *
+     * When set to null, the framework will not call IComposerClient.notifyExpectedPresent.
+     */
+    @nullable NotifyExpectedPresentConfig notifyExpectedPresentConfig;
+}
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 88b5de4..e60e1a7 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -55,13 +55,6 @@
         "libhidlbase",
         "libprocessgroup",
         "libtinyxml2",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "libvndksupport",
     ],
     header_libs: [
@@ -71,13 +64,6 @@
         "android.hardware.graphics.common@1.2",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0-vts",
         "libaidlcommonsupport",
         "libarect",
         "libbase",
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index ee9f0d5..d5602c1 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -20,7 +20,6 @@
 #include <android-base/unique_fd.h>
 #include <android/hardware/graphics/composer3/ComposerClientReader.h>
 #include <android/hardware/graphics/composer3/ComposerClientWriter.h>
-#include <mapper-vts/2.1/MapperVts.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
 #include <memory>
@@ -32,7 +31,6 @@
 using ::android::renderengine::LayerSettings;
 using common::Dataspace;
 using common::PixelFormat;
-using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
 
 static const Color BLACK = {0.0f, 0.0f, 0.0f, 1.0f};
 static const Color RED = {1.0f, 0.0f, 0.0f, 1.0f};
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index 66779c8..d1f89d0 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -19,7 +19,6 @@
 
 namespace aidl::android::hardware::graphics::composer3::vts {
 
-using ::android::hardware::graphics::mapper::V2_1::IMapper;
 using ::android::renderengine::DisplaySettings;
 using ::android::renderengine::LayerSettings;
 using ::android::renderengine::RenderEngineCreationArgs;
@@ -67,7 +66,7 @@
             mGraphicBuffer, *mRenderEngine,
             ::android::renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     auto result = mRenderEngine
-                          ->drawLayers(mDisplaySettings, compositionLayers, texture, true,
+                          ->drawLayers(mDisplaySettings, compositionLayers, texture,
                                        std::move(bufferFence))
                           .get();
     if (result.ok()) {
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.h b/graphics/composer/aidl/vts/RenderEngineVts.h
index 43d3a42..612f0ea 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.h
+++ b/graphics/composer/aidl/vts/RenderEngineVts.h
@@ -15,13 +15,11 @@
  */
 #pragma once
 
-#include <mapper-vts/2.1/MapperVts.h>
 #include <math/half.h>
 #include <math/vec3.h>
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -29,7 +27,6 @@
 
 namespace aidl::android::hardware::graphics::composer3::vts {
 
-using ::android::hardware::graphics::mapper::V2_1::IMapper;
 using ::android::renderengine::DisplaySettings;
 using ::android::renderengine::ExternalTexture;
 using ::android::renderengine::RenderEngineCreationArgs;
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 25b0ca0..11b995e 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -58,7 +58,7 @@
     return verifyComposerCallbackParams() && destroyAllLayers();
 }
 
-std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() {
+std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() const {
     int32_t version = 1;
     auto status = mComposerClient->getInterfaceVersion(&version);
     return {std::move(status), version};
@@ -295,7 +295,31 @@
 std::pair<ScopedAStatus, std::vector<int32_t>> VtsComposerClient::getDisplayConfigs(
         int64_t display) {
     std::vector<int32_t> outConfigs;
-    return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
+    if (!getDisplayConfigurationSupported()) {
+        return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
+    }
+
+    auto [status, configs] = getDisplayConfigurations(display);
+    if (!status.isOk()) {
+        return {std::move(status), outConfigs};
+    }
+    for (const auto& config : configs) {
+        outConfigs.emplace_back(config.configId);
+    }
+    return {std::move(status), outConfigs};
+}
+
+std::pair<ScopedAStatus, std::vector<DisplayConfiguration>>
+VtsComposerClient::getDisplayConfigurations(int64_t display) {
+    std::vector<DisplayConfiguration> outConfigs;
+    return {mComposerClient->getDisplayConfigurations(display, kMaxFrameIntervalNs, &outConfigs),
+            outConfigs};
+}
+
+ScopedAStatus VtsComposerClient::notifyExpectedPresent(int64_t display,
+                                                       ClockMonotonicTimestamp expectedPresentTime,
+                                                       int frameIntervalNs) {
+    return mComposerClient->notifyExpectedPresent(display, expectedPresentTime, frameIntervalNs);
 }
 
 std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
@@ -439,31 +463,41 @@
         vtsDisplays.reserve(displays.size());
         for (int64_t display : displays) {
             auto vtsDisplay = VtsDisplay{display};
-            auto configs = getDisplayConfigs(display);
-            if (!configs.first.isOk()) {
-                ALOGE("Unable to get the displays for test, failed to get the configs "
-                      "for display %" PRId64,
-                      display);
-                return {std::move(configs.first), vtsDisplays};
-            }
-            for (int config : configs.second) {
-                auto status = addDisplayConfig(&vtsDisplay, config);
+            if (getDisplayConfigurationSupported()) {
+                auto [status, configs] = getDisplayConfigurations(display);
                 if (!status.isOk()) {
-                    ALOGE("Unable to get the displays for test, failed to add config "
+                    ALOGE("Unable to get the displays for test, failed to get the DisplayConfigs "
                           "for display %" PRId64,
                           display);
                     return {std::move(status), vtsDisplays};
                 }
+                addDisplayConfigs(&vtsDisplay, configs);
+            } else {
+                auto [status, configs] = getDisplayConfigs(display);
+                if (!status.isOk()) {
+                    ALOGE("Unable to get the displays for test, failed to get the configs "
+                          "for display %" PRId64,
+                          display);
+                    return {std::move(status), vtsDisplays};
+                }
+                for (int config : configs) {
+                    status = addDisplayConfigLegacy(&vtsDisplay, config);
+                    if (!status.isOk()) {
+                        ALOGE("Unable to get the displays for test, failed to add config "
+                              "for display %" PRId64,
+                              display);
+                        return {std::move(status), vtsDisplays};
+                    }
+                }
             }
-
-            auto config = getActiveConfig(display);
-            if (!config.first.isOk()) {
+            auto activeConfig = getActiveConfig(display);
+            if (!activeConfig.first.isOk()) {
                 ALOGE("Unable to get the displays for test, failed to get active config "
-                      "for display %" PRId64, display);
-                return {std::move(config.first), vtsDisplays};
+                      "for display %" PRId64,
+                      display);
+                return {std::move(activeConfig.first), vtsDisplays};
             }
-
-            auto status = updateDisplayProperties(&vtsDisplay, config.second);
+            auto status = updateDisplayProperties(&vtsDisplay, activeConfig.second);
             if (!status.isOk()) {
                 ALOGE("Unable to get the displays for test, "
                       "failed to update the properties "
@@ -480,39 +514,53 @@
     }
 }
 
-ScopedAStatus VtsComposerClient::addDisplayConfig(VtsDisplay* vtsDisplay, int32_t config) {
-    const auto width =
-            getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
-    const auto height =
-            getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
+void VtsComposerClient::addDisplayConfigs(VtsDisplay* vtsDisplay,
+                                          const std::vector<DisplayConfiguration>& configs) {
+    for (const auto& config : configs) {
+        vtsDisplay->addDisplayConfig(config.configId, {config.vsyncPeriod, config.configGroup});
+    }
+}
+
+ScopedAStatus VtsComposerClient::addDisplayConfigLegacy(VtsDisplay* vtsDisplay, int32_t config) {
     const auto vsyncPeriod =
             getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
     const auto configGroup =
             getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
-    if (width.first.isOk() && height.first.isOk() && vsyncPeriod.first.isOk() &&
-        configGroup.first.isOk()) {
+    if (vsyncPeriod.first.isOk() && configGroup.first.isOk()) {
         vtsDisplay->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
         return ScopedAStatus::ok();
     }
 
-    LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
-               << ", height: " << height.first.isOk() << ", vsync: " << vsyncPeriod.first.isOk()
+    LOG(ERROR) << "Failed to update display property vsync: " << vsyncPeriod.first.isOk()
                << ", config: " << configGroup.first.isOk();
     return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
 }
 
 ScopedAStatus VtsComposerClient::updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config) {
-    const auto width =
-            getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
-    const auto height =
-            getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
-    if (width.first.isOk() && height.first.isOk()) {
-        vtsDisplay->setDimensions(width.second, height.second);
-        return ScopedAStatus::ok();
-    }
+    if (getDisplayConfigurationSupported()) {
+        auto [status, configs] = getDisplayConfigurations(vtsDisplay->getDisplayId());
+        if (status.isOk()) {
+            for (const auto& displayConfig : configs) {
+                if (displayConfig.configId == config) {
+                    vtsDisplay->setDimensions(displayConfig.width, displayConfig.height);
+                    return ScopedAStatus::ok();
+                }
+            }
+        }
+        LOG(ERROR) << "Failed to update display property with DisplayConfig";
+    } else {
+        const auto width =
+                getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
+        const auto height =
+                getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
+        if (width.first.isOk() && height.first.isOk()) {
+            vtsDisplay->setDimensions(width.second, height.second);
+            return ScopedAStatus::ok();
+        }
 
-    LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
-               << ", height: " << height.first.isOk();
+        LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
+                   << ", height: " << height.first.isOk();
+    }
     return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
 }
 
@@ -576,6 +624,13 @@
     return isValid;
 }
 
+bool VtsComposerClient::getDisplayConfigurationSupported() const {
+    auto [status, interfaceVersion] = getInterfaceVersion();
+    EXPECT_TRUE(status.isOk());
+    // getDisplayConfigurations api is supported starting interface version 3
+    return interfaceVersion >= 3;
+}
+
 bool VtsComposerClient::destroyAllLayers() {
     std::unordered_map<int64_t, DisplayResource> physicalDisplays;
     while (!mDisplayResources.empty()) {
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index ea3318c..20dc733 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -61,7 +61,7 @@
 
     bool tearDown();
 
-    std::pair<ScopedAStatus, int32_t> getInterfaceVersion();
+    std::pair<ScopedAStatus, int32_t> getInterfaceVersion() const;
 
     std::pair<ScopedAStatus, VirtualDisplay> createVirtualDisplay(int32_t width, int32_t height,
                                                                   PixelFormat pixelFormat,
@@ -142,6 +142,13 @@
 
     std::pair<ScopedAStatus, std::vector<int32_t>> getDisplayConfigs(int64_t display);
 
+    std::pair<ScopedAStatus, std::vector<DisplayConfiguration>> getDisplayConfigurations(
+            int64_t display);
+
+    ScopedAStatus notifyExpectedPresent(int64_t display,
+                                        ClockMonotonicTimestamp expectedPresentTime,
+                                        int frameIntervalNs);
+
     std::pair<ScopedAStatus, int32_t> getDisplayVsyncPeriod(int64_t display);
 
     ScopedAStatus setAutoLowLatencyMode(int64_t display, bool isEnabled);
@@ -189,8 +196,12 @@
 
     std::vector<RefreshRateChangedDebugData> takeListOfRefreshRateChangedDebugData();
 
+    static constexpr int32_t kMaxFrameIntervalNs = 50000000;  // 20fps
+
   private:
-    ScopedAStatus addDisplayConfig(VtsDisplay* vtsDisplay, int32_t config);
+    void addDisplayConfigs(VtsDisplay*, const std::vector<DisplayConfiguration>&);
+    ScopedAStatus addDisplayConfigLegacy(VtsDisplay*, int32_t config);
+    bool getDisplayConfigurationSupported() const;
     ScopedAStatus updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config);
 
     ScopedAStatus addDisplayToDisplayResources(int64_t display, bool isVirtual);
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 269abd1..a83b833 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -70,7 +70,6 @@
                         ::android::renderengine::RenderEngineCreationArgs::Builder()
                                 .setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888))
                                 .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
-                                .setUseColorManagerment(true)
                                 .setEnableProtectedContext(false)
                                 .setPrecacheToneMapperShaderOnly(false)
                                 .setContextPriority(::android::renderengine::RenderEngine::
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 18d36e4..1e6f34b 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -45,7 +45,6 @@
 #define LOG_TAG "VtsHalGraphicsComposer3_TargetTest"
 
 namespace aidl::android::hardware::graphics::composer3::vts {
-namespace {
 
 using namespace std::chrono_literals;
 
@@ -891,39 +890,6 @@
     EXPECT_TRUE(status.isOk());
 }
 
-TEST_P(GraphicsComposerAidlTest, GetOverlaySupport) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "Device does not support the new API for overlay support";
-        return;
-    }
-
-    const auto& [status, properties] = mComposerClient->getOverlaySupport();
-    if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
-        status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
-        GTEST_SUCCEED() << "getOverlaySupport is not supported";
-        return;
-    }
-
-    ASSERT_TRUE(status.isOk());
-    for (const auto& i : properties.combinations) {
-        for (const auto standard : i.standards) {
-            const auto val = static_cast<int32_t>(standard) &
-                             static_cast<int32_t>(common::Dataspace::STANDARD_MASK);
-            ASSERT_TRUE(val == static_cast<int32_t>(standard));
-        }
-        for (const auto transfer : i.transfers) {
-            const auto val = static_cast<int32_t>(transfer) &
-                             static_cast<int32_t>(common::Dataspace::TRANSFER_MASK);
-            ASSERT_TRUE(val == static_cast<int32_t>(transfer));
-        }
-        for (const auto range : i.ranges) {
-            const auto val = static_cast<int32_t>(range) &
-                             static_cast<int32_t>(common::Dataspace::RANGE_MASK);
-            ASSERT_TRUE(val == static_cast<int32_t>(range));
-        }
-    }
-}
-
 TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientation_BadDisplay) {
     const auto& [status, _] = mComposerClient->getDisplayPhysicalOrientation(getInvalidDisplayId());
 
@@ -1169,6 +1135,238 @@
     EXPECT_NO_FATAL_FAILURE(assertServiceSpecificError(status, IComposerClient::EX_BAD_PARAMETER));
 }
 
+/*
+ * Test that no two display configs are exactly the same.
+ */
+TEST_P(GraphicsComposerAidlTest, GetDisplayConfigNoRepetitions) {
+    for (const auto& display : mDisplays) {
+        const auto& [status, configs] = mComposerClient->getDisplayConfigs(display.getDisplayId());
+        for (std::vector<int>::size_type i = 0; i < configs.size(); i++) {
+            for (std::vector<int>::size_type j = i + 1; j < configs.size(); j++) {
+                const auto& [widthStatus1, width1] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[i], DisplayAttribute::WIDTH);
+                const auto& [heightStatus1, height1] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[i], DisplayAttribute::HEIGHT);
+                const auto& [vsyncPeriodStatus1, vsyncPeriod1] =
+                        mComposerClient->getDisplayAttribute(display.getDisplayId(), configs[i],
+                                                             DisplayAttribute::VSYNC_PERIOD);
+                const auto& [groupStatus1, group1] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[i], DisplayAttribute::CONFIG_GROUP);
+
+                const auto& [widthStatus2, width2] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[j], DisplayAttribute::WIDTH);
+                const auto& [heightStatus2, height2] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[j], DisplayAttribute::HEIGHT);
+                const auto& [vsyncPeriodStatus2, vsyncPeriod2] =
+                        mComposerClient->getDisplayAttribute(display.getDisplayId(), configs[j],
+                                                             DisplayAttribute::VSYNC_PERIOD);
+                const auto& [groupStatus2, group2] = mComposerClient->getDisplayAttribute(
+                        display.getDisplayId(), configs[j], DisplayAttribute::CONFIG_GROUP);
+
+                ASSERT_FALSE(width1 == width2 && height1 == height2 &&
+                             vsyncPeriod1 == vsyncPeriod2 && group1 == group2);
+            }
+        }
+    }
+}
+
+class GraphicsComposerAidlV2Test : public GraphicsComposerAidlTest {
+  protected:
+    void SetUp() override {
+        GraphicsComposerAidlTest::SetUp();
+        if (getInterfaceVersion() <= 1) {
+            GTEST_SKIP() << "Device interface version is expected to be >= 2";
+        }
+    }
+};
+
+TEST_P(GraphicsComposerAidlV2Test, GetOverlaySupport) {
+    const auto& [status, properties] = mComposerClient->getOverlaySupport();
+    if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+        status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+        GTEST_SUCCEED() << "getOverlaySupport is not supported";
+        return;
+    }
+
+    ASSERT_TRUE(status.isOk());
+    for (const auto& i : properties.combinations) {
+        for (const auto standard : i.standards) {
+            const auto val = static_cast<int32_t>(standard) &
+                             static_cast<int32_t>(common::Dataspace::STANDARD_MASK);
+            ASSERT_TRUE(val == static_cast<int32_t>(standard));
+        }
+        for (const auto transfer : i.transfers) {
+            const auto val = static_cast<int32_t>(transfer) &
+                             static_cast<int32_t>(common::Dataspace::TRANSFER_MASK);
+            ASSERT_TRUE(val == static_cast<int32_t>(transfer));
+        }
+        for (const auto range : i.ranges) {
+            const auto val = static_cast<int32_t>(range) &
+                             static_cast<int32_t>(common::Dataspace::RANGE_MASK);
+            ASSERT_TRUE(val == static_cast<int32_t>(range));
+        }
+    }
+}
+
+class GraphicsComposerAidlV3Test : public GraphicsComposerAidlTest {
+  protected:
+    void SetUp() override {
+        GraphicsComposerAidlTest::SetUp();
+        if (getInterfaceVersion() <= 2) {
+            GTEST_SKIP() << "Device interface version is expected to be >= 3";
+        }
+    }
+};
+
+TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigurations) {
+    for (const auto& display : mDisplays) {
+        const auto& [status, displayConfigurations] =
+                mComposerClient->getDisplayConfigurations(display.getDisplayId());
+        EXPECT_TRUE(status.isOk());
+        EXPECT_FALSE(displayConfigurations.empty());
+
+        for (const auto& displayConfig : displayConfigurations) {
+            EXPECT_NE(-1, displayConfig.width);
+            EXPECT_NE(-1, displayConfig.height);
+            EXPECT_NE(-1, displayConfig.vsyncPeriod);
+            EXPECT_NE(-1, displayConfig.configGroup);
+            if (displayConfig.dpi) {
+                EXPECT_NE(-1.f, displayConfig.dpi->x);
+                EXPECT_NE(-1.f, displayConfig.dpi->y);
+            }
+            if (displayConfig.vrrConfig) {
+                const auto& vrrConfig = *displayConfig.vrrConfig;
+                EXPECT_GE(vrrConfig.minFrameIntervalNs, displayConfig.vsyncPeriod);
+
+                EXPECT_EQ(1, std::count_if(
+                                     displayConfigurations.cbegin(), displayConfigurations.cend(),
+                                     [displayConfig](const auto& config) {
+                                         return config.configGroup == displayConfig.configGroup;
+                                     }))
+                        << "There should be only one VRR mode in one ConfigGroup";
+
+                const auto verifyFrameIntervalIsDivisorOfVsync = [&](int32_t frameIntervalNs) {
+                    constexpr auto kThreshold = 0.05f;  // 5%
+                    const auto ratio =
+                            static_cast<float>(frameIntervalNs) / displayConfig.vsyncPeriod;
+                    return ratio - std::round(ratio) <= kThreshold;
+                };
+
+                EXPECT_TRUE(verifyFrameIntervalIsDivisorOfVsync(vrrConfig.minFrameIntervalNs));
+
+                if (vrrConfig.frameIntervalPowerHints) {
+                    const auto& frameIntervalPowerHints = *vrrConfig.frameIntervalPowerHints;
+                    EXPECT_FALSE(frameIntervalPowerHints.empty());
+
+                    const auto minFrameInterval = *min_element(frameIntervalPowerHints.cbegin(),
+                                                               frameIntervalPowerHints.cend());
+                    EXPECT_LE(minFrameInterval->frameIntervalNs,
+                              VtsComposerClient::kMaxFrameIntervalNs);
+
+                    EXPECT_TRUE(std::all_of(frameIntervalPowerHints.cbegin(),
+                                            frameIntervalPowerHints.cend(),
+                                            [&](const auto& frameIntervalPowerHint) {
+                                                return verifyFrameIntervalIsDivisorOfVsync(
+                                                        frameIntervalPowerHint->frameIntervalNs);
+                                            }));
+                }
+
+                if (vrrConfig.notifyExpectedPresentConfig) {
+                    const auto& notifyExpectedPresentConfig =
+                            *vrrConfig.notifyExpectedPresentConfig;
+                    EXPECT_GT(0, notifyExpectedPresentConfig.notifyExpectedPresentHeadsUpNs);
+                    EXPECT_GE(0, notifyExpectedPresentConfig.notifyExpectedPresentTimeoutNs);
+                }
+            }
+        }
+    }
+}
+
+TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigsIsSubsetOfGetDisplayConfigurations) {
+    for (const auto& display : mDisplays) {
+        const auto& [status, displayConfigurations] =
+                mComposerClient->getDisplayConfigurations(display.getDisplayId());
+        EXPECT_TRUE(status.isOk());
+
+        const auto& [legacyConfigStatus, legacyConfigs] =
+                mComposerClient->getDisplayConfigs(display.getDisplayId());
+        EXPECT_TRUE(legacyConfigStatus.isOk());
+        EXPECT_FALSE(legacyConfigs.empty());
+        EXPECT_TRUE(legacyConfigs.size() <= displayConfigurations.size());
+
+        for (const auto legacyConfigId : legacyConfigs) {
+            const auto& legacyWidth = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::WIDTH);
+            const auto& legacyHeight = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::HEIGHT);
+            const auto& legacyVsyncPeriod = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::VSYNC_PERIOD);
+            const auto& legacyConfigGroup = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::CONFIG_GROUP);
+            const auto& legacyDpiX = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::DPI_X);
+            const auto& legacyDpiY = mComposerClient->getDisplayAttribute(
+                    display.getDisplayId(), legacyConfigId, DisplayAttribute::DPI_Y);
+
+            EXPECT_TRUE(legacyWidth.first.isOk() && legacyHeight.first.isOk() &&
+                        legacyVsyncPeriod.first.isOk() && legacyConfigGroup.first.isOk());
+
+            EXPECT_TRUE(std::any_of(
+                    displayConfigurations.begin(), displayConfigurations.end(),
+                    [&](const auto& displayConfiguration) {
+                        const bool requiredAttributesPredicate =
+                                displayConfiguration.configId == legacyConfigId &&
+                                displayConfiguration.width == legacyWidth.second &&
+                                displayConfiguration.height == legacyHeight.second &&
+                                displayConfiguration.vsyncPeriod == legacyVsyncPeriod.second &&
+                                displayConfiguration.configGroup == legacyConfigGroup.second;
+
+                        if (!requiredAttributesPredicate) {
+                            // Required attributes did not match
+                            return false;
+                        }
+
+                        // Check optional attributes
+                        const auto& [legacyDpiXStatus, legacyDpiXValue] = legacyDpiX;
+                        const auto& [legacyDpiYStatus, legacyDpiYValue] = legacyDpiY;
+                        if (displayConfiguration.dpi) {
+                            if (!legacyDpiXStatus.isOk() || !legacyDpiYStatus.isOk()) {
+                                // getDisplayAttribute failed for optional attributes
+                                return false;
+                            }
+
+                            // DPI values in DisplayConfigurations are not scaled (* 1000.f)
+                            // the way they are in the legacy DisplayConfigs.
+                            constexpr float kEpsilon = 0.001f;
+                            return std::abs(displayConfiguration.dpi->x -
+                                            legacyDpiXValue / 1000.f) < kEpsilon &&
+                                   std::abs(displayConfiguration.dpi->y -
+                                            legacyDpiYValue / 1000.f) < kEpsilon;
+                        } else {
+                            return !legacyDpiXStatus.isOk() && !legacyDpiYStatus.isOk() &&
+                                   EX_SERVICE_SPECIFIC == legacyDpiXStatus.getExceptionCode() &&
+                                   EX_SERVICE_SPECIFIC == legacyDpiYStatus.getExceptionCode() &&
+                                   IComposerClient::EX_UNSUPPORTED ==
+                                           legacyDpiXStatus.getServiceSpecificError() &&
+                                   IComposerClient::EX_UNSUPPORTED ==
+                                           legacyDpiYStatus.getServiceSpecificError();
+                        }
+                    }));
+        }
+    }
+}
+
+// TODO(b/291792736) Add detailed VTS test cases for NotifyExpectedPresent
+TEST_P(GraphicsComposerAidlV3Test, NotifyExpectedPresent) {
+    for (const auto& display : mDisplays) {
+        EXPECT_TRUE(mComposerClient
+                            ->notifyExpectedPresent(display.getDisplayId(),
+                                                    ClockMonotonicTimestamp{0},
+                                                    std::chrono::nanoseconds{8ms}.count())
+                            .isOk());
+    }
+}
+
 // Tests for Command.
 class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
   protected:
@@ -1767,53 +1965,6 @@
     execute();
 }
 
-TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferSlotsToClear) {
-    // Older HAL versions use a backwards compatible way of clearing buffer slots
-    const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
-    ASSERT_TRUE(versionStatus.isOk());
-    if (version <= 1) {
-        GTEST_SUCCEED() << "HAL at version 1 or lower does not have "
-                           "LayerCommand::bufferSlotsToClear.";
-        return;
-    }
-
-    const auto& [layerStatus, layer] =
-            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
-    EXPECT_TRUE(layerStatus.isOk());
-    auto& writer = getWriter(getPrimaryDisplayId());
-
-    // setup 3 buffers in the buffer cache, with the last buffer being active
-    // then emulate the Android platform code that clears all 3 buffer slots
-
-    const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
-    ASSERT_NE(nullptr, buffer1);
-    const auto handle1 = buffer1->handle;
-    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
-    execute();
-    ASSERT_TRUE(mReader.takeErrors().empty());
-
-    const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
-    ASSERT_NE(nullptr, buffer2);
-    const auto handle2 = buffer2->handle;
-    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
-    execute();
-    ASSERT_TRUE(mReader.takeErrors().empty());
-
-    const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
-    ASSERT_NE(nullptr, buffer3);
-    const auto handle3 = buffer3->handle;
-    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 2, handle3, /*acquireFence*/ -1);
-    execute();
-    ASSERT_TRUE(mReader.takeErrors().empty());
-
-    // Ensure we can clear all 3 buffer slots, even the active buffer - it is assumed the
-    // current active buffer's slot will be cleared, but still remain the active buffer and no
-    // errors will occur.
-    writer.setLayerBufferSlotsToClear(getPrimaryDisplayId(), layer, {0, 1, 2});
-    execute();
-    ASSERT_TRUE(mReader.takeErrors().empty());
-}
-
 TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferMultipleTimes) {
     const auto& [layerStatus, layer] =
             mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
@@ -2405,12 +2556,66 @@
     EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk());
 }
 
-TEST_P(GraphicsComposerAidlCommandTest, SetRefreshRateChangedCallbackDebug_Unsupported) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is "
-                           "not supported on older version of the service";
-        return;
+class GraphicsComposerAidlCommandV2Test : public GraphicsComposerAidlCommandTest {
+  protected:
+    void SetUp() override {
+        GraphicsComposerAidlTest::SetUp();
+        if (getInterfaceVersion() <= 1) {
+            GTEST_SKIP() << "Device interface version is expected to be >= 2";
+        }
     }
+};
+/**
+ * Test Capability::SKIP_VALIDATE
+ *
+ * Capability::SKIP_VALIDATE has been deprecated and should not be enabled.
+ */
+TEST_P(GraphicsComposerAidlCommandV2Test, SkipValidateDeprecatedTest) {
+    ASSERT_FALSE(hasCapability(Capability::SKIP_VALIDATE))
+            << "Found Capability::SKIP_VALIDATE capability.";
+}
+
+TEST_P(GraphicsComposerAidlCommandV2Test, SetLayerBufferSlotsToClear) {
+    // Older HAL versions use a backwards compatible way of clearing buffer slots
+    // HAL at version 1 or lower does not have LayerCommand::bufferSlotsToClear
+    const auto& [layerStatus, layer] =
+            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+    EXPECT_TRUE(layerStatus.isOk());
+    auto& writer = getWriter(getPrimaryDisplayId());
+
+    // setup 3 buffers in the buffer cache, with the last buffer being active
+    // then emulate the Android platform code that clears all 3 buffer slots
+
+    const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer1);
+    const auto handle1 = buffer1->handle;
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer2);
+    const auto handle2 = buffer2->handle;
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer3);
+    const auto handle3 = buffer3->handle;
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 2, handle3, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    // Ensure we can clear all 3 buffer slots, even the active buffer - it is assumed the
+    // current active buffer's slot will be cleared, but still remain the active buffer and no
+    // errors will occur.
+    writer.setLayerBufferSlotsToClear(getPrimaryDisplayId(), layer, {0, 1, 2});
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandV2Test, SetRefreshRateChangedCallbackDebug_Unsupported) {
     if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
         auto status = mComposerClient->setRefreshRateChangedCallbackDebugEnabled(
                 getPrimaryDisplayId(), /*enabled*/ true);
@@ -2426,12 +2631,7 @@
     }
 }
 
-TEST_P(GraphicsComposerAidlCommandTest, SetRefreshRateChangedCallbackDebug_Enabled) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is "
-                           "not supported on older version of the service";
-        return;
-    }
+TEST_P(GraphicsComposerAidlCommandV2Test, SetRefreshRateChangedCallbackDebug_Enabled) {
     if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
         GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
         return;
@@ -2459,13 +2659,8 @@
                         .isOk());
 }
 
-TEST_P(GraphicsComposerAidlCommandTest,
+TEST_P(GraphicsComposerAidlCommandV2Test,
        SetRefreshRateChangedCallbackDebugEnabled_noCallbackWhenIdle) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is "
-                           "not supported on older version of the service";
-        return;
-    }
     if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
         GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
         return;
@@ -2521,13 +2716,8 @@
                         .isOk());
 }
 
-TEST_P(GraphicsComposerAidlCommandTest,
+TEST_P(GraphicsComposerAidlCommandV2Test,
        SetRefreshRateChangedCallbackDebugEnabled_SetActiveConfigWithConstraints) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is "
-                           "not supported on older version of the service";
-        return;
-    }
     if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
         GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
         return;
@@ -2595,67 +2785,32 @@
     }
 }
 
-/*
- * Test that no two display configs are exactly the same.
- */
-TEST_P(GraphicsComposerAidlTest, GetDisplayConfigNoRepetitions) {
-    for (const auto& display : mDisplays) {
-        const auto& [status, configs] = mComposerClient->getDisplayConfigs(display.getDisplayId());
-        for (std::vector<int>::size_type i = 0; i < configs.size(); i++) {
-            for (std::vector<int>::size_type j = i + 1; j < configs.size(); j++) {
-                const auto& [widthStatus1, width1] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[i], DisplayAttribute::WIDTH);
-                const auto& [heightStatus1, height1] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[i], DisplayAttribute::HEIGHT);
-                const auto& [vsyncPeriodStatus1, vsyncPeriod1] =
-                        mComposerClient->getDisplayAttribute(display.getDisplayId(), configs[i],
-                                                             DisplayAttribute::VSYNC_PERIOD);
-                const auto& [groupStatus1, group1] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[i], DisplayAttribute::CONFIG_GROUP);
-
-                const auto& [widthStatus2, width2] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[j], DisplayAttribute::WIDTH);
-                const auto& [heightStatus2, height2] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[j], DisplayAttribute::HEIGHT);
-                const auto& [vsyncPeriodStatus2, vsyncPeriod2] =
-                        mComposerClient->getDisplayAttribute(display.getDisplayId(), configs[j],
-                                                             DisplayAttribute::VSYNC_PERIOD);
-                const auto& [groupStatus2, group2] = mComposerClient->getDisplayAttribute(
-                        display.getDisplayId(), configs[j], DisplayAttribute::CONFIG_GROUP);
-
-                ASSERT_FALSE(width1 == width2 && height1 == height2 &&
-                             vsyncPeriod1 == vsyncPeriod2 && group1 == group2);
-            }
-        }
-    }
-}
-
-/**
- * Test Capability::SKIP_VALIDATE
- *
- * Capability::SKIP_VALIDATE has been deprecated and should not be enabled.
- */
-TEST_P(GraphicsComposerAidlCommandTest, SkipValidateDeprecatedTest) {
-    if (getInterfaceVersion() <= 1) {
-        GTEST_SUCCEED() << "HAL at version 1 or lower can contain Capability::SKIP_VALIDATE.";
-        return;
-    }
-    ASSERT_FALSE(hasCapability(Capability::SKIP_VALIDATE))
-            << "Found Capability::SKIP_VALIDATE capability.";
-}
-
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, GraphicsComposerAidlCommandTest,
         testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
         ::android::PrintInstanceNameToString);
-
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, GraphicsComposerAidlTest,
         testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
         ::android::PrintInstanceNameToString);
-}  // namespace
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlV2Test);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerAidlV2Test,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlV3Test);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerAidlV3Test,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandV2Test);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerAidlCommandV2Test,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
+        ::android::PrintInstanceNameToString);
+
 }  // namespace aidl::android::hardware::graphics::composer3::vts
 
 int main(int argc, char** argv) {
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index e4a84e1..bae362f 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -677,7 +677,7 @@
 
     const native_handle_t* clonedBufferHandle;
     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
-    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    error = mGralloc->getMapper()->freeBuffer(const_cast<native_handle_t*>(clonedBufferHandle));
     EXPECT_EQ(Error::BAD_BUFFER, error)
             << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
 
@@ -2223,11 +2223,14 @@
     // Keep optional metadata types below and populate the encoded metadata vec
     // with some arbitrary different metadata because the common gralloc4::decode*()
     // functions do not distinguish between an empty vec and bad value.
-    ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+    if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) >= __ANDROID_API_T__) {
+        // Some old grallocs shipped with broken validation.
+        ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
+        ASSERT_EQ(Error::UNSUPPORTED,
+                  mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
+        ASSERT_EQ(Error::UNSUPPORTED,
+                  mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+    }
 }
 
 /**
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 2c06353..b329de2 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -1371,6 +1371,28 @@
     EXPECT_EQ(buffer->info().usage, *value);
 }
 
+TEST_P(GraphicsMapperStableCTests, GetUsage64) {
+    BufferDescriptorInfo info{
+            .name = {"VTS_TEMP"},
+            .width = 64,
+            .height = 64,
+            .layerCount = 1,
+            .format = PixelFormat::RGBA_8888,
+            .usage = BufferUsage::FRONT_BUFFER | BufferUsage::GPU_RENDER_TARGET |
+                     BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE,
+            .reservedSize = 0,
+    };
+    if (!isSupported(info)) {
+        GTEST_SKIP();
+    }
+    auto buffer = allocate(info);
+    auto bufferHandle = buffer->import();
+    auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
+    ASSERT_TRUE(value.has_value());
+    using T = std::underlying_type_t<BufferUsage>;
+    EXPECT_EQ(static_cast<T>(buffer->info().usage), static_cast<T>(*value));
+}
+
 TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
     auto buffer = allocateGeneric();
     auto bufferHandle = buffer->import();
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
index 3680d4d..31b4679 100644
--- a/health/1.0/default/convert.cpp
+++ b/health/1.0/default/convert.cpp
@@ -26,19 +26,18 @@
     config.periodicChoresIntervalFast = hc->periodic_chores_interval_fast;
     config.periodicChoresIntervalSlow = hc->periodic_chores_interval_slow;
 
-    config.batteryStatusPath        = hc->batteryStatusPath.string();
-    config.batteryHealthPath        = hc->batteryHealthPath.string();
-    config.batteryPresentPath       = hc->batteryPresentPath.string();
-    config.batteryCapacityPath      = hc->batteryCapacityPath.string();
-    config.batteryVoltagePath       = hc->batteryVoltagePath.string();
-    config.batteryTemperaturePath   = hc->batteryTemperaturePath.string();
-    config.batteryTechnologyPath    = hc->batteryTechnologyPath.string();
-    config.batteryCurrentNowPath    = hc->batteryCurrentNowPath.string();
-    config.batteryCurrentAvgPath    = hc->batteryCurrentAvgPath.string();
-    config.batteryChargeCounterPath = hc->batteryChargeCounterPath.string();
-    config.batteryFullChargePath    = hc->batteryFullChargePath.string();
-    config.batteryCycleCountPath    = hc->batteryCycleCountPath.string();
-
+    config.batteryStatusPath = hc->batteryStatusPath.c_str();
+    config.batteryHealthPath = hc->batteryHealthPath.c_str();
+    config.batteryPresentPath = hc->batteryPresentPath.c_str();
+    config.batteryCapacityPath = hc->batteryCapacityPath.c_str();
+    config.batteryVoltagePath = hc->batteryVoltagePath.c_str();
+    config.batteryTemperaturePath = hc->batteryTemperaturePath.c_str();
+    config.batteryTechnologyPath = hc->batteryTechnologyPath.c_str();
+    config.batteryCurrentNowPath = hc->batteryCurrentNowPath.c_str();
+    config.batteryCurrentAvgPath = hc->batteryCurrentAvgPath.c_str();
+    config.batteryChargeCounterPath = hc->batteryChargeCounterPath.c_str();
+    config.batteryFullChargePath = hc->batteryFullChargePath.c_str();
+    config.batteryCycleCountPath = hc->batteryCycleCountPath.c_str();
 }
 
 void convertFromHealthConfig(const HealthConfig& c, struct healthd_config *hc) {
diff --git a/health/2.0/vts/OWNERS b/health/2.0/vts/OWNERS
deleted file mode 100644
index 9f96f51..0000000
--- a/health/2.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 30545
-elsk@google.com
-sspatil@google.com
diff --git a/health/2.1/vts/OWNERS b/health/2.1/vts/OWNERS
deleted file mode 100644
index a6803cd..0000000
--- a/health/2.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elsk@google.com
-sspatil@google.com
diff --git a/health/2.1/vts/functional/OWNERS b/health/2.1/vts/functional/OWNERS
deleted file mode 100644
index cd06415..0000000
--- a/health/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 30545
-elsk@google.com
diff --git a/health/aidl/OWNERS b/health/OWNERS
similarity index 98%
rename from health/aidl/OWNERS
rename to health/OWNERS
index 0f1bee2..1d4d086 100644
--- a/health/aidl/OWNERS
+++ b/health/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 30545
+
+apelosi@google.com
 elsk@google.com
 smoreland@google.com
 wjack@google.com
-apelosi@google.com
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index f401643..4ad8f50 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -214,6 +214,7 @@
     } else {
         ::android::base::WriteStringToFd(res.getDescription(), fd);
     }
+    ::android::base::WriteStringToFd("\n", fd);
 
     fsync(fd);
     return STATUS_OK;
@@ -272,7 +273,11 @@
 
     {
         std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
-        callbacks_.emplace_back(LinkedCallback::Make(ref<Health>(), callback));
+        auto linked_callback_result = LinkedCallback::Make(ref<Health>(), callback);
+        if (!linked_callback_result.ok()) {
+            return ndk::ScopedAStatus::fromStatus(-linked_callback_result.error().code());
+        }
+        callbacks_.emplace_back(std::move(*linked_callback_result));
         // unlock
     }
 
diff --git a/health/aidl/default/LinkedCallback.cpp b/health/aidl/default/LinkedCallback.cpp
index 2985ffe..26e99f9 100644
--- a/health/aidl/default/LinkedCallback.cpp
+++ b/health/aidl/default/LinkedCallback.cpp
@@ -24,7 +24,7 @@
 
 namespace aidl::android::hardware::health {
 
-std::unique_ptr<LinkedCallback> LinkedCallback::Make(
+::android::base::Result<std::unique_ptr<LinkedCallback>> LinkedCallback::Make(
         std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback) {
     std::unique_ptr<LinkedCallback> ret(new LinkedCallback());
     binder_status_t linkRet =
@@ -32,7 +32,7 @@
                                  reinterpret_cast<void*>(ret.get()));
     if (linkRet != ::STATUS_OK) {
         LOG(WARNING) << __func__ << "Cannot link to death: " << linkRet;
-        return nullptr;
+        return ::android::base::Error(-linkRet);
     }
     ret->service_ = service;
     ret->callback_ = std::move(callback);
diff --git a/health/aidl/default/LinkedCallback.h b/health/aidl/default/LinkedCallback.h
index 82490a7..da494c9 100644
--- a/health/aidl/default/LinkedCallback.h
+++ b/health/aidl/default/LinkedCallback.h
@@ -20,6 +20,7 @@
 
 #include <aidl/android/hardware/health/IHealthInfoCallback.h>
 #include <android-base/macros.h>
+#include <android-base/result.h>
 #include <android/binder_auto_utils.h>
 
 #include <health-impl/Health.h>
@@ -34,8 +35,8 @@
     // service->death_reciepient() should be from CreateDeathRecipient().
     // Not using a strong reference to |service| to avoid circular reference. The lifetime
     // of |service| must be longer than this LinkedCallback object.
-    static std::unique_ptr<LinkedCallback> Make(std::shared_ptr<Health> service,
-                                                std::shared_ptr<IHealthInfoCallback> callback);
+    static ::android::base::Result<std::unique_ptr<LinkedCallback>> Make(
+            std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback);
 
     // Automatically unlinkToDeath upon destruction. So, it is always safe to reinterpret_cast
     // the cookie back to the LinkedCallback object.
diff --git a/health/storage/1.0/vts/functional/OWNERS b/health/storage/OWNERS
similarity index 79%
rename from health/storage/1.0/vts/functional/OWNERS
rename to health/storage/OWNERS
index 8f66979..7af8d99 100644
--- a/health/storage/1.0/vts/functional/OWNERS
+++ b/health/storage/OWNERS
@@ -1,3 +1,6 @@
 # Bug component: 30545
-elsk@google.com
+
+set noparent
+
 jaegeuk@google.com
+elsk@google.com
diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h
index 54b2740..fc3066e 100644
--- a/health/utils/libhealthloop/include/health/HealthLoop.h
+++ b/health/utils/libhealthloop/include/health/HealthLoop.h
@@ -15,6 +15,7 @@
  */
 #pragma once
 
+#include <functional>
 #include <memory>
 #include <mutex>
 #include <vector>
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 3096fe5..d62d055 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -22,15 +22,8 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library {
-    name: "android.hardware.identity-support-lib",
-    vendor_available: true,
-    srcs: [
-        "src/IdentityCredentialSupport.cpp",
-    ],
-    export_include_dirs: [
-        "include",
-    ],
+cc_defaults {
+    name: "android.hardware.identity-support-lib-deps",
     shared_libs: [
         "android.hardware.keymaster@4.0",
         "libcrypto",
@@ -47,19 +40,36 @@
     ],
 }
 
+cc_library {
+    name: "android.hardware.identity-support-lib",
+    vendor_available: true,
+    defaults: [
+        "android.hardware.identity-support-lib-deps",
+    ],
+    srcs: [
+        "src/IdentityCredentialSupport.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+}
+
 cc_test {
     name: "android.hardware.identity-support-lib-test",
     srcs: [
         "tests/IdentityCredentialSupportTest.cpp",
     ],
+    defaults: [
+        "android.hardware.identity-support-lib-deps",
+    ],
     shared_libs: [
-        "android.hardware.identity-support-lib",
         "libcrypto",
         "libbase",
         "libhidlbase",
         "libhardware",
     ],
     static_libs: [
+        "android.hardware.identity-support-lib",
         "libcppbor_external",
         "libgmock",
     ],
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 95a14b2..f23f270 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -20,6 +20,9 @@
         java: {
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 554afe7..65b3dfa 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2617,10 +2617,11 @@
     EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
     RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
 
-    size_t modulus_len = BN_num_bytes(rsa->n);
+    const BIGNUM* n = RSA_get0_n(rsa.get());
+    size_t modulus_len = BN_num_bytes(n);
     ASSERT_EQ(1024U / 8, modulus_len);
     std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
-    BN_bn2bin(rsa->n, modulus_buf.get());
+    BN_bn2bin(n, modulus_buf.get());
 
     // The modulus is too big to encrypt.
     string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2632,10 +2633,12 @@
     EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
 
     // One smaller than the modulus is okay.
-    BN_sub(rsa->n, rsa->n, BN_value_one());
-    modulus_len = BN_num_bytes(rsa->n);
+    BIGNUM_Ptr n_minus_1(BN_new());
+    ASSERT_TRUE(n_minus_1);
+    ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+    modulus_len = BN_num_bytes(n_minus_1.get());
     ASSERT_EQ(1024U / 8, modulus_len);
-    BN_bn2bin(rsa->n, modulus_buf.get());
+    BN_bn2bin(n_minus_1.get(), modulus_buf.get());
     message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
     EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index b709904..96580c0 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2449,10 +2449,11 @@
     EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
     RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
 
-    size_t modulus_len = BN_num_bytes(rsa->n);
+    const BIGNUM* n = RSA_get0_n(rsa.get());
+    size_t modulus_len = BN_num_bytes(n);
     ASSERT_EQ(2048U / 8, modulus_len);
     std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
-    BN_bn2bin(rsa->n, modulus_buf.get());
+    BN_bn2bin(n, modulus_buf.get());
 
     // The modulus is too big to encrypt.
     string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
@@ -2464,10 +2465,12 @@
     EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
 
     // One smaller than the modulus is okay.
-    BN_sub(rsa->n, rsa->n, BN_value_one());
-    modulus_len = BN_num_bytes(rsa->n);
+    BIGNUM_Ptr n_minus_1(BN_new());
+    ASSERT_TRUE(n_minus_1);
+    ASSERT_TRUE(BN_sub(n_minus_1.get(), n, BN_value_one()));
+    modulus_len = BN_num_bytes(n_minus_1.get());
     ASSERT_EQ(2048U / 8, modulus_len);
-    BN_bn2bin(rsa->n, modulus_buf.get());
+    BN_bn2bin(n_minus_1.get(), modulus_buf.get());
     message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
     EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
diff --git a/keymaster/TEST_MAPPING b/keymaster/TEST_MAPPING
new file mode 100644
index 0000000..8cbf3e1
--- /dev/null
+++ b/keymaster/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalKeymasterV3_0TargetTest"
+    },
+    {
+      "name": "VtsHalKeymasterV4_0TargetTest"
+    },
+    {
+      "name": "VtsHalKeymasterV4_1TargetTest"
+    }
+  ]
+}
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index c11934f..c9fba95 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -18,6 +18,9 @@
         java: {
             sdk_version: "module_current",
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/light/aidl/aidl_api/android.hardware.light/2/.hash b/light/aidl/aidl_api/android.hardware.light/2/.hash
index d27f4ad..2d4e7f0 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/.hash
+++ b/light/aidl/aidl_api/android.hardware.light/2/.hash
@@ -1 +1,2 @@
 c8b1e8ebb88c57dcb2c350a8d9b722e77dd864c8
+c7d3d941d303c70d1c22759a0b09e41930c1cddb
diff --git a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
index 25a2dce..5ac2a34 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLight.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLight {
   int id;
   int ordinal;
diff --git a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
index 40e520b..2878ce2 100644
--- a/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/2/android/hardware/light/HwLightState.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLightState {
   int color;
   android.hardware.light.FlashMode flashMode;
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
index 25a2dce..5ac2a34 100644
--- a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLight {
   int id;
   int ordinal;
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
index 40e520b..2878ce2 100644
--- a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.light;
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLightState {
   int color;
   android.hardware.light.FlashMode flashMode;
diff --git a/light/aidl/android/hardware/light/HwLight.aidl b/light/aidl/android/hardware/light/HwLight.aidl
index 43fdb4b..8db32cc 100644
--- a/light/aidl/android/hardware/light/HwLight.aidl
+++ b/light/aidl/android/hardware/light/HwLight.aidl
@@ -22,7 +22,7 @@
  * A description of a single light. Multiple lights can map to the same physical
  * LED. Separate physical LEDs are always represented by separate instances.
  */
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLight {
     /**
      * Integer ID used for controlling this light
diff --git a/light/aidl/android/hardware/light/HwLightState.aidl b/light/aidl/android/hardware/light/HwLightState.aidl
index 24d3250..3ba6c78 100644
--- a/light/aidl/android/hardware/light/HwLightState.aidl
+++ b/light/aidl/android/hardware/light/HwLightState.aidl
@@ -25,7 +25,7 @@
  * Not all lights must support all parameters. If you
  * can do something backward-compatible, do it.
  */
-@VintfStability
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable HwLightState {
     /**
      * The color of the LED in ARGB.
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
index 7920503..285329e 100644
--- a/light/aidl/default/Android.bp
+++ b/light/aidl/default/Android.bp
@@ -7,19 +7,17 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_binary {
+rust_binary {
     name: "android.hardware.lights-service.example",
     relative_install_path: "hw",
     init_rc: ["lights-default.rc"],
     vintf_fragments: ["lights-default.xml"],
     vendor: true,
-    shared_libs: [
-        "libbase",
-        "libbinder_ndk",
-        "android.hardware.light-V2-ndk",
+    rustlibs: [
+        "liblogger",
+        "liblog_rust",
+        "libbinder_rs",
+        "android.hardware.light-V2-rust",
     ],
-    srcs: [
-        "Lights.cpp",
-        "main.cpp",
-    ],
+    srcs: [ "main.rs" ],
 }
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
deleted file mode 100644
index 9bf3b20..0000000
--- a/light/aidl/default/Lights.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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 "Lights.h"
-
-#include <android-base/logging.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-static constexpr int kNumDefaultLights = 3;
-
-ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
-    LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
-    if (id <= 0 || id > kNumDefaultLights) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    } else {
-        return ndk::ScopedAStatus::ok();
-    }
-}
-
-ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* lights) {
-    for (int i = 1; i <= kNumDefaultLights; i++) {
-        lights->push_back({i, i});
-    }
-    LOG(INFO) << "Lights reporting supported lights";
-    return ndk::ScopedAStatus::ok();
-}
-
-}  // namespace light
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
deleted file mode 100644
index cba147f..0000000
--- a/light/aidl/default/Lights.h
+++ /dev/null
@@ -1,35 +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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/light/BnLights.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-// Default implementation that reports a few placeholder lights.
-class Lights : public BnLights {
-    ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
-    ndk::ScopedAStatus getLights(std::vector<HwLight>* lights) override;
-};
-
-}  // namespace light
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/light/aidl/default/lights.rs b/light/aidl/default/lights.rs
new file mode 100644
index 0000000..6c8aa3f
--- /dev/null
+++ b/light/aidl/default/lights.rs
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//! This module implements the ILights AIDL interface.
+
+use std::collections::HashMap;
+use std::sync::Mutex;
+
+use log::info;
+
+use android_hardware_light::aidl::android::hardware::light::{
+    HwLight::HwLight, HwLightState::HwLightState, ILights::ILights, LightType::LightType,
+};
+
+use binder::{ExceptionCode, Interface, Status};
+
+struct Light {
+    hw_light: HwLight,
+    state: HwLightState,
+}
+
+const NUM_DEFAULT_LIGHTS: i32 = 3;
+
+/// Defined so we can implement the ILights AIDL interface.
+pub struct LightsService {
+    lights: Mutex<HashMap<i32, Light>>,
+}
+
+impl Interface for LightsService {}
+
+impl LightsService {
+    fn new(hw_lights: impl IntoIterator<Item = HwLight>) -> Self {
+        let mut lights_map = HashMap::new();
+
+        for hw_light in hw_lights {
+            lights_map.insert(hw_light.id, Light { hw_light, state: Default::default() });
+        }
+
+        Self { lights: Mutex::new(lights_map) }
+    }
+}
+
+impl Default for LightsService {
+    fn default() -> Self {
+        let id_mapping_closure =
+            |light_id| HwLight { id: light_id, ordinal: light_id, r#type: LightType::BACKLIGHT };
+
+        Self::new((1..=NUM_DEFAULT_LIGHTS).map(id_mapping_closure))
+    }
+}
+
+impl ILights for LightsService {
+    fn setLightState(&self, id: i32, state: &HwLightState) -> binder::Result<()> {
+        info!("Lights setting state for id={} to color {:x}", id, state.color);
+
+        if let Some(light) = self.lights.lock().unwrap().get_mut(&id) {
+            light.state = *state;
+            Ok(())
+        } else {
+            Err(Status::new_exception(ExceptionCode::UNSUPPORTED_OPERATION, None))
+        }
+    }
+
+    fn getLights(&self) -> binder::Result<Vec<HwLight>> {
+        info!("Lights reporting supported lights");
+        Ok(self.lights.lock().unwrap().values().map(|light| light.hw_light).collect())
+    }
+}
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
deleted file mode 100644
index 54e1316..0000000
--- a/light/aidl/default/main.cpp
+++ /dev/null
@@ -1,35 +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.
- */
-
-#include "Lights.h"
-
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-using ::aidl::android::hardware::light::Lights;
-
-int main() {
-    ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
-
-    const std::string instance = std::string() + Lights::descriptor + "/default";
-    binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
-    CHECK_EQ(status, STATUS_OK);
-
-    ABinderProcess_joinThreadPool();
-    return EXIT_FAILURE;  // should not reached
-}
diff --git a/light/aidl/default/main.rs b/light/aidl/default/main.rs
new file mode 100644
index 0000000..8f32470
--- /dev/null
+++ b/light/aidl/default/main.rs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//! This implements the Lights Example Service.
+
+use android_hardware_light::aidl::android::hardware::light::ILights::{BnLights, ILights};
+use binder::BinderFeatures;
+
+mod lights;
+use lights::LightsService;
+
+const LOG_TAG: &str = "lights_service_example_rust";
+
+use log::Level;
+
+fn main() {
+    let logger_success = logger::init(
+        logger::Config::default().with_tag_on_device(LOG_TAG).with_min_level(Level::Trace),
+    );
+    if !logger_success {
+        panic!("{LOG_TAG}: Failed to start logger.");
+    }
+
+    binder::ProcessState::set_thread_pool_max_thread_count(0);
+
+    let lights_service = LightsService::default();
+    let lights_service_binder = BnLights::new_binder(lights_service, BinderFeatures::default());
+
+    let service_name = format!("{}/default", LightsService::get_descriptor());
+    binder::add_service(&service_name, lights_service_binder.as_binder())
+        .expect("Failed to register service");
+
+    binder::ProcessState::join_thread_pool()
+}
diff --git a/staging/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
similarity index 93%
rename from staging/c2/aidl/Android.bp
rename to media/c2/aidl/Android.bp
index b9da7ad..75d74ac 100644
--- a/staging/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -13,15 +13,15 @@
     name: "android.hardware.media.c2",
     vendor_available: true,
     double_loadable: true,
-    unstable: true,
     srcs: ["android/hardware/media/c2/*.aidl"],
     include_dirs: [
-        "frameworks/native/aidl/gui",
+        "frameworks/base/core/java",
     ],
     imports: [
         "android.hardware.common-V2",
         "android.hardware.media.bufferpool2-V1",
     ],
+    stability: "vintf",
     backend: {
         cpp: {
             enabled: false,
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..460ff97
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+union BaseBlock {
+  android.hardware.common.NativeHandle nativeBlock;
+  android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..7b3005e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Block {
+  int index;
+  android.hardware.media.c2.Params meta;
+  android.hardware.common.NativeHandle fence;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..b632932
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Buffer {
+  android.hardware.media.c2.Params info;
+  android.hardware.media.c2.Block[] blocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..909476c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable FieldDescriptor {
+  android.hardware.media.c2.FieldId fieldId;
+  android.hardware.media.c2.FieldDescriptor.Type type;
+  int structIndex;
+  int extent;
+  String name;
+  android.hardware.media.c2.FieldDescriptor.NamedValue[] namedValues;
+  @Backing(type="int") @VintfStability
+  enum Type {
+    NO_INIT = 0,
+    INT32,
+    UINT32,
+    CNTR32,
+    INT64,
+    UINT64,
+    CNTR64,
+    FLOAT,
+    STRING = 0x100,
+    BLOB,
+    STRUCT = 0x20000,
+  }
+  @VintfStability
+  parcelable NamedValue {
+    String name;
+    long value;
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..935b85d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable FieldId {
+  int offset;
+  int sizeBytes;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..69060be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+union FieldSupportedValues {
+  boolean empty;
+  android.hardware.media.c2.ValueRange range;
+  long[] values;
+  long[] flags;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..6a5fbe2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+  android.hardware.media.c2.ParamField field;
+  android.hardware.media.c2.FieldSupportedValuesQuery.Type type;
+  @Backing(type="int") @VintfStability
+  enum Type {
+    POSSIBLE = 0,
+    CURRENT,
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..187e3eb
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+  android.hardware.media.c2.Status status;
+  android.hardware.media.c2.FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..07bfb72
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable FrameData {
+  int flags;
+  android.hardware.media.c2.WorkOrdinal ordinal;
+  android.hardware.media.c2.Buffer[] buffers;
+  android.hardware.media.c2.Params configUpdate;
+  android.hardware.media.c2.InfoBuffer[] infoBuffers;
+  const int DROP_FRAME = (1 << 0) /* 1 */;
+  const int END_OF_STREAM = (1 << 1) /* 2 */;
+  const int DISCARD_FRAME = (1 << 2) /* 4 */;
+  const int FLAG_INCOMPLETE = (1 << 3) /* 8 */;
+  const int CODEC_CONFIG = (1 << 31) /* -2147483648 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..c7d8a97
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IComponent {
+  android.hardware.common.NativeHandle configureVideoTunnel(in int avSyncHwId);
+  android.hardware.media.c2.IComponent.BlockPool createBlockPool(in android.hardware.media.c2.IComponent.BlockPoolAllocator allocator);
+  void destroyBlockPool(in long blockPoolId);
+  void drain(in boolean withEos);
+  android.hardware.media.c2.WorkBundle flush();
+  android.hardware.media.c2.IComponentInterface getInterface();
+  void queue(in android.hardware.media.c2.WorkBundle workBundle);
+  void release();
+  void reset();
+  void start();
+  void stop();
+  parcelable BlockPool {
+    long blockPoolId;
+    android.hardware.media.c2.IConfigurable configurable;
+  }
+  union BlockPoolAllocator {
+    int allocatorId;
+    android.hardware.media.c2.IGraphicBufferAllocator igba;
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..2350dae
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IComponentInterface {
+  android.hardware.media.c2.IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..f6f2a63
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IComponentListener {
+  oneway void onError(in android.hardware.media.c2.Status status, in int errorCode);
+  oneway void onFramesRendered(in android.hardware.media.c2.IComponentListener.RenderedFrame[] renderedFrames);
+  oneway void onInputBuffersReleased(in android.hardware.media.c2.IComponentListener.InputBuffer[] inputBuffers);
+  oneway void onTripped(in android.hardware.media.c2.SettingResult[] settingResults);
+  oneway void onWorkDone(in android.hardware.media.c2.WorkBundle workBundle);
+  @VintfStability
+  parcelable InputBuffer {
+    long frameIndex;
+    int arrayIndex;
+  }
+  @VintfStability
+  parcelable RenderedFrame {
+    long bufferQueueId;
+    int slotId;
+    long timestampNs;
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..d1b5915
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IComponentStore {
+  void copyBuffer(in android.hardware.media.c2.Buffer src, in android.hardware.media.c2.Buffer dst);
+  android.hardware.media.c2.IComponent createComponent(in String name, in android.hardware.media.c2.IComponentListener listener, in android.hardware.media.bufferpool2.IClientManager pool);
+  android.hardware.media.c2.IComponentInterface createInterface(in String name);
+  android.hardware.media.c2.IConfigurable getConfigurable();
+  android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+  android.hardware.media.c2.StructDescriptor[] getStructDescriptors(in int[] indices);
+  android.hardware.media.c2.IComponentStore.ComponentTraits[] listComponents();
+  @VintfStability
+  parcelable ComponentTraits {
+    String name;
+    android.hardware.media.c2.IComponentStore.ComponentTraits.Domain domain;
+    android.hardware.media.c2.IComponentStore.ComponentTraits.Kind kind;
+    int rank;
+    String mediaType;
+    String[] aliases;
+    @Backing(type="int") @VintfStability
+    enum Kind {
+      OTHER = 0,
+      DECODER,
+      ENCODER,
+    }
+    @Backing(type="int") @VintfStability
+    enum Domain {
+      OTHER = 0,
+      VIDEO,
+      AUDIO,
+      IMAGE,
+    }
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..32f5abd
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IConfigurable {
+  android.hardware.media.c2.IConfigurable.ConfigResult config(in android.hardware.media.c2.Params inParams, in boolean mayBlock);
+  int getId();
+  String getName();
+  android.hardware.media.c2.Params query(in int[] indices, in boolean mayBlock);
+  android.hardware.media.c2.ParamDescriptor[] querySupportedParams(in int start, in int count);
+  android.hardware.media.c2.FieldSupportedValuesQueryResult[] querySupportedValues(in android.hardware.media.c2.FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+  @VintfStability
+  parcelable ConfigResult {
+    android.hardware.media.c2.Params params;
+    android.hardware.media.c2.SettingResult[] failures;
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
new file mode 100644
index 0000000..da3d5ff
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+interface IGraphicBufferAllocator {
+  android.hardware.media.c2.IGraphicBufferAllocator.Allocation allocate(in android.hardware.media.c2.IGraphicBufferAllocator.Description desc);
+  boolean deallocate(in long id);
+  android.hardware.media.c2.IGraphicBufferAllocator.WaitableFds getWaitableFds();
+  parcelable Allocation {
+    android.hardware.HardwareBuffer buffer;
+    ParcelFileDescriptor fence;
+  }
+  parcelable Description {
+    int width;
+    int height;
+    int format;
+    long usage;
+  }
+  parcelable WaitableFds {
+    ParcelFileDescriptor allocEvent;
+    ParcelFileDescriptor statusEvent;
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..94cd77d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable InfoBuffer {
+  int index;
+  android.hardware.media.c2.Buffer buffer;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..6f0ac50
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable ParamDescriptor {
+  int index;
+  int attrib;
+  String name;
+  int[] dependencies;
+  const int ATTRIBUTE_REQUIRED = (1 << 0) /* 1 */;
+  const int ATTRIBUTE_PERSISTENT = (1 << 1) /* 2 */;
+  const int ATTRIBUTE_STRICT = (1 << 2) /* 4 */;
+  const int ATTRIBUTE_READ_ONLY = (1 << 3) /* 8 */;
+  const int ATTRIBUTE_HIDDEN = (1 << 4) /* 16 */;
+  const int ATTRIBUTE_INTERNAL = (1 << 5) /* 32 */;
+  const int ATTRIBUTE_CONST = (1 << 6) /* 64 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..13d2522
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable ParamField {
+  int index;
+  android.hardware.media.c2.FieldId fieldId;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..5a2821c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable ParamFieldValues {
+  android.hardware.media.c2.ParamField paramOrField;
+  android.hardware.media.c2.FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..7d363c0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Params {
+  byte[] params;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..07fc1f3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable SettingResult {
+  android.hardware.media.c2.SettingResult.Failure failure;
+  android.hardware.media.c2.ParamFieldValues field;
+  android.hardware.media.c2.ParamFieldValues[] conflicts;
+  @Backing(type="int") @VintfStability
+  enum Failure {
+    BAD_TYPE,
+    BAD_PORT,
+    BAD_INDEX,
+    READ_ONLY,
+    MISMATCH,
+    BAD_VALUE,
+    CONFLICT,
+    UNSUPPORTED,
+    INFO_BAD_VALUE,
+    INFO_CONFLICT,
+  }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..8b430d2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Status {
+  int status;
+  const int OK = 0;
+  const int BAD_VALUE = (-22) /* -22 */;
+  const int BAD_INDEX = (-75) /* -75 */;
+  const int CANNOT_DO = (-2147483646) /* -2147483646 */;
+  const int DUPLICATE = (-17) /* -17 */;
+  const int NOT_FOUND = (-2) /* -2 */;
+  const int BAD_STATE = (-38) /* -38 */;
+  const int BLOCKING = (-9930) /* -9930 */;
+  const int NO_MEMORY = (-12) /* -12 */;
+  const int REFUSED = (-1) /* -1 */;
+  const int TIMED_OUT = (-110) /* -110 */;
+  const int OMITTED = (-74) /* -74 */;
+  const int CORRUPTED = (-2147483648) /* -2147483648 */;
+  const int NO_INIT = (-19) /* -19 */;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..58268e0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable StructDescriptor {
+  int type;
+  android.hardware.media.c2.FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..db71ce0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable ValueRange {
+  long min;
+  long max;
+  long step;
+  long num;
+  long denom;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..a534348
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Work {
+  byte[] chainInfo;
+  android.hardware.media.c2.FrameData input;
+  android.hardware.media.c2.Worklet[] worklets;
+  int workletsProcessed;
+  android.hardware.media.c2.Status result;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..84708a8
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable WorkBundle {
+  android.hardware.media.c2.Work[] works;
+  android.hardware.media.c2.BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..2833df3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable WorkOrdinal {
+  long timestampUs;
+  long frameIndex;
+  long customOrdinal;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..a79abf2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Worklet {
+  int componentId;
+  byte[] tunings;
+  android.hardware.media.c2.SettingResult[] failures;
+  android.hardware.media.c2.FrameData output;
+}
diff --git a/staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
rename to media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
index 16e7653..8b8b8e0 100644
--- a/staging/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
@@ -25,6 +25,7 @@
  * decoded data, codec-specific data, and other codec-related data are all sent
  * in the form of BaseBlocks.
  */
+@VintfStability
 union BaseBlock {
     /**
      * #nativeBlock is the opaque representation of a buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Block.aidl b/media/c2/aidl/android/hardware/media/c2/Block.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Block.aidl
rename to media/c2/aidl/android/hardware/media/c2/Block.aidl
index 4da8490..34aa7b1 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Block.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Block.aidl
@@ -26,6 +26,7 @@
  * attributes may differ among `Block` objects that refer to the same
  * `BaseBlock` in the same `WorkBundle`.
  */
+@VintfStability
 parcelable Block {
     /**
      * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
diff --git a/staging/c2/aidl/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Buffer.aidl
rename to media/c2/aidl/android/hardware/media/c2/Buffer.aidl
index fe01b64..d2dcf2d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Buffer.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
@@ -24,6 +24,7 @@
  *
  * This is a part of @ref FrameData.
  */
+@VintfStability
 parcelable Buffer {
     /**
      * Metadata associated with the buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
similarity index 97%
rename from staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
index 3dd14cd..a2774ec 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
@@ -21,10 +21,12 @@
 /**
  * Description of a field inside a C2Param structure.
  */
+@VintfStability
 parcelable FieldDescriptor {
     /**
      * Possible types of the field.
      */
+    @VintfStability
     @Backing(type="int")
     enum Type {
         NO_INIT = 0,
@@ -53,6 +55,7 @@
      * Named value type. This is used for defining an enum value for a numeric
      * type.
      */
+    @VintfStability
     parcelable NamedValue {
         /**
          * Name of the enum value. This must be unique for each enum value in
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldId.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldId.aidl
index c53f7a5..68bf058 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldId.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
@@ -22,6 +22,7 @@
  * Within a given C2Param structure, each field is uniquely identified by @ref
  * FieldId.
  */
+@VintfStability
 parcelable FieldId {
     /**
      * Offset of the field in bytes.
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
index 5f4ad2a..6c2033b 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -26,6 +26,7 @@
  * The intended type of values must be made clear in the context where
  * `FieldSupportedValues` is used.
  */
+@VintfStability
 union FieldSupportedValues {
     /**
      * No supported values
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
similarity index 97%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
index 33a8170..bdaaef6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -22,7 +22,9 @@
  * Query information for supported values of a field. This is used as input to
  * IConfigurable::querySupportedValues().
  */
+@VintfStability
 parcelable FieldSupportedValuesQuery {
+    @VintfStability
     @Backing(type="int")
     enum Type {
         /**
diff --git a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
rename to media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
index 133712a..b5c28c6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -23,6 +23,7 @@
  * This structure is used to hold the result from
  * IConfigurable::querySupportedValues().
  */
+@VintfStability
 parcelable FieldSupportedValuesQueryResult {
     /**
      * Result of the query. Possible values are
diff --git a/staging/c2/aidl/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/FrameData.aidl
rename to media/c2/aidl/android/hardware/media/c2/FrameData.aidl
index 81c76be..15c1b6d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/FrameData.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
@@ -31,6 +31,7 @@
  * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
  * standard.
  */
+@VintfStability
 parcelable FrameData {
     /** List of frame flags */
     /**
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
similarity index 92%
rename from staging/c2/aidl/android/hardware/media/c2/IComponent.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponent.aidl
index bea4b70..a7d94b1 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponent.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
@@ -17,12 +17,11 @@
 package android.hardware.media.c2;
 
 import android.hardware.common.NativeHandle;
-import android.view.Surface;
 
 import android.hardware.media.c2.IComponentInterface;
 import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.IGraphicBufferAllocator;
 import android.hardware.media.c2.WorkBundle;
-import android.hardware.media.c2.SurfaceSyncObj;
 
 /**
  * Interface for an AIDL Codec2 component.
@@ -32,6 +31,7 @@
  * All methods in `IComponent` must not block. If a method call cannot be
  * completed in a timely manner, it must throw `Status::TIMED_OUT`.
  */
+@VintfStability
 interface IComponent {
     /**
      * The reference object from framwork to HAL C2BlockPool.
@@ -44,6 +44,18 @@
         long blockPoolId;
         IConfigurable configurable;
     }
+
+    /**
+     * Allocator for C2BlockPool.
+     *
+     * C2BlockPool will use a C2Allocator which is specified by an id.
+     * or C2AIDL allocator interface directly.
+     */
+    union BlockPoolAllocator {
+        int allocatorId;
+        IGraphicBufferAllocator igba;
+    }
+
     /**
      * Configures a component for a tunneled playback mode.
      *
@@ -87,7 +99,8 @@
      * destroyBlockPool(), reset() or release(). reset() and release() must
      * destroy all `C2BlockPool` objects that have been created.
      *
-     * @param allocatorId Id of a `C2Allocator`.
+     * @param allocator AIDL allocator interface or C2Allocator specifier
+     *     for C2BlockPool
      * @param out configurable Configuration interface for the created pool. This
      *     must not be null.
      * @return Created block pool information. This could be used to config/query and
@@ -98,7 +111,7 @@
      *   - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
      *   - `Status::CORRUPTED` - Some unknown error occurred.
      */
-    BlockPool createBlockPool(in int allocatorId);
+    BlockPool createBlockPool(in BlockPoolAllocator allocator);
 
     /**
      * Destroys a local block pool previously created by createBlockPool().
@@ -233,25 +246,6 @@
     void reset();
 
     /**
-     * Starts using a surface for output with a synchronization object
-     *
-     * This method must not block.
-     *
-     * @param blockPoolId Id of the `C2BlockPool` to be associated with the
-     *     output surface.
-     * @param surface Output surface.
-     * @param syncObject synchronization object for buffer allocation between
-     *     Framework and Component.
-     * @throws ServiceSpecificException with one of the following values:
-     *   - `Status::CANNOT_DO` - The component does not support an output surface.
-     *   - `Status::REFUSED`   - The output surface cannot be accessed.
-     *   - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
-     *   - `Status::CORRUPTED` - Some unknown error occurred.
-     */
-    void setOutputSurface(in long blockPoolId, in Surface surface,
-        in SurfaceSyncObj syncObject);
-
-    /**
      * Starts the component.
      *
      * This method must be supported in stopped state as well as tripped state.
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
index 4589115..9db81e6 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
@@ -26,6 +26,7 @@
  *
  * An actual component exposes this interface via IComponent::getInterface().
  */
+@VintfStability
 interface IComponentInterface {
     /**
      * Returns the @ref IConfigurable instance associated to this component
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
index 786c8f1..75500b7 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
@@ -23,11 +23,13 @@
 /**
  * Callback interface for handling notifications from @ref IComponent.
  */
+@VintfStability
 oneway interface IComponentListener {
     /**
      * Identifying information for an input buffer previously queued to the
      * component via IComponent::queue().
      */
+    @VintfStability
     parcelable InputBuffer {
         /**
          * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
@@ -43,6 +45,7 @@
     /**
      * Information about rendering of a frame to a `Surface`.
      */
+    @VintfStability
     parcelable RenderedFrame {
         /**
          * Id of the `BufferQueue` containing the rendered buffer.
diff --git a/staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
rename to media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
index d332bd3..1435a7e 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
@@ -34,17 +34,21 @@
  * @note This is an extension of version 1.1 of `IComponentStore`. The purpose
  * of the extension is to add support for blocking output buffer allocator.
  */
+@VintfStability
 interface IComponentStore {
     /**
      * Component traits.
      */
+    @VintfStability
     parcelable ComponentTraits {
+        @VintfStability
         @Backing(type="int")
         enum Kind {
             OTHER = 0,
             DECODER,
             ENCODER,
         }
+        @VintfStability
         @Backing(type="int")
         enum Domain {
             OTHER = 0,
diff --git a/staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
rename to media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
index 9f79576..7fdb825 100644
--- a/staging/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
@@ -28,6 +28,7 @@
  * This interface must be supported in all states of the owning object, and must
  * not change the state of the owning object.
  */
+@VintfStability
 interface IConfigurable {
     /**
      * Return parcelable for config() interface.
@@ -35,6 +36,7 @@
      * This includes the successful config settings along with the failure reasons of
      * the specified setting.
      */
+    @VintfStability
     parcelable ConfigResult {
         Params params;
         SettingResult[] failures;
diff --git a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
new file mode 100644
index 0000000..1c97214
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.HardwareBuffer;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface for decoder output buffer allocator for HAL process
+ *
+ * A graphic buffer for decoder output is allocated by the interface.
+ */
+@VintfStability
+interface IGraphicBufferAllocator {
+    /**
+     * A graphic buffer allocation.
+     *
+     * buffer is in android.hardware.HardwareBuffer.
+     * fence is provided in order to signal readiness of the buffer I/O inside
+     * underlying Graphics subsystem. This is called a sync fence throughout Android framework.
+     */
+    parcelable Allocation {
+        HardwareBuffer buffer;
+        ParcelFileDescriptor fence;
+    }
+
+    /**
+     * Parameters for a graphic buffer allocation.
+     *
+     * Refer to AHardwareBuffer_Desc(libnativewindow) for details.
+     */
+    parcelable Description {
+        int width;
+        int height;
+        int format;
+        long usage;
+    }
+
+    /**
+     * Allocate a graphic buffer.
+     *
+     * @param desc Allocation parameters.
+     * @return an android.hardware.HardwareBuffer which is basically same to
+     *     AHardwareBuffer. If underlying grpahics system is blocked, c2::Status::Blocked
+     *     will be returned. In this case getWaitableFds() will return file descriptors which
+     *     can be used to construct a waitable object. The waitable object will be notified
+     *     when underlying graphics system is unblocked
+     * @throws ServiceSpecificException with one of the following values:
+     *   - `c2::Status::BAD_STATE` - The client is not in running states.
+     *   - `c2::Status::BLOCKED`   - Underlying graphics system is blocked.
+     *   - `c2::Status::CORRUPTED` - Some unknown error occurred.
+     */
+    Allocation allocate(in Description desc);
+
+    /**
+     * De-allocate a graphic buffer by graphic buffer's unique id.
+     *
+     * @param id graphic buffer's unique id. See also AHardwareBuffer_getId().
+     * @return {@code true} when de-allocate happened, {@code false} otherwise.
+     */
+    boolean deallocate(in long id);
+
+    /**
+     * Fds for waitable object events.
+     *
+     * Fds are created by eventfd() with semaphore mode.
+     * For allocEvent, An integer counter regarding dequeuable buffer count is maintained
+     * by client using read()/write() to the fd. The fd can be checked whether it is
+     * readable via poll(). When in readable status, the specified counter is positive
+     * so allocate/dequeue can happen.
+     *
+     * For statusEvent, the client can notify further allocation is not feasible.
+     * e.g.) life-cycle of the underlying allocator is ended.
+     *
+     * C2Fence object should be implemented based on this Fds. Thus, C2Fence can return
+     * either by allocation being ready or allocation being infeasible by the client status
+     * change.
+     */
+    parcelable WaitableFds {
+        ParcelFileDescriptor allocEvent;
+        ParcelFileDescriptor statusEvent;
+    }
+
+    /**
+     * Gets waiable file descriptors.
+     *
+     * Use this method once and cache it in order not to create unnecessary duplicated fds.
+     * The returned array will have two fds.
+     *
+     * If many waitable objects based on the same fd are competing, all watiable objects will be
+     * notified. After being notified, they should invoke allocate(). At least one of them can
+     * successfully allocate. Others not having an Allocation will have c2::Status::BLOCKED
+     * as return value. They should wait again via waitable objects based on the fds which are
+     * already returned from this interface.
+     *
+     * @return an fd array which will be wrapped to C2Fence and will be waited for
+     *     until allocating is unblocked.
+     */
+    WaitableFds getWaitableFds();
+}
diff --git a/staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
rename to media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
index 7cfabcb..207c4d0 100644
--- a/staging/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
@@ -23,6 +23,7 @@
  *
  * This is a part of @ref FrameData.
  */
+@VintfStability
 parcelable InfoBuffer {
     /**
      * A C2Param structure index.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
index 716c07e..84c6acc 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
@@ -21,6 +21,7 @@
  *
  * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
  */
+@VintfStability
 parcelable ParamDescriptor {
     /** The list of bit flags for attrib */
     /**
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamField.aidl
index 94f737d..64a46bb 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
@@ -21,6 +21,7 @@
 /**
  * Reference to a field in a C2Param structure.
  */
+@VintfStability
 parcelable ParamField {
     /**
      * Index of the C2Param structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
rename to media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
index 4bb9a91..7b74c0e 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
@@ -26,6 +26,7 @@
  * values object. This structure is used when reporting parameter configuration
  * failures and conflicts.
  */
+@VintfStability
 parcelable ParamFieldValues {
     /**
      * Reference to a field or a C2Param structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Params.aidl b/media/c2/aidl/android/hardware/media/c2/Params.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Params.aidl
rename to media/c2/aidl/android/hardware/media/c2/Params.aidl
index 3c1a321..53b512c 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Params.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Params.aidl
@@ -30,6 +30,7 @@
  * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
  * - (size - 8) bytes: data of the C2Param object.
  */
+@VintfStability
 parcelable Params {
     byte[] params;
 }
diff --git a/staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl
rename to media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
index a270146..c2b9574 100644
--- a/staging/c2/aidl/android/hardware/media/c2/SettingResult.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
@@ -22,10 +22,12 @@
  * Information describing the reason the parameter settings may fail, or may be
  * overridden.
  */
+@VintfStability
 parcelable SettingResult {
     /**
      * Failure code
      */
+    @VintfStability
     @Backing(type="int")
     enum Failure {
         /**
diff --git a/staging/c2/aidl/android/hardware/media/c2/Status.aidl b/media/c2/aidl/android/hardware/media/c2/Status.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Status.aidl
rename to media/c2/aidl/android/hardware/media/c2/Status.aidl
index 660db57..58a2404 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Status.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Status.aidl
@@ -19,6 +19,7 @@
 /**
  * Common return values for Codec2 operations.
  */
+@VintfStability
 parcelable Status {
     /**
      * Operation completed successfully.
diff --git a/staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
rename to media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
index 5d6d2eb..00359041 100644
--- a/staging/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
@@ -22,6 +22,7 @@
  * Description of a C2Param structure. It consists of an index and a list of
  * `FieldDescriptor`s.
  */
+@VintfStability
 parcelable StructDescriptor {
     /**
      * Index of the structure.
diff --git a/staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl
rename to media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
index 6707a25..9abcb7d 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ValueRange.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
@@ -38,6 +38,7 @@
  * The division in the formula may truncate the result if the data type of
  * these values is an integral type.
  */
+@VintfStability
 parcelable ValueRange {
     /**
      * Lower end of the range (inclusive).
diff --git a/staging/c2/aidl/android/hardware/media/c2/Work.aidl b/media/c2/aidl/android/hardware/media/c2/Work.aidl
similarity index 99%
rename from staging/c2/aidl/android/hardware/media/c2/Work.aidl
rename to media/c2/aidl/android/hardware/media/c2/Work.aidl
index 0732479..4b8d696 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Work.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Work.aidl
@@ -34,6 +34,7 @@
  *
  * `Work` is a part of @ref WorkBundle.
  */
+@VintfStability
 parcelable Work {
     /**
      * Additional work chain info not part of this work.
diff --git a/staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
rename to media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
index 79b4cdb..2125fda 100644
--- a/staging/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
@@ -35,6 +35,7 @@
  * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
  * data transferred over an IPC.
  */
+@VintfStability
 parcelable WorkBundle {
     /**
      * A list of Work items.
diff --git a/staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
rename to media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
index eb8b244..5708a90 100644
--- a/staging/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
@@ -31,6 +31,7 @@
  * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
  * Codec 2.0 standard.
  */
+@VintfStability
 parcelable WorkOrdinal {
     /**
      * Timestamp in microseconds.
diff --git a/staging/c2/aidl/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
similarity index 98%
rename from staging/c2/aidl/android/hardware/media/c2/Worklet.aidl
rename to media/c2/aidl/android/hardware/media/c2/Worklet.aidl
index 04c59c1..6b3ceac 100644
--- a/staging/c2/aidl/android/hardware/media/c2/Worklet.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
@@ -28,6 +28,7 @@
  * a @ref Work object for each expected output before calling
  * IComponent::queue().
  */
+@VintfStability
 parcelable Worklet {
     /**
      * Component id. (Input)
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 7bc65ff..8b7af11 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -23,4 +23,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: false,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.neuralnetworks",
+    ],
 }
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index 772e5e6..b93c80c 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -21,4 +21,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: false,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.neuralnetworks",
+    ],
 }
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 2b83d39..63e0f61 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -28,4 +28,8 @@
         "android.hidl.safe_union@1.0",
     ],
     gen_java: false,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.neuralnetworks",
+    ],
 }
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index aa8fc39..c343802 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -29,4 +29,8 @@
         "android.hidl.safe_union@1.0",
     ],
     gen_java: false,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.neuralnetworks",
+    ],
 }
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index 09a45d1..08ec5fe 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -34,6 +34,9 @@
             sdk_version: "module_current",
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 082572d..7643926 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -55,6 +55,44 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
+
+cc_defaults {
+    name: "android.hardware.power-ndk_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_export_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_static",
+    static_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_shared",
+    libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_static",
+    static_libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
index c792d4e..8ee15ef 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
@@ -34,10 +34,10 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Boost {
-  INTERACTION = 0,
-  DISPLAY_UPDATE_IMMINENT = 1,
-  ML_ACC = 2,
-  AUDIO_LAUNCH = 3,
-  CAMERA_LAUNCH = 4,
-  CAMERA_SHOT = 5,
+  INTERACTION,
+  DISPLAY_UPDATE_IMMINENT,
+  ML_ACC,
+  AUDIO_LAUNCH,
+  CAMERA_LAUNCH,
+  CAMERA_SHOT,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index e6809da..6bc663e 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -41,4 +41,5 @@
   oneway void close();
   oneway void sendHint(android.hardware.power.SessionHint hint);
   void setThreads(in int[] threadIds);
+  oneway void setMode(android.hardware.power.SessionMode type, boolean enabled);
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
index f38426b..efbb300 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -34,21 +34,21 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Mode {
-  DOUBLE_TAP_TO_WAKE = 0,
-  LOW_POWER = 1,
-  SUSTAINED_PERFORMANCE = 2,
-  FIXED_PERFORMANCE = 3,
-  VR = 4,
-  LAUNCH = 5,
-  EXPENSIVE_RENDERING = 6,
-  INTERACTIVE = 7,
-  DEVICE_IDLE = 8,
-  DISPLAY_INACTIVE = 9,
-  AUDIO_STREAMING_LOW_LATENCY = 10,
-  CAMERA_STREAMING_SECURE = 11,
-  CAMERA_STREAMING_LOW = 12,
-  CAMERA_STREAMING_MID = 13,
-  CAMERA_STREAMING_HIGH = 14,
-  GAME = 15,
-  GAME_LOADING = 16,
+  DOUBLE_TAP_TO_WAKE,
+  LOW_POWER,
+  SUSTAINED_PERFORMANCE,
+  FIXED_PERFORMANCE,
+  VR,
+  LAUNCH,
+  EXPENSIVE_RENDERING,
+  INTERACTIVE,
+  DEVICE_IDLE,
+  DISPLAY_INACTIVE,
+  AUDIO_STREAMING_LOW_LATENCY,
+  CAMERA_STREAMING_SECURE,
+  CAMERA_STREAMING_LOW,
+  CAMERA_STREAMING_MID,
+  CAMERA_STREAMING_HIGH,
+  GAME,
+  GAME_LOADING,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..d0ae0ba
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum SessionMode {
+  POWER_EFFICIENCY,
+}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 7db0ea1..62263c8 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -17,6 +17,7 @@
 package android.hardware.power;
 
 import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
 import android.hardware.power.WorkDuration;
 
 @VintfStability
@@ -81,4 +82,13 @@
      *    must be thrown.
      */
     void setThreads(in int[] threadIds);
+
+    /**
+     * Called to enable or disable special modes for the hint session, which may
+     * adjust the power or performance of the session.
+     *
+     * @param type The mode being set
+     * @param enabled True to enable the mode, false to disable it
+     */
+    oneway void setMode(SessionMode type, boolean enabled);
 }
diff --git a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl b/power/aidl/android/hardware/power/SessionMode.aidl
similarity index 61%
copy from staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
copy to power/aidl/android/hardware/power/SessionMode.aidl
index 94f737d..f1ee64e 100644
--- a/staging/c2/aidl/android/hardware/media/c2/ParamField.aidl
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,20 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.media.c2;
+package android.hardware.power;
 
-import android.hardware.media.c2.FieldId;
-
-/**
- * Reference to a field in a C2Param structure.
- */
-parcelable ParamField {
+@VintfStability
+@Backing(type="int")
+enum SessionMode {
     /**
-     * Index of the C2Param structure.
+     * This mode indicates that the work of this hint session is not
+     * critical to perceived performance, despite its CPU intensity,
+     * and can be safely scheduled to prefer power efficiency.
      */
-    int index;
-    /**
-     * Identifier of the field inside the C2Param structure.
-     */
-    FieldId fieldId;
+    POWER_EFFICIENCY,
 }
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index da91ee6..c0bfbe8 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -23,6 +23,7 @@
 
 cc_binary {
     name: "android.hardware.power-service.example",
+    defaults: ["android.hardware.power-ndk_shared"],
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.rc"],
     vintf_fragments: [":android.hardware.power.xml"],
@@ -30,7 +31,6 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power-V4-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
index f395800..452e435 100644
--- a/power/aidl/default/PowerHintSession.cpp
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -59,4 +59,8 @@
     return ScopedAStatus::ok();
 }
 
+ScopedAStatus PowerHintSession::setMode(SessionMode /* mode */, bool /* enabled */) {
+    return ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
index 1d74716..b488bf1 100644
--- a/power/aidl/default/PowerHintSession.h
+++ b/power/aidl/default/PowerHintSession.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/power/BnPowerHintSession.h>
 #include <aidl/android/hardware/power/SessionHint.h>
+#include <aidl/android/hardware/power/SessionMode.h>
 #include <aidl/android/hardware/power/WorkDuration.h>
 
 namespace aidl::android::hardware::power::impl::example {
@@ -33,6 +34,7 @@
     ndk::ScopedAStatus close() override;
     ndk::ScopedAStatus sendHint(SessionHint hint) override;
     ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
+    ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
 };
 
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index f5dd6b9..418fb83 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>4</version>
+        <version>5</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 56c98bd..eb98b8b 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -26,14 +26,12 @@
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
+        "android.hardware.power-ndk_static",
     ],
     srcs: ["VtsHalPowerTargetTest.cpp"],
     shared_libs: [
         "libbinder_ndk",
     ],
-    static_libs: [
-        "android.hardware.power-V4-ndk",
-    ],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index c2216f8..96995a0 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -29,12 +29,12 @@
 namespace aidl::android::hardware::power {
 namespace {
 
-using ::android::base::GetUintProperty;
 using android::hardware::power::Boost;
 using android::hardware::power::IPower;
 using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
 using android::hardware::power::SessionHint;
+using android::hardware::power::SessionMode;
 using android::hardware::power::WorkDuration;
 
 const std::vector<Boost> kBoosts{ndk::enum_range<Boost>().begin(), ndk::enum_range<Boost>().end()};
@@ -44,6 +44,9 @@
 const std::vector<SessionHint> kSessionHints{ndk::enum_range<SessionHint>().begin(),
                                              ndk::enum_range<SessionHint>().end()};
 
+const std::vector<SessionMode> kSessionModes{ndk::enum_range<SessionMode>().begin(),
+                                             ndk::enum_range<SessionMode>().end()};
+
 const std::vector<Boost> kInvalidBoosts = {
         static_cast<Boost>(static_cast<int32_t>(kBoosts.front()) - 1),
         static_cast<Boost>(static_cast<int32_t>(kBoosts.back()) + 1),
@@ -59,6 +62,11 @@
         static_cast<SessionHint>(static_cast<int32_t>(kSessionHints.back()) + 1),
 };
 
+const std::vector<SessionMode> kInvalidSessionModes = {
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.front()) - 1),
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
+};
+
 class DurationWrapper : public WorkDuration {
   public:
     DurationWrapper(int64_t dur, int64_t time) {
@@ -92,36 +100,33 @@
         DurationWrapper(1000000000L, 4L),
 };
 
-// DEVICEs launching with Android 11 MUST meet the requirements for the
-// target-level=5 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix5ApiLevel = 30;
-
-// DEVICEs launching with Android 13 MUST meet the requirements for the
-// target-level=7 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix7ApiLevel = 33;
-
-// DEVICEs launching with Android 14 MUST meet the requirements for the
-// target-level=8 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix8ApiLevel = 34;
-
-inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
-    return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
-           status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
-}
-
 class PowerAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
         AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
         ASSERT_NE(binder, nullptr);
         power = IPower::fromBinder(ndk::SpAIBinder(binder));
-
-        mApiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
-        ASSERT_NE(mApiLevel, 0);
+        auto status = power->getInterfaceVersion(&mServiceVersion);
+        ASSERT_TRUE(status.isOk());
     }
 
     std::shared_ptr<IPower> power;
-    uint64_t mApiLevel;
+    int32_t mServiceVersion;
+};
+
+class HintSessionAidl : public PowerAidl {
+  public:
+    virtual void SetUp() override {
+        PowerAidl::SetUp();
+        if (mServiceVersion < 2) {
+            GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
+        }
+
+        auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession);
+        ASSERT_TRUE(status.isOk());
+        ASSERT_NE(nullptr, mSession);
+    }
+    std::shared_ptr<IPowerHintSession> mSession;
 };
 
 TEST_P(PowerAidl, setMode) {
@@ -175,113 +180,95 @@
 }
 
 TEST_P(PowerAidl, getHintSessionPreferredRate) {
-    int64_t rate = -1;
-    auto status = power->getHintSessionPreferredRate(&rate);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+    if (mServiceVersion < 2) {
+        GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
     }
-    ASSERT_TRUE(status.isOk());
+
+    int64_t rate = -1;
+    ASSERT_TRUE(power->getHintSessionPreferredRate(&rate).isOk());
     // At least 1ms rate limit from HAL
     ASSERT_GE(rate, 1000000);
 }
 
-TEST_P(PowerAidl, createAndCloseHintSession) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
-    ASSERT_TRUE(status.isOk());
-    ASSERT_NE(nullptr, session);
-    ASSERT_TRUE(session->pause().isOk());
-    ASSERT_TRUE(session->resume().isOk());
+TEST_P(HintSessionAidl, createAndCloseHintSession) {
+    ASSERT_TRUE(mSession->pause().isOk());
+    ASSERT_TRUE(mSession->resume().isOk());
     // Test normal destroy operation
-    ASSERT_TRUE(session->close().isOk());
-    session.reset();
+    ASSERT_TRUE(mSession->close().isOk());
+    mSession.reset();
 }
 
-TEST_P(PowerAidl, createHintSessionFailed) {
+TEST_P(HintSessionAidl, createHintSessionFailed) {
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
 
     // Regardless of whether V2 and beyond is supported, the status is always not STATUS_OK.
     ASSERT_FALSE(status.isOk());
-
-    // If device not launching with Android 13 and beyond, check whether it's supported,
-    // if not, skip the test.
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && isUnknownOrUnsupported(status)) {
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 }
 
-TEST_P(PowerAidl, updateAndReportDurations) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
-    ASSERT_TRUE(status.isOk());
-    ASSERT_NE(nullptr, session);
-
-    ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk());
-    ASSERT_TRUE(session->reportActualWorkDuration(kDurations).isOk());
+TEST_P(HintSessionAidl, updateAndReportDurations) {
+    ASSERT_TRUE(mSession->updateTargetWorkDuration(16666667LL).isOk());
+    ASSERT_TRUE(mSession->reportActualWorkDuration(kDurations).isOk());
 }
 
-TEST_P(PowerAidl, sendSessionHint) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (!status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        return;
+TEST_P(HintSessionAidl, sendSessionHint) {
+    if (mServiceVersion < 4) {
+        GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
     }
+
     for (const auto& sessionHint : kSessionHints) {
-        ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+        ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
     }
     for (const auto& sessionHint : kInvalidSessionHints) {
-        ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+        ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
     }
 }
 
-TEST_P(PowerAidl, setThreads) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+TEST_P(HintSessionAidl, setThreads) {
+    if (mServiceVersion < 4) {
+        GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
     }
-    ASSERT_TRUE(status.isOk());
 
-    status = session->setThreads(kEmptyTids);
-    if (mApiLevel < kCompatibilityMatrix8ApiLevel && isUnknownOrUnsupported(status)) {
-        GTEST_SKIP() << "DEVICE not launching with Android 14 and beyond.";
-    }
+    auto status = mSession->setThreads(kEmptyTids);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 
-    status = session->setThreads(kSelfTids);
-    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(mSession->setThreads(kSelfTids).isOk());
+}
+
+TEST_P(HintSessionAidl, setSessionMode) {
+    if (mServiceVersion < 5) {
+        GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+    }
+
+    for (const auto& sessionMode : kSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
+    for (const auto& sessionMode : kInvalidSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
 }
 
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
 // or later
 TEST_P(PowerAidl, hasFixedPerformance) {
-    if (mApiLevel < kCompatibilityMatrix5ApiLevel) {
-        GTEST_SKIP() << "FIXED_PERFORMANCE mode is only required for all devices launching Android "
-                        "11 or later.";
-    }
     bool supported;
     ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
     ASSERT_TRUE(supported);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HintSessionAidl);
+
 INSTANTIATE_TEST_SUITE_P(Power, PowerAidl,
                          testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
                          ::android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Power, HintSessionAidl,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
+                         ::android::PrintInstanceNameToString);
 
 }  // namespace
 }  // namespace aidl::android::hardware::power
diff --git a/radio/1.0/vts/functional/OWNERS b/radio/1.0/vts/functional/OWNERS
deleted file mode 100644
index 1b6d937..0000000
--- a/radio/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-shuoq@google.com
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
deleted file mode 100644
index 4d199ca..0000000
--- a/radio/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.2/vts/OWNERS b/radio/1.2/vts/OWNERS
deleted file mode 100644
index 4d199ca..0000000
--- a/radio/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.3/vts/OWNERS b/radio/1.3/vts/OWNERS
deleted file mode 100644
index 4d199ca..0000000
--- a/radio/1.3/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
deleted file mode 100644
index 4d199ca..0000000
--- a/radio/1.4/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.5/vts/OWNERS b/radio/1.5/vts/OWNERS
deleted file mode 100644
index 4d199ca..0000000
--- a/radio/1.5/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.6/vts/OWNERS b/radio/1.6/vts/OWNERS
deleted file mode 100644
index a07c917..0000000
--- a/radio/1.6/vts/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include ../../1.0/vts/OWNERS
diff --git a/radio/1.0/vts/OWNERS b/radio/OWNERS
similarity index 63%
rename from radio/1.0/vts/OWNERS
rename to radio/OWNERS
index 117692a..67ac2e2 100644
--- a/radio/1.0/vts/OWNERS
+++ b/radio/OWNERS
@@ -1,5 +1,4 @@
 # Bug component: 20868
-jminjie@google.com
-sarahchin@google.com
-shuoq@google.com
+
 jackyu@google.com
+sarahchin@google.com
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 09f845b..72aaa0f 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -12,7 +12,6 @@
     vendor_available: true,
     host_supported: true,
     srcs: ["android/hardware/radio/*.aidl"],
-    frozen: true,
     stability: "vintf",
     backend: {
         cpp: {
@@ -41,9 +40,8 @@
     vendor_available: true,
     host_supported: true,
     srcs: ["android/hardware/radio/config/*.aidl"],
-    frozen: true,
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -72,7 +70,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/data/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -92,8 +90,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -102,7 +98,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/messaging/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -122,8 +118,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -132,7 +126,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/modem/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -152,8 +146,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -162,7 +154,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/network/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -182,8 +174,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -212,7 +202,6 @@
         },
     ],
     frozen: true,
-
 }
 
 aidl_interface {
@@ -222,8 +211,8 @@
     srcs: ["android/hardware/radio/sim/*.aidl"],
     stability: "vintf",
     imports: [
-        "android.hardware.radio-V2",
-        "android.hardware.radio.config-V2",
+        "android.hardware.radio-V3",
+        "android.hardware.radio.config-V3",
     ],
     backend: {
         cpp: {
@@ -250,8 +239,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -260,7 +247,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/voice/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: true,
@@ -280,8 +267,6 @@
         },
 
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -290,8 +275,8 @@
     srcs: ["android/hardware/radio/ims/media/*.aidl"],
     stability: "vintf",
     imports: [
-        "android.hardware.radio-V2",
-        "android.hardware.radio.data-V2",
+        "android.hardware.radio-V3",
+        "android.hardware.radio.data-V3",
     ],
     backend: {
         cpp: {
@@ -310,8 +295,6 @@
             ],
         },
     ],
-    frozen: true,
-
 }
 
 aidl_interface {
@@ -319,7 +302,7 @@
     vendor_available: true,
     srcs: ["android/hardware/radio/ims/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V2"],
+    imports: ["android.hardware.radio-V3"],
     backend: {
         cpp: {
             enabled: false,
@@ -334,6 +317,20 @@
             imports: ["android.hardware.radio-V2"],
         },
     ],
-    frozen: true,
+}
 
+aidl_interface {
+    name: "android.hardware.radio.satellite",
+    vendor_available: true,
+    srcs: ["android/hardware/radio/satellite/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio-V3"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
 }
diff --git a/radio/aidl/OWNERS b/radio/aidl/OWNERS
deleted file mode 100644
index 7b01aad..0000000
--- a/radio/aidl/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 20868
-include ../1.0/vts/OWNERS
-
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
index a48a89b..0f5e7e4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
@@ -40,6 +40,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @VintfStability
 interface IRadioConfig {
   oneway void getHalDeviceCapabilities(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
index 994e337..9189f90 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @VintfStability
 interface IRadioConfigIndication {
   oneway void simSlotsStatusChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.config.SimSlotStatus[] slotStatus);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
index 038b0ae..348aa34 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @VintfStability
 interface IRadioConfigResponse {
   oneway void getHalDeviceCapabilitiesResponse(in android.hardware.radio.RadioResponseInfo info, in boolean modemReducedFeatureSet1);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
index 74017e4..41c4201 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum MultipleEnabledProfilesMode {
   NONE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
index db3a4c6..3648866 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PhoneCapability {
   byte maxActiveData;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl
index b5d31ad..ede3189 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SimPortInfo {
   String iccId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
index c264dfd..e84e7d4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SimSlotStatus {
   int cardState;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl
index 31271ee..5278e79 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.config;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SlotPortMapping {
   int physicalSlotId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl
index a33ad6e..eed8170 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ApnAuthType {
   NO_PAP_NO_CHAP,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 45d22c8..d2d3137 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -32,22 +32,23 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ApnTypes {
   NONE = 0,
-  DEFAULT = (1 << 0),
-  MMS = (1 << 1),
-  SUPL = (1 << 2),
-  DUN = (1 << 3),
-  HIPRI = (1 << 4),
-  FOTA = (1 << 5),
-  IMS = (1 << 6),
-  CBS = (1 << 7),
-  IA = (1 << 8),
-  EMERGENCY = (1 << 9),
-  MCX = (1 << 10),
-  XCAP = (1 << 11),
-  VSIM = (1 << 12),
-  BIP = (1 << 13),
-  ENTERPRISE = (1 << 14),
+  DEFAULT = (1 << 0) /* 1 */,
+  MMS = (1 << 1) /* 2 */,
+  SUPL = (1 << 2) /* 4 */,
+  DUN = (1 << 3) /* 8 */,
+  HIPRI = (1 << 4) /* 16 */,
+  FOTA = (1 << 5) /* 32 */,
+  IMS = (1 << 6) /* 64 */,
+  CBS = (1 << 7) /* 128 */,
+  IA = (1 << 8) /* 256 */,
+  EMERGENCY = (1 << 9) /* 512 */,
+  MCX = (1 << 10) /* 1024 */,
+  XCAP = (1 << 11) /* 2048 */,
+  VSIM = (1 << 12) /* 4096 */,
+  BIP = (1 << 13) /* 8192 */,
+  ENTERPRISE = (1 << 14) /* 16384 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
index 8a3fd4f..009b428 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum DataCallFailCause {
   NONE = 0,
@@ -101,12 +102,12 @@
   OEM_DCFAILCAUSE_13 = 0x100D,
   OEM_DCFAILCAUSE_14 = 0x100E,
   OEM_DCFAILCAUSE_15 = 0x100F,
-  VOICE_REGISTRATION_FAIL = (-1),
-  DATA_REGISTRATION_FAIL = (-2),
-  SIGNAL_LOST = (-3),
-  PREF_RADIO_TECH_CHANGED = (-4),
-  RADIO_POWER_OFF = (-5),
-  TETHERED_CALL_ACTIVE = (-6),
+  VOICE_REGISTRATION_FAIL = (-1) /* -1 */,
+  DATA_REGISTRATION_FAIL = (-2) /* -2 */,
+  SIGNAL_LOST = (-3) /* -3 */,
+  PREF_RADIO_TECH_CHANGED = (-4) /* -4 */,
+  RADIO_POWER_OFF = (-5) /* -5 */,
+  TETHERED_CALL_ACTIVE = (-6) /* -6 */,
   ERROR_UNSPECIFIED = 0xffff,
   LLC_SNDCP = 0x19,
   ACTIVATION_REJECTED_BCM_VIOLATION = 0x30,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index 0136fa4..bd44275 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable DataProfileInfo {
   int profileId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl
index 0ddaff1..98ae53a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum DataRequestReason {
   NORMAL = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
index e80a764..e1fedb8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="byte") @JavaDerive(toString=true) @VintfStability
 enum DataThrottlingAction {
   NO_DATA_THROTTLING,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl
index 5b9aaa0..3a3f41d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EpsQos {
   int qci;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
index 7b572f1..3888c62 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @VintfStability
 interface IRadioData {
   oneway void allocatePduSessionId(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
index 0ffa1f7..6057d6a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @VintfStability
 interface IRadioDataIndication {
   oneway void dataCallListChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SetupDataCallResult[] dcList);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl
index 4edc17d..dc44454 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @VintfStability
 interface IRadioDataResponse {
   oneway void acknowledgeRequest(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl
index 592a54a..789ee86 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable KeepaliveRequest {
   int type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl
index 82b0fc8..404b44a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable KeepaliveStatus {
   int sessionHandle;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
index 77d637b..bef4c73 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LinkAddress {
   String address;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
index be859b7..22bbe42 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NrQos {
   int fiveQi;
@@ -42,8 +43,8 @@
    * @deprecated use averagingWindowMillis;
    */
   char averagingWindowMs;
-  int averagingWindowMillis = AVERAGING_WINDOW_UNKNOWN;
+  int averagingWindowMillis = AVERAGING_WINDOW_UNKNOWN /* -1 */;
   const byte FLOW_ID_RANGE_MIN = 1;
   const byte FLOW_ID_RANGE_MAX = 63;
-  const int AVERAGING_WINDOW_UNKNOWN = (-1);
+  const int AVERAGING_WINDOW_UNKNOWN = (-1) /* -1 */;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl
index 8595d52..e4bbf79 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable OsAppId {
   byte[] osAppId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl
index 033b12f..ea7529c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PcoDataInfo {
   int cid;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl
index d1c4a62..3a7f82d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl
@@ -32,9 +32,10 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum PdpProtocolType {
-  UNKNOWN = (-1),
+  UNKNOWN = (-1) /* -1 */,
   IP = 0,
   IPV6 = 1,
   IPV4V6 = 2,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
index 470a9c1..45e2dc9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PortRange {
   int start;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl
index ca06e41..4dac56c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union Qos {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl
index 6d4b7a9..b59dee0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable QosBandwidth {
   int maxBitrateKbps;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl
index de45cc5..a3208d9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable QosFilter {
   String[] localAddresses;
@@ -47,7 +48,7 @@
   const byte DIRECTION_DOWNLINK = 0;
   const byte DIRECTION_UPLINK = 1;
   const byte DIRECTION_BIDIRECTIONAL = 2;
-  const byte PROTOCOL_UNSPECIFIED = (-1);
+  const byte PROTOCOL_UNSPECIFIED = (-1) /* -1 */;
   const byte PROTOCOL_TCP = 6;
   const byte PROTOCOL_UDP = 17;
   const byte PROTOCOL_ESP = 50;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl
index 4b75340..50b52a4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union QosFilterIpsecSpi {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
index 3fb34ea..4913dcf 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union QosFilterIpv6FlowLabel {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl
index fa85b5a..4f0d260 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union QosFilterTypeOfService {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl
index bbfdd2d..89010a9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable QosSession {
   int qosSessionId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
index d83df81..8864c24 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RouteSelectionDescriptor {
   byte precedence;
@@ -39,7 +40,7 @@
   byte sscMode;
   android.hardware.radio.data.SliceInfo[] sliceInfo;
   String[] dnn;
-  const byte SSC_MODE_UNKNOWN = (-1);
+  const byte SSC_MODE_UNKNOWN = (-1) /* -1 */;
   const byte SSC_MODE_1 = 1;
   const byte SSC_MODE_2 = 2;
   const byte SSC_MODE_3 = 3;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
index 83f9db6..6ae626e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SetupDataCallResult {
   android.hardware.radio.data.DataCallFailCause cause;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl
index efe4816..60df402 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SliceInfo {
   byte sliceServiceType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl
index b00febe..4d28737 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SlicingConfig {
   android.hardware.radio.data.UrspRule[] urspRules;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl
index d7b0654..dc474a2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable TrafficDescriptor {
   @nullable String dnn;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl
index 7002fd1..6850f6a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.data;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable UrspRule {
   int precedence;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
index 37e3b25..36a538c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum AmrMode {
   AMR_MODE_0 = (1 << 0) /* 1 */,
   AMR_MODE_1 = (1 << 1) /* 2 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
index 36edb7f..dcf0dd1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable AmrParams {
   android.hardware.radio.ims.media.AmrMode amrMode;
   boolean octetAligned;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrMode.aidl
index c108c07..eca7b93 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable AnbrMode {
   android.hardware.radio.ims.media.CodecMode anbrUplinkMode;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl
index fff6e1c..594a39f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable CallQuality {
   int downlinkCallQualityLevel;
   int uplinkCallQualityLevel;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecMode.aidl
index 0e9140f..644321c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union CodecMode {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
index 3da2dbd..6eefb34 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable CodecParams {
   android.hardware.radio.ims.media.CodecType codecType;
   byte rxPayloadTypeNumber;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl
index 08e3f0f..7e5722f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 union CodecSpecificParams {
   android.hardware.radio.ims.media.AmrParams amr;
   android.hardware.radio.ims.media.EvsParams evs;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
index e4193cd..98463b1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CodecType {
   AMR = (1 << 0) /* 1 */,
   AMR_WB = (1 << 1) /* 2 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl
index 5523fd8..f420fa7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable DtmfParams {
   byte rxPayloadTypeNumber;
   byte txPayloadTypeNumber;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl
index db3eb29..d8c77bd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EvsBandwidth {
   NONE = 0,
   NARROW_BAND = (1 << 0) /* 1 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
index fb1f14d..1a59389 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EvsMode {
   EVS_MODE_0 = (1 << 0) /* 1 */,
   EVS_MODE_1 = (1 << 1) /* 2 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
index 735eb08..deb53af 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable EvsParams {
   android.hardware.radio.ims.media.EvsBandwidth bandwidth;
   android.hardware.radio.ims.media.EvsMode evsMode;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl
index 30793e5..190d25b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @VintfStability
 interface IImsMedia {
   oneway void setListener(in android.hardware.radio.ims.media.IImsMediaListener mediaListener);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl
index 40f7107..9b7a392 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @VintfStability
 interface IImsMediaListener {
   oneway void onOpenSessionSuccess(int sessionId, android.hardware.radio.ims.media.IImsMediaSession session);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
index ea9f3a4..45c8002 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @VintfStability
 interface IImsMediaSession {
   oneway void setListener(in android.hardware.radio.ims.media.IImsMediaSessionListener sessionListener);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index cb221df..5ec9c18 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
+/* @hide */
 @VintfStability
 interface IImsMediaSessionListener {
   oneway void onModifySessionResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl
index 6ec5156..1095f01 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable LocalEndPoint {
   ParcelFileDescriptor rtpFd;
   ParcelFileDescriptor rtcpFd;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl
index 0e9eaee..5410f2a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum MediaDirection {
   NO_FLOW = 0,
   RTP_TX = (1 << 0) /* 1 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityStatus.aidl
index 4accf53..da6e751 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityStatus.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable MediaQualityStatus {
   int rtpInactivityTimeMillis;
   int rtcpInactivityTimeMillis;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
index 31cf373..ecc379c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable MediaQualityThreshold {
   int[] rtpInactivityTimerMillis;
   int rtcpInactivityTimerMillis;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl
index 6a76d85..0bc4154 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable RtcpConfig {
   String canonicalName;
   int transmitPort;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
index 289c810..714442c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RtcpXrReportBlockType {
   RTCPXR_NONE = 0,
   RTCPXR_LOSS_RLE_REPORT_BLOCK = (1 << 0) /* 1 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl
index 35357d1..dd7f466 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable RtpAddress {
   String ipAddress;
   int portNumber;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
index 8a826f6..472ec35 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable RtpConfig {
   int direction;
   android.hardware.radio.AccessNetwork accessNetwork;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl
index 41b0aeb..97dacf1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RtpError {
   NONE = 0,
   INVALID_PARAM = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
index 83b8a31..06207ee 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable RtpHeaderExtension {
   int localId;
   byte[] data;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl
index 13a7487..4107432 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims.media;
-@VintfStability
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
 parcelable RtpSessionParams {
   byte pTimeMillis;
   int maxPtimeMillis;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
index 90e75f9..421f752 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ConnectionFailureInfo {
   android.hardware.radio.ims.ConnectionFailureInfo.ConnectionFailureReason failureReason;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl
index ebea903..75099e7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EpsFallbackReason {
   NO_NETWORK_TRIGGER = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl
index 4df8709..6018a4b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @VintfStability
 interface IRadioIms {
   oneway void setSrvccCallInfo(int serial, in android.hardware.radio.ims.SrvccCall[] srvccCalls);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl
index ef6b4cc..c754af3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @VintfStability
 interface IRadioImsIndication {
   oneway void onConnectionSetupFailure(in android.hardware.radio.RadioIndicationType type, int token, in android.hardware.radio.ims.ConnectionFailureInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl
index 053ba46..fbb1bfc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @VintfStability
 interface IRadioImsResponse {
   oneway void setSrvccCallInfoResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
index 6e14830..3895d75 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsCall {
   int index;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
index b04e559..5b5bd40 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ImsDeregistrationReason {
   REASON_SIM_REMOVED = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
index be5e004..66d8165 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsRegistration {
   android.hardware.radio.ims.ImsRegistrationState regState;
@@ -39,8 +40,8 @@
   android.hardware.radio.ims.SuggestedAction suggestedAction;
   int capabilities;
   const int IMS_MMTEL_CAPABILITY_NONE = 0;
-  const int IMS_MMTEL_CAPABILITY_VOICE = (1 << 0);
-  const int IMS_MMTEL_CAPABILITY_VIDEO = (1 << 1);
-  const int IMS_MMTEL_CAPABILITY_SMS = (1 << 2);
-  const int IMS_RCS_CAPABILITIES = (1 << 3);
+  const int IMS_MMTEL_CAPABILITY_VOICE = (1 << 0) /* 1 */;
+  const int IMS_MMTEL_CAPABILITY_VIDEO = (1 << 1) /* 2 */;
+  const int IMS_MMTEL_CAPABILITY_SMS = (1 << 2) /* 4 */;
+  const int IMS_RCS_CAPABILITIES = (1 << 3) /* 8 */;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl
index 6302b47..01ae565 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ImsRegistrationState {
   NOT_REGISTERED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl
index cf2e4f1..efc3551 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ImsStreamDirection {
   UPLINK = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl
index 10c477f..853f4b5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl
@@ -32,7 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
-@Backing(type="int") @VintfStability
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ImsStreamType {
   AUDIO = 1,
   VIDEO = 2,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl
index b1a0b77..4eeda9d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ImsTrafficType {
   EMERGENCY,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
index 5119b0f..21645da 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SrvccCall {
   int index;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
index bbe170e..120e7e8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.ims;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum SuggestedAction {
   NONE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
index 39e2be2..abfb308 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaBroadcastSmsConfigInfo {
   int serviceCategory;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl
index befdbde..ee8371c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSmsAck {
   boolean errorClass;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl
index ab29c77..7382b1f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSmsAddress {
   int digitMode;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl
index 867596c..0e98f4b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSmsMessage {
   int teleserviceId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
index d67fe8c..a0e3991 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSmsSubaddress {
   int subaddressType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
index b0a7f98..d6292e7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSmsWriteArgs {
   int status;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
index 46604ca..1ccba86 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable GsmBroadcastSmsConfigInfo {
   int fromServiceId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl
index 4df7fd2..bdd7d0c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable GsmSmsMessage {
   String smscPdu;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
index dfec59a..bf5fde5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @VintfStability
 interface IRadioMessaging {
   oneway void acknowledgeIncomingGsmSmsWithPdu(in int serial, in boolean success, in String ackPdu);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
index 8f7824f..389fb26 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @VintfStability
 interface IRadioMessagingIndication {
   oneway void cdmaNewSms(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.messaging.CdmaSmsMessage msg);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
index c3af7a6..9b10464 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @VintfStability
 interface IRadioMessagingResponse {
   oneway void acknowledgeIncomingGsmSmsWithPduResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
index 85f62b7..40b9ddb 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsSmsMessage {
   android.hardware.radio.RadioTechnologyFamily tech;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl
index 32f7a5c..3f1d120 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SendSmsResult {
   int messageRef;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
index d061c9e..6aeda3e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum SmsAcknowledgeFailCause {
   MEMORY_CAPACITY_EXCEEDED = 0xD3,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl
index 489cc07..a294b47 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.messaging;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SmsWriteArgs {
   int status;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
index 7e22ee0..c834342 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ActivityStatsInfo {
   int sleepModeTimeMs;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
index 08ed9a5..b44ab71 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ActivityStatsTechSpecificInfo {
   android.hardware.radio.AccessNetwork rat;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
index acc0b22..1159f93 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum DeviceStateType {
   POWER_SAVE_MODE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl
index 3a0ec25..2d814ef 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable HardwareConfig {
   int type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
index 62bb160..d453cb0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable HardwareConfigModem {
   int rilModel;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl
index 5810982..4c2e31b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable HardwareConfigSim {
   String modemUuid;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
index 8546be7..bd8ba47 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @VintfStability
 interface IRadioModem {
   oneway void enableModem(in int serial, in boolean on);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl
index 514ff9a..20066f8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @VintfStability
 interface IRadioModemIndication {
   oneway void hardwareConfigChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.modem.HardwareConfig[] configs);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
index 5955439..b9ef51b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @VintfStability
 interface IRadioModemResponse {
   oneway void acknowledgeRequest(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
index f8776ec..a2df30d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImeiInfo {
   android.hardware.radio.modem.ImeiInfo.ImeiType type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
index b80d7ac..f97b9a2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
@@ -33,6 +33,7 @@
 
 package android.hardware.radio.modem;
 /**
+ * @hide
  * @deprecated NV APIs are deprecated starting from Android U.
  */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
index 6a786bc..c38ceb7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
@@ -33,6 +33,7 @@
 
 package android.hardware.radio.modem;
 /**
+ * @hide
  * @deprecated NV APIs are deprecated starting from Android U.
  */
 @JavaDerive(toString=true) @VintfStability
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
index f2e2858..bc3cfcc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioCapability {
   int session;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl
index 57f2941..3383fa4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioState {
   OFF = 0,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
index 37622b1..b4208b7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ResetNvType {
   RELOAD,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
index 28d8862..667a8a7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union AccessTechnologySpecificInfo {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
index e105b39..67c9349 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable BarringInfo {
   int serviceType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
index a813633..03369b9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable BarringTypeSpecificInfo {
   int factor;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
index 927f9ac..bc9c0ba 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
@@ -32,13 +32,14 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable Cdma2000RegistrationInfo {
   boolean cssSupported;
   int roamingIndicator;
   int systemIsInPrl;
   int defaultRoamingIndicator;
-  const int PRL_INDICATOR_NOT_REGISTERED = (-1);
+  const int PRL_INDICATOR_NOT_REGISTERED = (-1) /* -1 */;
   const int PRL_INDICATOR_NOT_IN_PRL = 0;
   const int PRL_INDICATOR_IN_PRL = 1;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl
index 2a4db70..84532e3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CdmaRoamingType {
   HOME_NETWORK,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl
index e2f97bf..94430a8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSignalStrength {
   int dbm;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl
index 5ce3b3e..3775a40 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CellConnectionStatus {
   NONE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl
index 2ee92de..ba27b39 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union CellIdentity {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl
index d659a28..63571bb 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityCdma {
   int networkId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl
index d3193be..5040f20 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityGsm {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl
index 2ae7b43..be7821d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityLte {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl
index b30af50..6f4f9a0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityNr {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl
index e99d147..864a886 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityTdscdma {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl
index 12001fc..4e76277 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellIdentityWcdma {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
index 467c6b7..6bb31b0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfo {
   boolean registered;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl
index e3bf46b..6d76a26 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoCdma {
   android.hardware.radio.network.CellIdentityCdma cellIdentityCdma;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl
index 84dcd07..2074c2f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoGsm {
   android.hardware.radio.network.CellIdentityGsm cellIdentityGsm;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl
index 221340b..aa3b310 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoLte {
   android.hardware.radio.network.CellIdentityLte cellIdentityLte;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl
index b392c1d..a8f49af 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoNr {
   android.hardware.radio.network.CellIdentityNr cellIdentityNr;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
index 4ab0640..fd3239d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union CellInfoRatSpecificInfo {
   android.hardware.radio.network.CellInfoGsm gsm;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl
index 138b35c..1a03f34 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoTdscdma {
   android.hardware.radio.network.CellIdentityTdscdma cellIdentityTdscdma;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl
index cf7b135..d02824d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfoWcdma {
   android.hardware.radio.network.CellIdentityWcdma cellIdentityWcdma;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
index fe734c8..b9e6f82 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ClosedSubscriberGroupInfo {
   boolean csgIndication;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
index 6b022b6..0de7e20 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
@@ -32,8 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum Domain {
-  CS = (1 << 0),
-  PS = (1 << 1),
+  CS = (1 << 0) /* 1 */,
+  PS = (1 << 1) /* 2 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
index 071e6b5..c5b067e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EmergencyMode {
   EMERGENCY_WWAN = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
index 2797aff..471c7a0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EmergencyNetworkScanTrigger {
   android.hardware.radio.AccessNetwork[] accessNetwork;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
index 7d99a53..3b8083d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EmergencyRegResult {
   android.hardware.radio.AccessNetwork accessNetwork;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyScanType.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyScanType.aidl
index 5e86c76..0681a73 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyScanType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyScanType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EmergencyScanType {
   NO_PREFERENCE = 0,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl
index 57fac3f..82257ec 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EutranBands {
   BAND_1 = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
index 90e342a..bb34fe1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -32,14 +32,15 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EutranRegistrationInfo {
   android.hardware.radio.network.LteVopsInfo lteVopsInfo;
   android.hardware.radio.network.NrIndicators nrIndicators;
   android.hardware.radio.network.EutranRegistrationInfo.AttachResultType lteAttachResultType;
   int extraInfo;
-  const int EXTRA_CSFB_NOT_PREFERRED = (1 << 0);
-  const int EXTRA_SMS_ONLY = (1 << 1);
+  const int EXTRA_CSFB_NOT_PREFERRED = (1 << 0) /* 1 */;
+  const int EXTRA_SMS_ONLY = (1 << 1) /* 2 */;
   enum AttachResultType {
     NONE,
     EPS_ONLY,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl
index 7c56711..e97e17d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EvdoSignalStrength {
   int dbm;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl
index 135935f..ee0d419 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum GeranBands {
   BAND_T380 = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl
index 2b53b39..65847ef 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable GsmSignalStrength {
   int signalStrength;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 382ddd8..cbc1e30 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @VintfStability
 interface IRadioNetwork {
   oneway void getAllowedNetworkTypesBitmap(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
index 0f017ea..05a36ef 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @VintfStability
 interface IRadioNetworkIndication {
   oneway void barringInfoChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index bfe8fa3..c86bebc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @VintfStability
 interface IRadioNetworkResponse {
   oneway void acknowledgeRequest(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl
index 00ba346..7847fbe 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl
@@ -32,15 +32,16 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum IndicationFilter {
   NONE = 0,
-  ALL = (~0),
-  SIGNAL_STRENGTH = (1 << 0),
-  FULL_NETWORK_STATE = (1 << 1),
-  DATA_CALL_DORMANCY_CHANGED = (1 << 2),
-  LINK_CAPACITY_ESTIMATE = (1 << 3),
-  PHYSICAL_CHANNEL_CONFIG = (1 << 4),
-  REGISTRATION_FAILURE = (1 << 5),
-  BARRING_INFO = (1 << 6),
+  ALL = (~0) /* -1 */,
+  SIGNAL_STRENGTH = (1 << 0) /* 1 */,
+  FULL_NETWORK_STATE = (1 << 1) /* 2 */,
+  DATA_CALL_DORMANCY_CHANGED = (1 << 2) /* 4 */,
+  LINK_CAPACITY_ESTIMATE = (1 << 3) /* 8 */,
+  PHYSICAL_CHANNEL_CONFIG = (1 << 4) /* 16 */,
+  REGISTRATION_FAILURE = (1 << 5) /* 32 */,
+  BARRING_INFO = (1 << 6) /* 64 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl
index 27b16c1..6dc6d3e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LceDataInfo {
   int lastHopCapacityKbps;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl
index 5707b8e..3fc4b5c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LinkCapacityEstimate {
   int downlinkCapacityKbps;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl
index b5b8579..eb2ca28 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LteSignalStrength {
   int signalStrength;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl
index 6d8dd4e..f8d3aa1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LteVopsInfo {
   boolean isVopsSupported;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
index 6039740..60eaf77 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NetworkScanRequest {
   int type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
index 4e392d0..695a194 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NetworkScanResult {
   int status;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl
index 5904690..fb939df 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum NgranBands {
   BAND_1 = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl
index 62c2a56..7af15a7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="byte") @JavaDerive(toString=true) @VintfStability
 enum NrDualConnectivityState {
   ENABLE = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl
index 88429f6..efcd6d3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NrIndicators {
   boolean isEndcAvailable;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
index 7d6ab82..11e7356 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NrSignalStrength {
   int ssRsrp;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
index e5a0a70..61146aa 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NrVopsInfo {
   byte vopsSupported;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl
index 034150e..abe2bea 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable OperatorInfo {
   String alphaLong;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl
index 4e3e39e..44cab0e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum PhoneRestrictedState {
   NONE = 0x00,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
index 928c6b7..7d64f7e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PhysicalChannelConfig {
   android.hardware.radio.network.CellConnectionStatus status;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
index efc64a6..2e50e67 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union PhysicalChannelConfigBand {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
index 1566bb5..8229207 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioAccessSpecifier {
   android.hardware.radio.AccessNetwork accessNetwork;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
index a6ac12a..9ba420e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 union RadioAccessSpecifierBands {
   boolean noinit;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
index 74696fb..6058e30 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioBandMode {
   BAND_MODE_UNSPECIFIED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
index 711c9ac..f11b911 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RegState {
   NOT_REG_MT_NOT_SEARCHING_OP = 0,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
index f0a03ae..625d970 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RegStateResult {
   android.hardware.radio.network.RegState regState;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl
index 8acf8ab..56f516d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RegistrationFailCause {
   NONE = 0,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl
index 1c50190..da7db9a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SignalStrength {
   android.hardware.radio.network.GsmSignalStrength gsm;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
index 744eed7..77b4831 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SignalThresholdInfo {
   int signalMeasurement;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl
index b62c71b..5192eae 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SuppSvcNotification {
   boolean isMT;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl
index d74c950..fe209e5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable TdscdmaSignalStrength {
   int signalStrength;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
index 3ca16b5..a6f4d13 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum UsageSetting {
   VOICE_CENTRIC = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl
index 8be3da2..977afe3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum UtranBands {
   BAND_1 = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl
index 9112527..b765ab6 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.network;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable WcdmaSignalStrength {
   int signalStrength;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatellite.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatellite.aidl
new file mode 100644
index 0000000..0c7408a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatellite.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@VintfStability
+interface IRadioSatellite {
+  oneway void addAllowedSatelliteContacts(in int serial, in String[] contacts);
+  oneway void getCapabilities(in int serial);
+  oneway void getMaxCharactersPerTextMessage(in int serial);
+  oneway void getPendingMessages(in int serial);
+  oneway void getPowerState(in int serial);
+  oneway void getSatelliteMode(in int serial);
+  oneway void getTimeForNextSatelliteVisibility(in int serial);
+  oneway void provisionService(in int serial, in String imei, in String msisdn, in String imsi, in android.hardware.radio.satellite.SatelliteFeature[] features);
+  oneway void removeAllowedSatelliteContacts(in int serial, in String[] contacts);
+  oneway void responseAcknowledgement();
+  oneway void sendMessages(in int serial, in String[] messages, in String destination, in double latitude, in double longitude);
+  oneway void setIndicationFilter(in int serial, in int filterBitmask);
+  oneway void setPower(in int serial, in boolean on);
+  oneway void setResponseFunctions(in android.hardware.radio.satellite.IRadioSatelliteResponse satelliteResponse, in android.hardware.radio.satellite.IRadioSatelliteIndication satelliteIndication);
+  oneway void startSendingSatellitePointingInfo(in int serial);
+  oneway void stopSendingSatellitePointingInfo(in int serial);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl
new file mode 100644
index 0000000..36ec5f3
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@VintfStability
+interface IRadioSatelliteIndication {
+  oneway void onMessagesTransferComplete(in android.hardware.radio.RadioIndicationType type, in boolean complete);
+  oneway void onNewMessages(in android.hardware.radio.RadioIndicationType type, in String[] messages);
+  oneway void onPendingMessageCount(in android.hardware.radio.RadioIndicationType type, in int count);
+  oneway void onProvisionStateChanged(in android.hardware.radio.RadioIndicationType type, boolean provisioned, in android.hardware.radio.satellite.SatelliteFeature[] features);
+  oneway void onSatelliteModeChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.satellite.SatelliteMode mode);
+  oneway void onSatellitePointingInfoChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.satellite.PointingInfo pointingInfo);
+  oneway void onSatelliteRadioTechnologyChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.satellite.NTRadioTechnology technology);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl
new file mode 100644
index 0000000..bf9b9e6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@VintfStability
+interface IRadioSatelliteResponse {
+  oneway void acknowledgeRequest(in int serial);
+  oneway void addAllowedSatelliteContactsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getCapabilitiesResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.satellite.SatelliteCapabilities capabilities);
+  oneway void getMaxCharactersPerTextMessageResponse(in android.hardware.radio.RadioResponseInfo info, in int charLimit);
+  oneway void getPendingMessagesResponse(in android.hardware.radio.RadioResponseInfo info, in String[] messages);
+  oneway void getPowerStateResponse(in android.hardware.radio.RadioResponseInfo info, in boolean on);
+  oneway void getSatelliteModeResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.satellite.SatelliteMode mode, in android.hardware.radio.satellite.NTRadioTechnology technology);
+  oneway void getTimeForNextSatelliteVisibilityResponse(in android.hardware.radio.RadioResponseInfo info, in int timeInSeconds);
+  oneway void provisionServiceResponse(in android.hardware.radio.RadioResponseInfo info, in boolean provisioned);
+  oneway void removeAllowedSatelliteContactsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendMessagesResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setIndicationFilterResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setPowerResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void startSendingSatellitePointingInfoResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void stopSendingSatellitePointingInfoResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IndicationFilter.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IndicationFilter.aidl
new file mode 100644
index 0000000..b9df1f5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/IndicationFilter.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum IndicationFilter {
+  NONE = 0,
+  SATELLITE_MODE = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/NTRadioTechnology.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/NTRadioTechnology.aidl
new file mode 100644
index 0000000..f05baaa
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/NTRadioTechnology.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum NTRadioTechnology {
+  NB_IOT_NTN = 0,
+  NR_NTN = 1,
+  EMTC_NTN = 2,
+  PROPRIETARY = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/PointingInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/PointingInfo.aidl
new file mode 100644
index 0000000..1ada88a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/PointingInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
+parcelable PointingInfo {
+  float satelliteAzimuthDegrees;
+  float satelliteElevationDegrees;
+  float antennaAzimuthDegrees;
+  float antennaPitchDegrees;
+  float antennaRollDegrees;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteCapabilities.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteCapabilities.aidl
new file mode 100644
index 0000000..e0af71a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteCapabilities.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@JavaDerive(toString=true) @VintfStability
+parcelable SatelliteCapabilities {
+  android.hardware.radio.satellite.NTRadioTechnology[] supportedRadioTechnologies;
+  boolean isAlwaysOn;
+  boolean needsPointingToSatellite;
+  android.hardware.radio.satellite.SatelliteFeature[] supportedFeatures;
+  boolean needsSeparateSimProfile;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteFeature.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteFeature.aidl
new file mode 100644
index 0000000..e79e572
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteFeature.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SatelliteFeature {
+  SOS_SMS = 0,
+  EMERGENCY_SMS = 1,
+  SMS = 2,
+  LOCATION_SHARING = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteMode.aidl
new file mode 100644
index 0000000..a1ce566
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.satellite/current/android/hardware/radio/satellite/SatelliteMode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.satellite;
+/* @hide */
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SatelliteMode {
+  POWERED_OFF = 0,
+  OUT_OF_SERVICE_NOT_SEARCHING = 1,
+  OUT_OF_SERVICE_SEARCHING = 2,
+  ACQUIRED = 3,
+  MESSAGE_TRANSFERRING = 4,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
index 8a41fb9..898b616 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable AppStatus {
   int appType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
index 6bc3919..066777a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CardPowerState {
   POWER_DOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
index 46cb7be..1a9d621 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CardStatus {
   int cardState;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl
index cc56888..24fff2e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable Carrier {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
index 3700de3..84cdf5d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CarrierRestrictions {
   android.hardware.radio.sim.Carrier[] allowedCarriers;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
index 080aa5e..13b06e7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CdmaSubscriptionSource {
   RUIM_SIM,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
index 901b251..1728e41 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @VintfStability
 interface IRadioSim {
   oneway void areUiccApplicationsEnabled(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl
index d4371b8..a74b65a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @VintfStability
 interface IRadioSimIndication {
   oneway void carrierInfoForImsiEncryption(in android.hardware.radio.RadioIndicationType info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
index d7c2100..c653847 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @VintfStability
 interface IRadioSimResponse {
   oneway void acknowledgeRequest(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl
index 5a312dc..661518d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable IccIo {
   int command;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl
index 6c6bde2..1e418cd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable IccIoResult {
   int sw1;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
index 05e71cd..40722e5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsiEncryptionInfo {
   String mcc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
index 5e96fc6..aaf9f3e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="byte") @JavaDerive(toString=true) @VintfStability
 enum PbReceivedStatus {
   PB_RECEIVED_OK = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl
index dc1d960..7952308 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum PersoSubstate {
   UNKNOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl
index 7531c96..b020687 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PhonebookCapacity {
   int maxAdnRecords;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl
index 2e96a4b..1a6943b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PhonebookRecordInfo {
   int recordId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl
index 663ea73..924929b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum PinState {
   UNKNOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl
index 02121e6..57ca2a5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SelectUiccSub {
   int slot;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl
index 1329141..5c81e3d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SessionInfo {
   int sessionId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
index c391e5a..45f6e48 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SimApdu {
   int sessionId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index d59fcab..5a5e8ac 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum SimLockMultiSimPolicy {
   NO_MULTISIM_POLICY,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
index 69bf476..81ba510 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.sim;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SimRefreshResult {
   int type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl
index 1ab2902..8725c7f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum AudioQuality {
   UNSPECIFIED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
index 10d2ee7..b45a45b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable Call {
   int state;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl
index 8e7aaab..51c8758 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CallForwardInfo {
   int status;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl
index 310f9a0..0b36be4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaCallWaiting {
   String number;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
index b6b562c..300b03f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaDisplayInfoRecord {
   String alphaBuf;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
index 24ae775..2f7f5f0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaInformationRecord {
   int name;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
index e34b393..4e4a7ee 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaLineControlInfoRecord {
   byte lineCtrlPolarityIncluded;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
index aeb0347..c3b0d5a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaNumberInfoRecord {
   String number;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
index fad3841..ae35fba 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CdmaOtaProvisionStatus {
   SPL_UNLOCKED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
index b61b91b..93c7c6b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaRedirectingNumberInfoRecord {
   android.hardware.radio.voice.CdmaNumberInfoRecord redirectingNumber;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
index 6c7b264..69447b4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaSignalInfoRecord {
   boolean isPresent;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
index 438231c..69d79aa 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaT53AudioControlInfoRecord {
   byte upLink;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
index 1b254f5..83b6fb9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CdmaT53ClirInfoRecord {
   byte cause;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl
index 7e799c7..fc811f2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CfData {
   android.hardware.radio.voice.CallForwardInfo[] cfInfo;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
index a34149a..c38c801 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum ClipStatus {
   CLIP_PROVISIONED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl
index 2b2e759..26041f0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable Dial {
   String address;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
index 4e1dfc0..3099a20 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EmergencyCallRouting {
   UNKNOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
index ac3867e..2129f39 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EmergencyNumber {
   String number;
@@ -40,8 +41,8 @@
   int categories;
   String[] urns;
   int sources;
-  const int SOURCE_NETWORK_SIGNALING = (1 << 0);
-  const int SOURCE_SIM = (1 << 1);
-  const int SOURCE_MODEM_CONFIG = (1 << 2);
-  const int SOURCE_DEFAULT = (1 << 3);
+  const int SOURCE_NETWORK_SIGNALING = (1 << 0) /* 1 */;
+  const int SOURCE_SIM = (1 << 1) /* 2 */;
+  const int SOURCE_MODEM_CONFIG = (1 << 2) /* 4 */;
+  const int SOURCE_DEFAULT = (1 << 3) /* 8 */;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl
index 0a70d2d..819baf8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl
@@ -32,14 +32,15 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum EmergencyServiceCategory {
   UNSPECIFIED = 0,
-  POLICE = (1 << 0),
-  AMBULANCE = (1 << 1),
-  FIRE_BRIGADE = (1 << 2),
-  MARINE_GUARD = (1 << 3),
-  MOUNTAIN_RESCUE = (1 << 4),
-  MIEC = (1 << 5),
-  AIEC = (1 << 6),
+  POLICE = (1 << 0) /* 1 */,
+  AMBULANCE = (1 << 1) /* 2 */,
+  FIRE_BRIGADE = (1 << 2) /* 4 */,
+  MARINE_GUARD = (1 << 3) /* 8 */,
+  MOUNTAIN_RESCUE = (1 << 4) /* 16 */,
+  MIEC = (1 << 5) /* 32 */,
+  AIEC = (1 << 6) /* 64 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
index 603b1d6..d0a9451 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @VintfStability
 interface IRadioVoice {
   oneway void acceptCall(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
index 189ed43..4614ee1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @VintfStability
 interface IRadioVoiceIndication {
   oneway void callRing(in android.hardware.radio.RadioIndicationType type, in boolean isGsm, in android.hardware.radio.voice.CdmaSignalInfoRecord record);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
index 7acc044..46927c2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @VintfStability
 interface IRadioVoiceResponse {
   oneway void acceptCallResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
index 7d54623..0cac135 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum LastCallFailCause {
   UNOBTAINABLE_NUMBER = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
index 221acf7..151adf2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LastCallFailCauseInfo {
   android.hardware.radio.voice.LastCallFailCause causeCode;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl
index 4b5c216..981ba02 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum SrvccState {
   HANDOVER_STARTED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
index f18b404..24365dc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SsInfoData {
   int[] ssInfo;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
index 75f3de5..999f47c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable StkCcUnsolSsResult {
   int serviceType;
@@ -72,13 +73,13 @@
   const int TELESERVICE_TYPE_SMS_SERVICES = 4;
   const int TELESERVICE_TYPE_ALL_TELESERVICES_EXCEPT_SMS = 5;
   const int SUPP_SERVICE_CLASS_NONE = 0;
-  const int SUPP_SERVICE_CLASS_VOICE = (1 << 0);
-  const int SUPP_SERVICE_CLASS_DATA = (1 << 1);
-  const int SUPP_SERVICE_CLASS_FAX = (1 << 2);
-  const int SUPP_SERVICE_CLASS_SMS = (1 << 3);
-  const int SUPP_SERVICE_CLASS_DATA_SYNC = (1 << 4);
-  const int SUPP_SERVICE_CLASS_DATA_ASYNC = (1 << 5);
-  const int SUPP_SERVICE_CLASS_PACKET = (1 << 6);
-  const int SUPP_SERVICE_CLASS_PAD = (1 << 7);
-  const int SUPP_SERVICE_CLASS_MAX = (1 << 7);
+  const int SUPP_SERVICE_CLASS_VOICE = (1 << 0) /* 1 */;
+  const int SUPP_SERVICE_CLASS_DATA = (1 << 1) /* 2 */;
+  const int SUPP_SERVICE_CLASS_FAX = (1 << 2) /* 4 */;
+  const int SUPP_SERVICE_CLASS_SMS = (1 << 3) /* 8 */;
+  const int SUPP_SERVICE_CLASS_DATA_SYNC = (1 << 4) /* 16 */;
+  const int SUPP_SERVICE_CLASS_DATA_ASYNC = (1 << 5) /* 32 */;
+  const int SUPP_SERVICE_CLASS_PACKET = (1 << 6) /* 64 */;
+  const int SUPP_SERVICE_CLASS_PAD = (1 << 7) /* 128 */;
+  const int SUPP_SERVICE_CLASS_MAX = (1 << 7) /* 128 */;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl
index e432e65..41ff6b8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum TtyMode {
   OFF,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
index 424e73f..9e80f03 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum UssdModeType {
   NOTIFY,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
index 9313760..3c84c8d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.voice;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable UusInfo {
   int uusType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
index 9641651..73a267b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum AccessNetwork {
   UNKNOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
index b7b074b..1298ab0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioAccessFamily {
   UNKNOWN = (1 << android.hardware.radio.RadioTechnology.UNKNOWN) /* 1 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
index 9785825..970cd1e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioConst {
   const int MAX_RILDS = 3;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
index 98606e5..781c9f6 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioError {
   NONE = 0,
@@ -123,4 +124,15 @@
   BLOCKED_DUE_TO_CALL = 69,
   RF_HARDWARE_ISSUE = 70,
   NO_RF_CALIBRATION_INFO = 71,
+  ENCODING_NOT_SUPPORTED = 72,
+  FEATURE_NOT_SUPPORTED = 73,
+  INVALID_CONTACT = 74,
+  MODEM_INCOMPATIBLE = 75,
+  NETWORK_TIMEOUT = 76,
+  NO_SATELLITE_SIGNAL = 77,
+  NOT_SUFFICIENT_ACCOUNT_BALANCE = 78,
+  RADIO_TECHNOLOGY_NOT_SUPPORTED = 79,
+  SUBSCRIBER_NOT_AUTHORIZED = 80,
+  SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL = 81,
+  UNIDENTIFIED_SUBSCRIBER = 82,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl
index 58b35a5..316f92f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioIndicationType {
   UNSOLICITED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
index b2a7a06..f03a73b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioResponseInfo {
   android.hardware.radio.RadioResponseType type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
index 37ed7bb..2e0c315 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioResponseInfoModem {
   android.hardware.radio.RadioResponseType type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl
index 1ee62bd..8bdb45b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioResponseType {
   SOLICITED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
index b6af5aa..7c6a657 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioTechnology {
   UNKNOWN,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
index 2af7e53..85e9850 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio;
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum RadioTechnologyFamily {
   THREE_GPP,
diff --git a/radio/aidl/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
index 2885642..4099f83 100644
--- a/radio/aidl/android/hardware/radio/AccessNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
index edf33ba..9ab4583 100644
--- a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.RadioTechnology;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/RadioConst.aidl b/radio/aidl/android/hardware/radio/RadioConst.aidl
index 6591ef1..7b923b9 100644
--- a/radio/aidl/android/hardware/radio/RadioConst.aidl
+++ b/radio/aidl/android/hardware/radio/RadioConst.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioConst {
diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl
index 2031399..e95d725 100644
--- a/radio/aidl/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/android/hardware/radio/RadioError.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
@@ -301,4 +302,51 @@
      * Unlike RF_HARDWARE_ISSUE, this is a SW problem and no HW repair is needed.
      */
     NO_RF_CALIBRATION_INFO = 71,
+    /**
+     * The encoding scheme is not supported by either the network or the MS.
+     */
+    ENCODING_NOT_SUPPORTED = 72,
+    /**
+     * The requesting feature is not supported by the service provider/operator.
+     */
+    FEATURE_NOT_SUPPORTED = 73,
+    /**
+     * The contact to be added is either not existing or not valid.
+     */
+    INVALID_CONTACT = 74,
+    /**
+     * The modem of the MS is not compatible with the service provider/operator. This generic error
+     * should be used only when there are some mimatches in the capabilities between the MS and
+     * the operator and the error cannot be mapped properly to other specific network errors.
+     */
+    MODEM_INCOMPATIBLE = 75,
+    /**
+     * Modem timeout to receive ACK or response from network after sending a request to the network.
+     */
+    NETWORK_TIMEOUT = 76,
+    /**
+     * Modem fails to communicate with the satellite network since there is no satellite signal.
+     */
+    NO_SATELLITE_SIGNAL = 77,
+    /**
+     * The request cannot be performed since the subscriber's account balance is not sufficient.
+     */
+    NOT_SUFFICIENT_ACCOUNT_BALANCE = 78,
+    /**
+     * The radio technology is not supported by the service provider/operator.
+     */
+    RADIO_TECHNOLOGY_NOT_SUPPORTED = 79,
+    /**
+     * The subscription is not authorized to register with the service provider/operator.
+     */
+    SUBSCRIBER_NOT_AUTHORIZED = 80,
+    /**
+     * While processing a request from the Framework, the satellite modem detects terrestrial
+     * signal, aborts the request, and switches to the terrestrial network.
+     */
+    SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL = 81,
+    /**
+     * The subscriber is not registered in the service provider.
+     */
+    UNIDENTIFIED_SUBSCRIBER = 82
 }
diff --git a/radio/aidl/android/hardware/radio/RadioIndicationType.aidl b/radio/aidl/android/hardware/radio/RadioIndicationType.aidl
index 2dcc492..594b147 100644
--- a/radio/aidl/android/hardware/radio/RadioIndicationType.aidl
+++ b/radio/aidl/android/hardware/radio/RadioIndicationType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
index f70a3fe..25195aa 100644
--- a/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.RadioError;
 import android.hardware.radio.RadioResponseType;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioResponseInfo {
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
index 13abfb9..286f397 100644
--- a/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.RadioError;
 import android.hardware.radio.RadioResponseType;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioResponseInfoModem {
diff --git a/radio/aidl/android/hardware/radio/RadioResponseType.aidl b/radio/aidl/android/hardware/radio/RadioResponseType.aidl
index cd4a305..000f478 100644
--- a/radio/aidl/android/hardware/radio/RadioResponseType.aidl
+++ b/radio/aidl/android/hardware/radio/RadioResponseType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
index 4b51152..7ae428b 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnology.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
index a2b989d..4b5498c 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
index 85c2cee..1075ef7 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
@@ -28,6 +28,7 @@
 import android.hardware.radio.config.IRadioConfigResponse;
 import android.hardware.radio.config.SlotPortMapping;
 
+/** @hide */
 @VintfStability
 oneway interface IRadioConfig {
     /**
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
index abf55f1..ed2366b 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -20,6 +20,7 @@
 
 /**
  * Interface declaring unsolicited radio config indications.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioConfigIndication {
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
index 0d36bbd..cb3533e 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -21,6 +21,7 @@
 
 /**
  * Interface declaring response functions to solicited radio config requests.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioConfigResponse {
diff --git a/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl b/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
index b18ea0e..1d9b66e 100644
--- a/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
+++ b/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
@@ -20,6 +20,7 @@
  * Multiple Enabled Profiles(MEP) mode is the jointly supported MEP mode. As per section 3.4.1.1 of
  * GSMA spec SGP.22 v3.0,there are 3 supported MEP modes: MEP-A1, MEP-A2 and MEP-B.
  * If there is no jointly supported MEP mode, supported MEP mode is set to NONE.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
index 8e4f338..35d6b5d 100644
--- a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
+++ b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
@@ -20,6 +20,7 @@
  * Phone capability which describes the data connection capability of modem.
  * It's used to evaluate possible phone config change, for example from single
  * SIM device to multi-SIM device.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
index db24719..f579639 100644
--- a/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.config;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SimPortInfo {
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index 6a36d5e..34f98c5 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.config.MultipleEnabledProfilesMode;
 import android.hardware.radio.config.SimPortInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SimSlotStatus {
diff --git a/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl b/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl
index c78afcb..30cca50 100644
--- a/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl
+++ b/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.config;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SlotPortMapping {
diff --git a/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl b/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl
index a4116db..1d1d851 100644
--- a/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index ed1256d..366570a 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
index 071ce55..e015e8e 100644
--- a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index ea4e751..613387f 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.data.PdpProtocolType;
 import android.hardware.radio.data.TrafficDescriptor;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable DataProfileInfo {
diff --git a/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl b/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl
index 44b47f8..b16081d 100644
--- a/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
index e4ee444..a762e34 100644
--- a/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @Backing(type="byte")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/EpsQos.aidl b/radio/aidl/android/hardware/radio/data/EpsQos.aidl
index 8965d6e..42eee32 100644
--- a/radio/aidl/android/hardware/radio/data/EpsQos.aidl
+++ b/radio/aidl/android/hardware/radio/data/EpsQos.aidl
@@ -20,6 +20,7 @@
 
 /**
  * LTE/EPS Quality of Service parameters as per 3gpp spec 24.301 sec 9.9.4.3.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
index 0171d39..519d425 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioData.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
@@ -34,6 +34,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioDataResponse and IRadioDataIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioData {
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
index 938c695..c3fdcaa 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -25,6 +25,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for data APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioDataIndication {
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
index 06c83c1..b714844 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
@@ -23,6 +23,7 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for data APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioDataResponse {
diff --git a/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
index c720de0..1838f2e 100644
--- a/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
+++ b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable KeepaliveRequest {
diff --git a/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl b/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl
index 0b829c4..162fc37 100644
--- a/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl
+++ b/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable KeepaliveStatus {
diff --git a/radio/aidl/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
index 12a7637..957973d 100644
--- a/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
+++ b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Describes a data link address for mobile data connection.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/NrQos.aidl b/radio/aidl/android/hardware/radio/data/NrQos.aidl
index 4078fdc..f636e6b 100644
--- a/radio/aidl/android/hardware/radio/data/NrQos.aidl
+++ b/radio/aidl/android/hardware/radio/data/NrQos.aidl
@@ -20,6 +20,7 @@
 
 /**
  * 5G Quality of Service parameters as per 3gpp spec 24.501 sec 9.11.4.12
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/OsAppId.aidl b/radio/aidl/android/hardware/radio/data/OsAppId.aidl
index 88e7832..ae38cf3 100644
--- a/radio/aidl/android/hardware/radio/data/OsAppId.aidl
+++ b/radio/aidl/android/hardware/radio/data/OsAppId.aidl
@@ -18,6 +18,7 @@
 
 /**
  * This struct represents the OsId + OsAppId as defined in TS 24.526 Section 5.2
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl b/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl
index 38a821f..a487bb3 100644
--- a/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable PcoDataInfo {
diff --git a/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl b/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl
index 792a503..27e541d 100644
--- a/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl
+++ b/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Specifies the type of packet data protocol which is defined in TS 27.007 section 10.1.1.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/data/PortRange.aidl b/radio/aidl/android/hardware/radio/data/PortRange.aidl
index 5c83ca4..7326966 100644
--- a/radio/aidl/android/hardware/radio/data/PortRange.aidl
+++ b/radio/aidl/android/hardware/radio/data/PortRange.aidl
@@ -20,6 +20,7 @@
  * Defines range of ports. start and end are the first and last port numbers (inclusive) in the
  * range. Both start and end are in PORT_RANGE_MIN to PORT_RANGE_MAX range. A single port shall
  * be represented by the same start and end value.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/Qos.aidl b/radio/aidl/android/hardware/radio/data/Qos.aidl
index d9ab9e7..e98d030 100644
--- a/radio/aidl/android/hardware/radio/data/Qos.aidl
+++ b/radio/aidl/android/hardware/radio/data/Qos.aidl
@@ -21,6 +21,7 @@
 
 /**
  * EPS or NR QOS parameters
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl b/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl
index e841548..f2eca41 100644
--- a/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable QosBandwidth {
diff --git a/radio/aidl/android/hardware/radio/data/QosFilter.aidl b/radio/aidl/android/hardware/radio/data/QosFilter.aidl
index f5dc7ec..4a2b61d 100644
--- a/radio/aidl/android/hardware/radio/data/QosFilter.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosFilter.aidl
@@ -23,6 +23,7 @@
 
 /**
  * See 3gpp 24.008 10.5.6.12 and 3gpp 24.501 9.11.4.13
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl b/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl
index 5059c28..83c4fe1 100644
--- a/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union QosFilterIpsecSpi {
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl b/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
index 6f14934..4591174 100644
--- a/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union QosFilterIpv6FlowLabel {
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl b/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl
index f5770a4..8d27399 100644
--- a/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.data;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union QosFilterTypeOfService {
diff --git a/radio/aidl/android/hardware/radio/data/QosSession.aidl b/radio/aidl/android/hardware/radio/data/QosSession.aidl
index 770b124..1a8eb2c 100644
--- a/radio/aidl/android/hardware/radio/data/QosSession.aidl
+++ b/radio/aidl/android/hardware/radio/data/QosSession.aidl
@@ -21,6 +21,7 @@
 
 /**
  * QOS session associated with a dedicated bearer
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
index 14b0ffc..4e9e954 100644
--- a/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
+++ b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -21,6 +21,7 @@
 
 /**
  * This struct represents a single route selection descriptor as defined in 3GPP TS 24.526.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
index fee54ac..b8f01c0 100644
--- a/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
+++ b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -24,6 +24,7 @@
 import android.hardware.radio.data.SliceInfo;
 import android.hardware.radio.data.TrafficDescriptor;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SetupDataCallResult {
diff --git a/radio/aidl/android/hardware/radio/data/SliceInfo.aidl b/radio/aidl/android/hardware/radio/data/SliceInfo.aidl
index 7ad7fc3..809b8e0 100644
--- a/radio/aidl/android/hardware/radio/data/SliceInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/SliceInfo.aidl
@@ -18,6 +18,7 @@
 
 /**
  * This struct represents a S-NSSAI as defined in 3GPP TS 24.501.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl b/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl
index e94b58c..47ac41e 100644
--- a/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl
+++ b/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl
@@ -21,6 +21,7 @@
 
 /**
  * This struct represents the current slicing configuration.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl b/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl
index 2c117a5..098c77a 100644
--- a/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl
+++ b/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl
@@ -22,6 +22,7 @@
  * This struct represents a traffic descriptor. A valid struct must have at least one of the
  * optional values present. This is based on the definition of traffic descriptor in
  * TS 24.526 Section 5.2.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/data/UrspRule.aidl b/radio/aidl/android/hardware/radio/data/UrspRule.aidl
index 0499edd..f2028b4 100644
--- a/radio/aidl/android/hardware/radio/data/UrspRule.aidl
+++ b/radio/aidl/android/hardware/radio/data/UrspRule.aidl
@@ -21,6 +21,7 @@
 
 /**
  * This struct represents a single URSP rule as defined in 3GPP TS 24.526.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
index 70faa1e..c96f59f 100644
--- a/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -16,10 +16,10 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ConnectionFailureInfo {
-
     @VintfStability
     @Backing(type="int")
     enum ConnectionFailureReason {
diff --git a/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl b/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl
index 670638b..5300fbe 100644
--- a/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl
+++ b/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl b/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl
index bd661a7..05d6035 100644
--- a/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl
+++ b/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl
@@ -34,6 +34,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioImsResponse and IRadioImsIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioIms {
@@ -90,9 +91,8 @@
      *
      * Response function is IRadioImsResponse.startImsTrafficResponse()
      */
-    void startImsTraffic(int serial, int token,
-            ImsTrafficType imsTrafficType, AccessNetwork accessNetworkType,
-            ImsCall.Direction trafficDirection);
+    void startImsTraffic(int serial, int token, ImsTrafficType imsTrafficType,
+            AccessNetwork accessNetworkType, ImsCall.Direction trafficDirection);
 
     /**
      * Indicates IMS traffic has been stopped.
@@ -123,8 +123,8 @@
      * @param radioImsResponse Object containing response functions
      * @param radioImsIndication Object containing radio indications
      */
-    void setResponseFunctions(in IRadioImsResponse radioImsResponse,
-            in IRadioImsIndication radioImsIndication);
+    void setResponseFunctions(
+            in IRadioImsResponse radioImsResponse, in IRadioImsIndication radioImsIndication);
 
     /**
      * Access Network Bitrate Recommendation Query (ANBRQ), see 3GPP TS 26.114.
@@ -138,7 +138,8 @@
      *
      * Response function is IRadioImsResponse.sendAnbrQueryResponse()
      */
-    void sendAnbrQuery(int serial, ImsStreamType mediaType, ImsStreamDirection direction, int bitsPerSecond);
+    void sendAnbrQuery(
+            int serial, ImsStreamType mediaType, ImsStreamDirection direction, int bitsPerSecond);
 
     /**
      * Provides a list of IMS call information to radio.
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl b/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl
index d123d07..58e30ce 100644
--- a/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl
+++ b/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl
@@ -24,6 +24,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for ims APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioImsIndication {
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl b/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl
index ff516cc..b8a5a94 100644
--- a/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl
+++ b/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl
@@ -21,10 +21,10 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for ims APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioImsResponse {
-
     /**
      * @param info Response info struct containing response type, serial no. and error
      *
@@ -73,8 +73,8 @@
      *   RadioError:INVALID_ARGUMENTS
      *   RadioError:NO_RESOURCES
      */
-    void startImsTrafficResponse(in RadioResponseInfo info,
-            in @nullable ConnectionFailureInfo failureInfo);
+    void startImsTrafficResponse(
+            in RadioResponseInfo info, in @nullable ConnectionFailureInfo failureInfo);
 
     /**
      * @param info Response info struct containing response type, serial no. and error
diff --git a/radio/aidl/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
index b71682f..427c1f5 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
@@ -18,10 +18,10 @@
 
 import android.hardware.radio.AccessNetwork;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ImsCall {
-
     @Backing(type="int")
     enum CallType {
         NORMAL,
diff --git a/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
index eac8db4..acfe51c 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
index 662f9e9..5158386 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.ims.ImsRegistrationState;
 import android.hardware.radio.ims.SuggestedAction;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ImsRegistration {
diff --git a/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl b/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl
index fd5c0fa..187cb38 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
@@ -25,4 +26,4 @@
 
     /** IMS is successfully registered */
     REGISTERED,
-}
\ No newline at end of file
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl b/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl
index c0cea32..42ce1bd 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl b/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl
index c12a0c1..b88dc60 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl
@@ -16,8 +16,10 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum ImsStreamType {
     /** Media Stream Type - Audio **/
     AUDIO = 1,
diff --git a/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl b/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl
index 5a824c0..5af43f9 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
@@ -40,4 +41,4 @@
 
     /** Ut/XCAP (XML Configuration Access Protocol) */
     UT_XCAP
-}
\ No newline at end of file
+}
diff --git a/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
index 38e6cdb..16858f9 100644
--- a/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
+++ b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
@@ -16,10 +16,10 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SrvccCall {
-
     @VintfStability
     @Backing(type="int")
     enum CallType {
diff --git a/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
index 2d12ed6..443042d 100644
--- a/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
+++ b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.ims;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
index 66d8ef0..dc2a162 100644
--- a/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
@@ -16,9 +16,13 @@
 
 package android.hardware.radio.ims.media;
 
-/** AMR codec mode to represent the bit rate. See 3ggp Specs 26.976 & 26.071 */
+/**
+ * AMR codec mode to represent the bit rate. See 3ggp Specs 26.976 & 26.071
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum AmrMode {
     /** 4.75 kbps for AMR / 6.6 kbps for AMR-WB */
     AMR_MODE_0 = 1 << 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
index 4ed3a24..9d7ab05 100644
--- a/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
@@ -18,7 +18,9 @@
 
 import android.hardware.radio.ims.media.AmrMode;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable AmrParams {
     /** mode-set: AMR codec mode to represent the bit rate */
     AmrMode amrMode;
diff --git a/radio/aidl/android/hardware/radio/ims/media/AnbrMode.aidl b/radio/aidl/android/hardware/radio/ims/media/AnbrMode.aidl
index f758cd4..af6f92f 100644
--- a/radio/aidl/android/hardware/radio/ims/media/AnbrMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/AnbrMode.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.ims.media.CodecMode;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable AnbrMode {
diff --git a/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl b/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl
index a8f7b16..dcf9623 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable CallQuality {
     /**
      * downlink CallQualityLevel for a given ongoing call
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecMode.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecMode.aidl
index aa1b3a4..6858ef4 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecMode.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.ims.media.AmrMode;
 import android.hardware.radio.ims.media.EvsMode;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union CodecMode {
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
index 0aa5505..74de6ec 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
@@ -19,7 +19,9 @@
 import android.hardware.radio.ims.media.CodecSpecificParams;
 import android.hardware.radio.ims.media.CodecType;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable CodecParams {
     /** Negotiated codec type */
     CodecType codecType;
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl
index 4410c81..86dcea0 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl
@@ -19,7 +19,9 @@
 import android.hardware.radio.ims.media.AmrParams;
 import android.hardware.radio.ims.media.EvsParams;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 union CodecSpecificParams {
     AmrParams amr;
     EvsParams evs;
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
index 31218e3..99fbac4 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
@@ -16,8 +16,10 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum CodecType {
     /** Adaptive Multi-Rate */
     AMR = 1 << 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl b/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl
index a7dcb0d..d2926f0 100644
--- a/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable DtmfParams {
     /**
      * Dynamic payload type number to be used for DTMF RTP packets received.
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl
index 8278514..279c489 100644
--- a/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl
@@ -15,9 +15,14 @@
  */
 
 package android.hardware.radio.ims.media;
-/** EVS Speech codec bandwidths, See 3gpp spec 26.441 Table 1 */
+
+/**
+ * EVS Speech codec bandwidths, See 3gpp spec 26.441 Table 1
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum EvsBandwidth {
     NONE = 0,
     NARROW_BAND = 1 << 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
index 95bd6c7..12d981b 100644
--- a/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
@@ -16,9 +16,13 @@
 
 package android.hardware.radio.ims.media;
 
-/** EVS codec mode to represent the bit rate. See 3ggp Spec 26.952 Table 5.1 */
+/**
+ * EVS codec mode to represent the bit rate. See 3ggp Spec 26.952 Table 5.1
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum EvsMode {
     /** 6.6 kbps for EVS AMR-WB IO */
     EVS_MODE_0 = 1 << 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
index d138c83..52c3bf9 100644
--- a/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
@@ -19,7 +19,9 @@
 import android.hardware.radio.ims.media.EvsBandwidth;
 import android.hardware.radio.ims.media.EvsMode;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable EvsParams {
     /** EVS codec bandwidth */
     EvsBandwidth bandwidth;
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl
index ecf1370..0af86c7 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl
@@ -23,10 +23,10 @@
 
 /**
  * This interface is used by IMS media framework to talk to RTP stack located in another processor.
+ * @hide
  */
 @VintfStability
 oneway interface IImsMedia {
-
     /**
      * Set the listener functions for receiving notifications from the RTP stack.
      *
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl
index 228acb7..371edd2 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl
@@ -21,6 +21,7 @@
 
 /**
  * Interface declaring listener functions for unsolicited IMS media notifications.
+ * @hide
  */
 @VintfStability
 oneway interface IImsMediaListener {
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
index ec2fa2b..deb741b 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -24,6 +24,7 @@
 
 /**
  * Session specific interface used by IMS media framework to talk to the vendor RTP stack.
+ * @hide
  */
 @VintfStability
 oneway interface IImsMediaSession {
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
index 8341da2..442c018 100644
--- a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -24,6 +24,7 @@
 
 /**
  * Interface declaring listener functions for unsolicited IMS media notifications per session.
+ * @hide
  */
 @VintfStability
 oneway interface IImsMediaSessionListener {
diff --git a/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl b/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl
index 2bd48c6..29f25bb 100644
--- a/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl
@@ -18,7 +18,9 @@
 
 import android.os.ParcelFileDescriptor;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable LocalEndPoint {
     /** Socket file descriptor for RTP traffic */
     ParcelFileDescriptor rtpFd;
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl
index e5c34c7..4ae36df 100644
--- a/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl
@@ -26,9 +26,11 @@
  *     Receive-Only : RTP_RX | RTCP_TX | RTCP_RX - eg. Remote Hold.
  *     Send-Receive : RTP_TX | RTP_RX | RTCP_TX | RTCP_RX - eg. Active call.
  *     Send-Only    : RTP_TX | RTCP_TX | RTCP_RX - eg. Simplex call, voice mail, etc
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum MediaDirection {
     /**
      * No RTP/RTCP flow in either direction. The implementation
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaQualityStatus.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaQualityStatus.aidl
index b99e501..b617f91 100644
--- a/radio/aidl/android/hardware/radio/ims/media/MediaQualityStatus.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaQualityStatus.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable MediaQualityStatus {
     /**
      * Rtp inactivity observed as per threshold set by
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
index bf98928..25473d0 100644
--- a/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable MediaQualityThreshold {
     /** Array including threshold values in milliseconds for monitoring RTP inactivity */
     int[] rtpInactivityTimerMillis;
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl b/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl
index 98bbfc6..9cb3c0e 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable RtcpConfig {
     /** Canonical name that will be sent to all session participants */
     String canonicalName;
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
index 7f6839a..88180d7 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
@@ -16,25 +16,28 @@
 
 package android.hardware.radio.ims.media;
 
-/** RTP Control Protocol Extended Reports (RTCP XR) Blocks, See RFC 3611 section 4 */
-
+/**
+ * RTP Control Protocol Extended Reports (RTCP XR) Blocks, See RFC 3611 section 4
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum RtcpXrReportBlockType {
     /** Disable RTCP XR */
     RTCPXR_NONE = 0,
     /** Loss RLE Report Block */
-    RTCPXR_LOSS_RLE_REPORT_BLOCK                  = 1 << 0,
+    RTCPXR_LOSS_RLE_REPORT_BLOCK = 1 << 0,
     /** Duplicate RLE Report Block */
-    RTCPXR_DUPLICATE_RLE_REPORT_BLOCK             = 1 << 1,
+    RTCPXR_DUPLICATE_RLE_REPORT_BLOCK = 1 << 1,
     /** Packet Receipt Times Report Block */
-    RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK      = 1 << 2,
+    RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK = 1 << 2,
     /** Receiver Reference Time Report Block */
-    RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK   = 1 << 3,
+    RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK = 1 << 3,
     /** DLRR Report Block */
-    RTCPXR_DLRR_REPORT_BLOCK                      = 1 << 4,
+    RTCPXR_DLRR_REPORT_BLOCK = 1 << 4,
     /** Statistics Summary Report Block */
-    RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK        = 1 << 5,
+    RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK = 1 << 5,
     /** VoIP Metrics Report Block */
-    RTCPXR_VOIP_METRICS_REPORT_BLOCK              = 1 << 6,
+    RTCPXR_VOIP_METRICS_REPORT_BLOCK = 1 << 6,
 }
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl
index 2db73a3..c17e4b2 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl
@@ -16,7 +16,9 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable RtpAddress {
     /** Point to point IP address */
     String ipAddress;
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
index f93b112..3c5c4dd 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
@@ -22,7 +22,9 @@
 import android.hardware.radio.ims.media.RtpAddress;
 import android.hardware.radio.ims.media.RtpSessionParams;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable RtpConfig {
     /** Media flow direction. The bitfield of MediaDirection(s) */
     int direction;
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl
index 11a3468..84f972f 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl
@@ -16,8 +16,10 @@
 
 package android.hardware.radio.ims.media;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
+@JavaDerive(toString=true)
 enum RtpError {
     /** Success */
     NONE = 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
index 76b13dc..19e855a 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
@@ -16,8 +16,12 @@
 
 package android.hardware.radio.ims.media;
 
-/** RTP Header Extensions, see RFC 8285 */
+/**
+ * RTP Header Extensions, see RFC 8285
+ * @hide
+ */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable RtpHeaderExtension {
     /** Local identifier */
     int localId;
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl
index f93c52c..ae5c7e6 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl
@@ -19,7 +19,9 @@
 import android.hardware.radio.ims.media.CodecParams;
 import android.hardware.radio.ims.media.DtmfParams;
 
+/** @hide */
 @VintfStability
+@JavaDerive(toString=true)
 parcelable RtpSessionParams {
     /**
      * ptime: Recommended length of time in milliseconds represented by the media
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
index 4173f15..35a6a8d 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaBroadcastSmsConfigInfo {
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
index 85ef692..2544ab5 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSmsAck {
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
index 8e521df..a7ad233 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSmsAddress {
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
index d4fb26f..51388b6 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.messaging.CdmaSmsAddress;
 import android.hardware.radio.messaging.CdmaSmsSubaddress;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSmsMessage {
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
index 18e5837..19d84ff 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSmsSubaddress {
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
index 4191985..897ec80 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.messaging.CdmaSmsMessage;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSmsWriteArgs {
diff --git a/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl b/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
index 5138c3c..b4ab518 100644
--- a/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Which types of Cell Broadcast Message (CBM) are to be received by the ME
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl
index b256c9a..9a1a7b9 100644
--- a/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable GsmSmsMessage {
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
index 8bd84a3..44818ff 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -35,6 +35,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioMessagingResponse and IRadioMessagingIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioMessaging {
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
index 8834cd9..a177c2c 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -21,6 +21,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for messaging APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioMessagingIndication {
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
index 8cbc869..84c34ca 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -23,6 +23,7 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for messaging APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioMessagingResponse {
diff --git a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
index d4be044..5f9f82b 100644
--- a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.messaging.CdmaSmsMessage;
 import android.hardware.radio.messaging.GsmSmsMessage;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ImsSmsMessage {
diff --git a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
index 80e059c..ea93727 100644
--- a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SendSmsResult {
diff --git a/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl b/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
index eb15bf1..6f529eb 100644
--- a/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl b/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl
index 6eef941..64ce606 100644
--- a/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.messaging;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SmsWriteArgs {
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
index b2a56d4..db77c51 100644
--- a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.modem.ActivityStatsTechSpecificInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ActivityStatsInfo {
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
index fcc2df2..7ca4021 100644
--- a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.AccessNetwork;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ActivityStatsTechSpecificInfo {
diff --git a/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
index ad0d59c..c1f4cd6 100644
--- a/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
+++ b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.modem;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl
index 8eb1f2d..323e5c9 100644
--- a/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.modem.HardwareConfigModem;
 import android.hardware.radio.modem.HardwareConfigSim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable HardwareConfig {
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
index f5e2c27..1ba3562 100644
--- a/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.RadioTechnology;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable HardwareConfigModem {
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl
index c82bc6e..a5747c1 100644
--- a/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.modem;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable HardwareConfigSim {
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
index 2011c53..0d51584 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
@@ -31,6 +31,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioModemResponse and IRadioModemIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioModem {
@@ -244,5 +245,5 @@
      *
      * Response function is IRadioModemResponse.getImeiResponse()
      */
-     void getImei(in int serial);
+    void getImei(in int serial);
 }
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl
index c61de99..4b98277 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl
@@ -23,6 +23,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for modem APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioModemIndication {
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
index fd4bffb..b6946f3 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -19,11 +19,12 @@
 import android.hardware.radio.RadioResponseInfo;
 import android.hardware.radio.modem.ActivityStatsInfo;
 import android.hardware.radio.modem.HardwareConfig;
-import android.hardware.radio.modem.RadioCapability;
 import android.hardware.radio.modem.ImeiInfo;
+import android.hardware.radio.modem.RadioCapability;
 
 /**
  * Interface declaring response functions to solicited radio requests for modem APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioModemResponse {
diff --git a/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl b/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
index 2d25bb7..6d33505 100644
--- a/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
@@ -18,26 +18,25 @@
 
 /**
  * ImeiInfo to encapsulate the IMEI information from modem
+ * @hide
  */
-
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ImeiInfo {
-
     @VintfStability
     @Backing(type="int")
     /**
      * ImeiType enum is used identify the IMEI as primary or secondary as mentioned in GSMA TS.37
      */
     enum ImeiType {
-       /**
-        * This is the primary IMEI of the device as mentioned in the GSMA TS.37. In a multi-SIM
-        * device the modem must set one IMEI with this type as mentioned in GSMA TS37_2.2_REQ_8.
-        * A single SIM with one IMEI must by default set that IMEI with this type.
-        */
-       PRIMARY = 1,
-       /** This is not the primary IMEI of the device */
-       SECONDARY = 2,
+        /**
+         * This is the primary IMEI of the device as mentioned in the GSMA TS.37. In a multi-SIM
+         * device the modem must set one IMEI with this type as mentioned in GSMA TS37_2.2_REQ_8.
+         * A single SIM with one IMEI must by default set that IMEI with this type.
+         */
+        PRIMARY = 1,
+        /** This is not the primary IMEI of the device */
+        SECONDARY = 2,
     }
 
     /** Primary or secondary IMEI as mentioned in GSMA spec TS.37 */
@@ -48,8 +47,8 @@
      * SIM activations or swaps.
      */
     String imei;
-   /**
+    /**
      * IMEI software version, see 3gpp spec 23.003 section 6.
      */
     String svn;
-}
\ No newline at end of file
+}
diff --git a/radio/aidl/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
index 310b1ad..b405137 100644
--- a/radio/aidl/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
@@ -16,7 +16,10 @@
 
 package android.hardware.radio.modem;
 
-/** @deprecated NV APIs are deprecated starting from Android U. */
+/**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
index 6472f23..c57253b 100644
--- a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
@@ -18,7 +18,10 @@
 
 import android.hardware.radio.modem.NvItem;
 
-/** @deprecated NV APIs are deprecated starting from Android U. */
+/**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ * @hide
+ */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable NvWriteItem {
diff --git a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
index 16cba09..9781595 100644
--- a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.modem;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioCapability {
diff --git a/radio/aidl/android/hardware/radio/modem/RadioState.aidl b/radio/aidl/android/hardware/radio/modem/RadioState.aidl
index dedad25..c36dbe0 100644
--- a/radio/aidl/android/hardware/radio/modem/RadioState.aidl
+++ b/radio/aidl/android/hardware/radio/modem/RadioState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.modem;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
index 6476fe8..e290a52 100644
--- a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
@@ -16,7 +16,10 @@
 
 package android.hardware.radio.modem;
 
-/** Note: This will be deprecated along with nvResetConfig in Android U. */
+/**
+ * Note: This will be deprecated along with nvResetConfig in Android U.
+ * @hide
+ */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
index 8b95ced..9c48a8d 100644
--- a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.network.EutranRegistrationInfo;
 import android.hardware.radio.network.NrVopsInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union AccessTechnologySpecificInfo {
diff --git a/radio/aidl/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
index 2759406..f12e35c 100644
--- a/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.network.BarringTypeSpecificInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable BarringInfo {
diff --git a/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
index 3db3bf3..b4a3bdf 100644
--- a/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable BarringTypeSpecificInfo {
diff --git a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
index b06fabb..91b8500 100644
--- a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable Cdma2000RegistrationInfo {
diff --git a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
index 2fea519..0bb7c04 100644
--- a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
+++ b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
index 1286f67..ae7aa93 100644
--- a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl b/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl
index da36ff0..3bc19e1 100644
--- a/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
index e34866b..6142087 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
@@ -25,6 +25,7 @@
 
 /**
  * A union representing the CellIdentity of a single cell.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
index 5bb26c1..b93988f 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.network.OperatorInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellIdentityCdma {
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
index 60f42b6..bc02adc 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.network.OperatorInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellIdentityGsm {
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
index bfa58ac..27c2580 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.network.EutranBands;
 import android.hardware.radio.network.OperatorInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellIdentityLte {
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
index d51a18e..4192845 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
@@ -22,6 +22,7 @@
 /**
  * The CellIdentity structure should be reported once for each element of the PLMN-IdentityInfoList
  * broadcast in SIB1 CellAccessRelatedInfo as per 3GPP TS 38.331 Section 6.3.2.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
index f6e790f..33ffc6f 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.ClosedSubscriberGroupInfo;
 import android.hardware.radio.network.OperatorInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellIdentityTdscdma {
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
index a76509b..b6e328a 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.ClosedSubscriberGroupInfo;
 import android.hardware.radio.network.OperatorInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellIdentityWcdma {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
index 161ac71..4895326 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellConnectionStatus;
 import android.hardware.radio.network.CellInfoRatSpecificInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfo {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
index 5408104..0a2bc54 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.network.CellIdentityCdma;
 import android.hardware.radio.network.EvdoSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoCdma {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl b/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl
index cadcd91..db84510 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellIdentityGsm;
 import android.hardware.radio.network.GsmSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoGsm {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl b/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl
index 443a668..3d9b2f3 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellIdentityLte;
 import android.hardware.radio.network.LteSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoLte {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl b/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl
index 6b3d4f4..61591a9 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellIdentityNr;
 import android.hardware.radio.network.NrSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoNr {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
index 76e92a4..10a4a5f 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
@@ -23,6 +23,7 @@
 import android.hardware.radio.network.CellInfoTdscdma;
 import android.hardware.radio.network.CellInfoWcdma;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union CellInfoRatSpecificInfo {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl
index fb9c984..ff0fff3 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellIdentityTdscdma;
 import android.hardware.radio.network.TdscdmaSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoTdscdma {
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl
index 2d6a2e5..c38e306 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.CellIdentityWcdma;
 import android.hardware.radio.network.WcdmaSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CellInfoWcdma {
diff --git a/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl b/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
index a2d82d7..d61c1dc 100644
--- a/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ClosedSubscriberGroupInfo {
diff --git a/radio/aidl/android/hardware/radio/network/Domain.aidl b/radio/aidl/android/hardware/radio/network/Domain.aidl
index be5f320..bb169bd 100644
--- a/radio/aidl/android/hardware/radio/network/Domain.aidl
+++ b/radio/aidl/android/hardware/radio/network/Domain.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl b/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
index 25031a9..7a2ed9c 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl b/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
index 0a22e4c..ea4bfeb 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
@@ -18,9 +18,10 @@
 import android.hardware.radio.AccessNetwork;
 import android.hardware.radio.network.EmergencyScanType;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
-parcelable EmergencyNetworkScanTrigger{
+parcelable EmergencyNetworkScanTrigger {
     /**
      * Access network to be prioritized during emergency scan. The 1st entry has the highest
      * priority.
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
index 2215149..af2750e 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.Domain;
 import android.hardware.radio.network.RegState;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable EmergencyRegResult {
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyScanType.aidl b/radio/aidl/android/hardware/radio/network/EmergencyScanType.aidl
index 72c5490..efa6c02 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyScanType.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyScanType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/EutranBands.aidl b/radio/aidl/android/hardware/radio/network/EutranBands.aidl
index 72e76e3..969a1b7 100644
--- a/radio/aidl/android/hardware/radio/network/EutranBands.aidl
+++ b/radio/aidl/android/hardware/radio/network/EutranBands.aidl
@@ -18,6 +18,7 @@
 
 /**
  * EUTRAN bands up to V16.4.0
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
index b986944..fb319c1 100644
--- a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.network.LteVopsInfo;
 import android.hardware.radio.network.NrIndicators;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable EutranRegistrationInfo {
diff --git a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
index c3b3898..fc7cc1b 100644
--- a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable EvdoSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/GeranBands.aidl b/radio/aidl/android/hardware/radio/network/GeranBands.aidl
index 0e5b7b2..29d829f 100644
--- a/radio/aidl/android/hardware/radio/network/GeranBands.aidl
+++ b/radio/aidl/android/hardware/radio/network/GeranBands.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
index 796f80f..d569cf7 100644
--- a/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable GsmSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index f22cdb0..e4c3856 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -37,6 +37,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioNetworkResponse and IRadioNetworkIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioNetwork {
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index 47d932d..2c6f4e7 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -21,16 +21,17 @@
 import android.hardware.radio.network.BarringInfo;
 import android.hardware.radio.network.CellIdentity;
 import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.EmergencyRegResult;
 import android.hardware.radio.network.LinkCapacityEstimate;
 import android.hardware.radio.network.NetworkScanResult;
 import android.hardware.radio.network.PhoneRestrictedState;
 import android.hardware.radio.network.PhysicalChannelConfig;
 import android.hardware.radio.network.SignalStrength;
 import android.hardware.radio.network.SuppSvcNotification;
-import android.hardware.radio.network.EmergencyRegResult;
 
 /**
  * Interface declaring unsolicited radio indications for network APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioNetworkIndication {
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 457b5b9..db37a0e 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -33,6 +33,7 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for network APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioNetworkResponse {
diff --git a/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl b/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl
index 9cab28d..7b95273 100644
--- a/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl
+++ b/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl b/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl
index fdbdc2b..c855b18 100644
--- a/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable LceDataInfo {
diff --git a/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl b/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl
index 6461719..0aea27c 100644
--- a/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl
+++ b/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable LinkCapacityEstimate {
diff --git a/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
index 2d97c45..21d3ec7 100644
--- a/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable LteSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl
index fb3b986..a320acb 100644
--- a/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl
@@ -19,6 +19,7 @@
 /**
  * Type to define the LTE specific network capabilities for voice over PS including emergency and
  * normal voice calls.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
index ae173c7..37f2cf1 100644
--- a/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.network.RadioAccessSpecifier;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable NetworkScanRequest {
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
index 6d83f74..4465046 100644
--- a/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.RadioError;
 import android.hardware.radio.network.CellInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable NetworkScanResult {
diff --git a/radio/aidl/android/hardware/radio/network/NgranBands.aidl b/radio/aidl/android/hardware/radio/network/NgranBands.aidl
index 53c7a3d..a87a0d1 100644
--- a/radio/aidl/android/hardware/radio/network/NgranBands.aidl
+++ b/radio/aidl/android/hardware/radio/network/NgranBands.aidl
@@ -18,6 +18,7 @@
 
 /**
  * NGRAN bands up to V16.5.0
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl b/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl
index e293dff..00e19fe 100644
--- a/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl
@@ -18,6 +18,7 @@
 
 /**
  * NR Dual connectivity state
+ * @hide
  */
 @VintfStability
 @Backing(type="byte")
diff --git a/radio/aidl/android/hardware/radio/network/NrIndicators.aidl b/radio/aidl/android/hardware/radio/network/NrIndicators.aidl
index 32cc964..214272c 100644
--- a/radio/aidl/android/hardware/radio/network/NrIndicators.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrIndicators.aidl
@@ -18,6 +18,7 @@
 
 /**
  * The parameters of NR 5G Non-Standalone.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
index 30ae067..65daf36 100644
--- a/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable NrSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
index 197f401..71961a3 100644
--- a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
@@ -19,6 +19,7 @@
 /**
  * Type to define the NR specific network capabilities for voice over PS including emergency and
  * normal voice calls.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl b/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl
index 56f4dca..36dbadf 100644
--- a/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable OperatorInfo {
diff --git a/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl b/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl
index 23ae3b1..de3527c 100644
--- a/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl
+++ b/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
index 9996953..ecb9463 100644
--- a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
+++ b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.network.CellConnectionStatus;
 import android.hardware.radio.network.PhysicalChannelConfigBand;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable PhysicalChannelConfig {
diff --git a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
index 707a032..aa0e9b2 100644
--- a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
+++ b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
@@ -21,6 +21,7 @@
 import android.hardware.radio.network.NgranBands;
 import android.hardware.radio.network.UtranBands;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union PhysicalChannelConfigBand {
diff --git a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
index 8504248..b3cee47 100644
--- a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
+++ b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.AccessNetwork;
 import android.hardware.radio.network.RadioAccessSpecifierBands;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioAccessSpecifier {
diff --git a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
index 38afee5..4bf694a 100644
--- a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
+++ b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
@@ -21,6 +21,7 @@
 import android.hardware.radio.network.NgranBands;
 import android.hardware.radio.network.UtranBands;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 union RadioAccessSpecifierBands {
diff --git a/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
index 45c4a51..364a562 100644
--- a/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
+++ b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/RegState.aidl b/radio/aidl/android/hardware/radio/network/RegState.aidl
index bdba4c4..de2d5f6 100644
--- a/radio/aidl/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegState.aidl
@@ -20,6 +20,7 @@
  * Please note that registration state UNKNOWN is treated as "out of service" in Android telephony.
  * Registration state REG_DENIED must be returned if Location Update Reject (with cause 17 - Network
  * Failure) is received repeatedly from the network, to facilitate "managed roaming".
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
index f1d2972..57a73c0 100644
--- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -22,6 +22,7 @@
 import android.hardware.radio.network.RegState;
 import android.hardware.radio.network.RegistrationFailCause;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RegStateResult {
diff --git a/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl b/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl
index 9549f2e..2955f96 100644
--- a/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl
@@ -19,6 +19,7 @@
 /**
  * Call fail causes for Circuit-switched service enumerated in 3GPP TS 24.008, 10.5.3.6 and
  * 10.5.147. Additional detail is available in 3GPP TS 24.008 Annex G.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
index ddb4582..5fed522 100644
--- a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
@@ -24,6 +24,7 @@
 import android.hardware.radio.network.TdscdmaSignalStrength;
 import android.hardware.radio.network.WcdmaSignalStrength;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
index 0a8e9ce..e440a64 100644
--- a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -20,6 +20,7 @@
 
 /**
  * Contains the threshold values of each signal measurement type.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl b/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl
index d4229e1..3b8c8b2 100644
--- a/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl
+++ b/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SuppSvcNotification {
diff --git a/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
index ec9ca6b..4afdd0f 100644
--- a/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable TdscdmaSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
index 5a714a4..0b6cfdd 100644
--- a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
@@ -21,6 +21,7 @@
  *
  * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
  * Annex A.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/UtranBands.aidl b/radio/aidl/android/hardware/radio/network/UtranBands.aidl
index a0fd427..8478b66 100644
--- a/radio/aidl/android/hardware/radio/network/UtranBands.aidl
+++ b/radio/aidl/android/hardware/radio/network/UtranBands.aidl
@@ -18,6 +18,7 @@
 
 /**
  * UTRAN bands up to V15.0.0
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
index 7595c05..ace89ed 100644
--- a/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.network;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable WcdmaSignalStrength {
diff --git a/radio/aidl/android/hardware/radio/satellite/IRadioSatellite.aidl b/radio/aidl/android/hardware/radio/satellite/IRadioSatellite.aidl
new file mode 100644
index 0000000..749f49f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/IRadioSatellite.aidl
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+import android.hardware.radio.satellite.IRadioSatelliteIndication;
+import android.hardware.radio.satellite.IRadioSatelliteResponse;
+import android.hardware.radio.satellite.IndicationFilter;
+import android.hardware.radio.satellite.SatelliteFeature;
+
+/**
+ * This interface is used by telephony to send commands to and query info from satellite modem.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * @hide
+ */
+@VintfStability
+oneway interface IRadioSatellite {
+    /**
+     * Add contacts that are allowed to be used for satellite communication. This is applicable for
+     * incoming messages as well.
+     *
+     * @param serial Serial number of request.
+     * @param contacts List of allowed contacts to be added.
+     */
+    void addAllowedSatelliteContacts(in int serial, in String[] contacts);
+
+    /**
+     * Get feature capabilities supported by satellite.
+     *
+     * @param serial Serial number of request.
+     */
+    void getCapabilities(in int serial);
+
+    /**
+     * Get max number of characters per text message.
+     *
+     * @param serial Serial number of request.
+     */
+    void getMaxCharactersPerTextMessage(in int serial);
+
+    /**
+     * Get pending messages.
+     *
+     * @param serial Serial number of request.
+     */
+    void getPendingMessages(in int serial);
+
+    /**
+     * Get satellite modem state.
+     *
+     * @param serial Serial number of request.
+     */
+    void getPowerState(in int serial);
+
+    /**
+     * Get current satellite registration mode, which is defined in {@link #SatelliteMode}.
+     *
+     * @param serial Serial number of request.
+     */
+    void getSatelliteMode(in int serial);
+
+    /**
+     * Get time for next visibility of satellite.
+     *
+     * @param serial Serial number of request.
+     */
+    void getTimeForNextSatelliteVisibility(in int serial);
+
+    /**
+     * Provision the subscription with a satellite provider. This is needed to register the
+     * subscription if the provider allows dynamic registration.
+     *
+     * @param serial Serial number of request.
+     * @param imei IMEI of the SIM associated with the satellite modem.
+     * @param msisdn MSISDN of the SIM associated with the satellite modem.
+     * @param imsi IMSI of the SIM associated with the satellite modem.
+     * @param features List of features to be provisioned.
+     */
+    void provisionService(in int serial, in String imei, in String msisdn, in String imsi,
+            in SatelliteFeature[] features);
+
+    /**
+     * Remove contacts that are allowed to be used for satellite communication. This is applicable
+     * for incoming messages as well.
+     *
+     * @param serial Serial number of request.
+     * @param contacts List of allowed contacts to be removed.
+     */
+    void removeAllowedSatelliteContacts(in int serial, in String[] contacts);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Send text messages.
+     *
+     * @param serial Serial number of request.
+     * @param messages List of messages in text format to be sent.
+     * @param destination The recipient of the message.
+     * @param latitude The current latitude of the device.
+     * @param longitude The current longitude of the device. The location (i.e., latitude and
+     *        longitude) of the device will be filled for emergency messages.
+     */
+    void sendMessages(in int serial, in String[] messages, in String destination,
+            in double latitude, in double longitude);
+
+    /**
+     * Set the filter for what type of indication framework want to receive from modem.
+     *
+     * @param serial Serial number of request.
+     * @param filterBitmask The filter bitmask identifying what type of indication Telephony
+     *                      framework wants to receive from modem. This bitmask is the 'or'
+     *                      combination of the enum values defined in {@link #IndicationFilter}.
+     */
+    void setIndicationFilter(in int serial, in int filterBitmask);
+
+    /**
+     * Turn satellite modem on/off.
+     *
+     * @param serial Serial number of request.
+     * @param on True for turning on.
+     *           False for turning off.
+     */
+    void setPower(in int serial, in boolean on);
+
+    /**
+     * Set response functions for Satellite requests and indications.
+     *
+     * @param satelliteResponse Object containing response functions
+     * @param satelliteIndication Object containing radio indications
+     */
+    void setResponseFunctions(in IRadioSatelliteResponse satelliteResponse,
+            in IRadioSatelliteIndication satelliteIndication);
+
+    /**
+     * User started pointing to the satellite. Modem should continue to update the pointing input
+     * as user device/satellite moves.
+     *
+     * @param serial Serial number of request.
+     */
+    void startSendingSatellitePointingInfo(in int serial);
+
+    /**
+     * Stop sending satellite pointing info to the framework.
+     *
+     * @param serial Serial number of request.
+     */
+    void stopSendingSatellitePointingInfo(in int serial);
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl b/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl
new file mode 100644
index 0000000..2a2fb95
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteIndication.aidl
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.satellite.NTRadioTechnology;
+import android.hardware.radio.satellite.PointingInfo;
+import android.hardware.radio.satellite.SatelliteFeature;
+import android.hardware.radio.satellite.SatelliteMode;
+
+/**
+ * Interface declaring unsolicited radio indications for satellite APIs.
+ * @hide
+ */
+@VintfStability
+oneway interface IRadioSatelliteIndication {
+    /**
+     * Confirms that ongoing message transfer is complete.
+     *
+     * @param type Type of radio indication
+     * @param complete True mean the transfer is complete.
+     *                 False means the transfer is not complete.
+     */
+    void onMessagesTransferComplete(in RadioIndicationType type, in boolean complete);
+
+    /**
+     * Indicates new message received on device.
+     *
+     * @param type Type of radio indication
+     * @param messages List of new messages received.
+     */
+    void onNewMessages(in RadioIndicationType type, in String[] messages);
+
+    /**
+     * Indicates that satellite has pending messages for the device to be pulled.
+     *
+     * @param type Type of radio indication
+     * @param count Number of pending messages.
+     */
+    void onPendingMessageCount(in RadioIndicationType type, in int count);
+
+    /**
+     * Indicate that satellite provision state has changed.
+     *
+     * @param type Type of radio indication
+     * @param provisioned True means the service is provisioned.
+     *                    False means the service is not provisioned.
+     * @param features List of Feature whose provision state has changed.
+     */
+    void onProvisionStateChanged(
+            in RadioIndicationType type, boolean provisioned, in SatelliteFeature[] features);
+
+    /**
+     * Indicate that satellite mode has changed.
+     *
+     * @param type Type of radio indication
+     * @param mode The current mode of the satellite modem.
+     */
+    void onSatelliteModeChanged(in RadioIndicationType type, in SatelliteMode mode);
+
+    /**
+     * Indicate that satellite Pointing input has changed.
+     *
+     * @param type Type of radio indication
+     * @param pointingInfo The current pointing info.
+     */
+    void onSatellitePointingInfoChanged(in RadioIndicationType type, in PointingInfo pointingInfo);
+
+    /**
+     * Indicate that satellite radio technology has changed.
+     *
+     * @param type Type of radio indication
+     * @param technology The current technology of the satellite modem.
+     */
+    void onSatelliteRadioTechnologyChanged(
+            in RadioIndicationType type, in NTRadioTechnology technology);
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl b/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl
new file mode 100644
index 0000000..2bef3d2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/IRadioSatelliteResponse.aidl
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.satellite.NTRadioTechnology;
+import android.hardware.radio.satellite.SatelliteCapabilities;
+import android.hardware.radio.satellite.SatelliteMode;
+
+/**
+ * Interface declaring response functions to solicited radio requests for satellite APIs.
+ * @hide
+ */
+@VintfStability
+oneway interface IRadioSatelliteResponse {
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * Response of the request addAllowedSatelliteContacts.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:ABORTED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:CANCELLED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_CONTACT
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:NETWORK_TIMEOUT
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_SATELLITE_SIGNAL
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NOT_SUFFICIENT_ACCOUNT_BALANCE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIM_BUSY
+     *   RadioError:SIM_ERR
+     *   RadioError:SIM_FULL
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:UNIDENTIFIED_SUBSCRIBER
+     */
+    void addAllowedSatelliteContactsResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request getCapabilities.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param capabilities List of capabilities that the satellite modem supports.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void getCapabilitiesResponse(in RadioResponseInfo info, in SatelliteCapabilities capabilities);
+
+    /**
+     * Response of the request getMaxCharactersPerTextMessage.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param charLimit Maximum number of characters in a text message that can be sent.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void getMaxCharactersPerTextMessageResponse(in RadioResponseInfo info, in int charLimit);
+
+    /**
+     * Response of the request getPendingMessages.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param messages List of pending messages received.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:ABORTED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     *   RadioError:CANCELLED
+     *   RadioError:ENCODING_ERR
+     *   RadioError:ENCODING_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:NETWORK_TIMEOUT
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_SMS_TO_ACK
+     *   RadioError:NO_SATELLITE_SIGNAL
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NOT_SUFFICIENT_ACCOUNT_BALANCE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIM_BUSY
+     *   RadioError:SIM_ERR
+     *   RadioError:SIM_FULL
+     *   RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL
+     */
+    void getPendingMessagesResponse(in RadioResponseInfo info, in String[] messages);
+
+    /**
+     * Response of the request getPowerSate.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param on True means the modem is ON.
+     *           False means the modem is OFF.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void getPowerStateResponse(in RadioResponseInfo info, in boolean on);
+
+    /**
+     * Response of the request getSatelliteMode.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param mode Current Mode of the satellite modem.
+     * @param technology The current technology of the satellite modem.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void getSatelliteModeResponse(
+            in RadioResponseInfo info, in SatelliteMode mode, in NTRadioTechnology technology);
+
+    /**
+     * Response of the request getTimeForNextSatelliteVisibility.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param timeInSeconds The duration in seconds after which the satellite will be visible.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void getTimeForNextSatelliteVisibilityResponse(in RadioResponseInfo info, in int timeInSeconds);
+
+    /**
+     * Response of the request provisionService.
+     *
+     * @param info Response info struct containing serial no. and error
+     * @param provisioned True means the service is provisioned.
+     *                    False means the service is not provisioned.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:ABORTED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:CANCELLED
+     *   RadioError:FEATURE_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:MODEM_INCOMPATIBLE
+     *   RadioError:NETWORK_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:NETWORK_TIMEOUT
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_SATELLITE_SIGNAL
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:RADIO_TECHNOLOGY_NOT_SUPPORTED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIM_BUSY
+     *   RadioError:SIM_ERR
+     *   RadioError:SIM_FULL
+     *   RadioError:SUBSCRIBER_NOT_AUTHORIZED
+     *   RadioError:SYSTEM_ERR
+     */
+    void provisionServiceResponse(in RadioResponseInfo info, in boolean provisioned);
+
+    /**
+     * Response of the request removeAllowedSatelliteContacts.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:ABORTED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:CANCELLED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_CONTACT
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:NETWORK_TIMEOUT
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_SATELLITE_SIGNAL
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NOT_SUFFICIENT_ACCOUNT_BALANCE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIM_BUSY
+     *   RadioError:SIM_ERR
+     *   RadioError:SIM_FULL
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:UNIDENTIFIED_SUBSCRIBER
+     */
+    void removeAllowedSatelliteContactsResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request sendMessages.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:ABORTED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     *   RadioError:CANCELLED
+     *   RadioError:ENCODING_ERR
+     *   RadioError:ENCODING_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:NETWORK_TIMEOUT
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_SMS_TO_ACK
+     *   RadioError:NO_SATELLITE_SIGNAL
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NOT_SUFFICIENT_ACCOUNT_BALANCE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIM_BUSY
+     *   RadioError:SIM_ERR
+     *   RadioError:SIM_FULL
+     *   RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL
+     *   RadioError:UNIDENTIFIED_SUBSCRIBER
+     */
+    void sendMessagesResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request setIndicationFilter.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void setIndicationFilterResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request setPower.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_RF_CALIBRATION_INFO
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:RF_HARDWARE_ISSUE
+     *   RadioError:SYSTEM_ERR
+     */
+    void setPowerResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request startSendingSatellitePointingInfo.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void startSendingSatellitePointingInfoResponse(in RadioResponseInfo info);
+
+    /**
+     * Response of the request stopSendingSatellitePointingInfo.
+     *
+     * @param info Response info struct containing serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     */
+    void stopSendingSatellitePointingInfoResponse(in RadioResponseInfo info);
+}
diff --git a/automotive/vehicle/aidl/impl/utils/test/Android.bp b/radio/aidl/android/hardware/radio/satellite/IndicationFilter.aidl
similarity index 66%
rename from automotive/vehicle/aidl/impl/utils/test/Android.bp
rename to radio/aidl/android/hardware/radio/satellite/IndicationFilter.aidl
index ad9954f..16bd10d 100644
--- a/automotive/vehicle/aidl/impl/utils/test/Android.bp
+++ b/radio/aidl/android/hardware/radio/satellite/IndicationFilter.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
+package android.hardware.radio.satellite;
 
-cc_library_headers {
-    name: "VehicleHalTestUtilHeaders",
-    vendor: true,
-    header_libs: ["VehicleHalUtilHeaders"],
-    export_include_dirs: ["include"],
+/** @hide */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum IndicationFilter {
+    NONE = 0,
+    SATELLITE_MODE = 1
 }
diff --git a/radio/aidl/android/hardware/radio/satellite/NTRadioTechnology.aidl b/radio/aidl/android/hardware/radio/satellite/NTRadioTechnology.aidl
new file mode 100644
index 0000000..f161895
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/NTRadioTechnology.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+/** @hide */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum NTRadioTechnology {
+    /* 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology */
+    NB_IOT_NTN = 0,
+    /* 3GPP 5G NR over Non-Terrestrial-Networks technology */
+    NR_NTN = 1,
+    /* 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology */
+    EMTC_NTN = 2,
+    /* Proprietary technology like Iridium or Bullitt */
+    PROPRIETARY = 3
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/PointingInfo.aidl b/radio/aidl/android/hardware/radio/satellite/PointingInfo.aidl
new file mode 100644
index 0000000..9f12d7a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/PointingInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+/** @hide */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PointingInfo {
+    /* Satellite azimuth in degrees */
+    float satelliteAzimuthDegrees;
+
+    /* Satellite elevation in degrees */
+    float satelliteElevationDegrees;
+
+    /* Antenna azimuth in degrees */
+    float antennaAzimuthDegrees;
+
+    /**
+     * Angle of rotation about the x axis. This value represents the angle between a plane
+     * parallel to the device's screen and a plane parallel to the ground.
+     */
+    float antennaPitchDegrees;
+
+    /**
+     * Angle of rotation about the y axis. This value represents the angle between a plane
+     * perpendicular to the device's screen and a plane parallel to the ground.
+     */
+    float antennaRollDegrees;
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/SatelliteCapabilities.aidl b/radio/aidl/android/hardware/radio/satellite/SatelliteCapabilities.aidl
new file mode 100644
index 0000000..29eb635
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/SatelliteCapabilities.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+import android.hardware.radio.satellite.NTRadioTechnology;
+import android.hardware.radio.satellite.SatelliteFeature;
+
+/** @hide */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SatelliteCapabilities {
+    /**
+     * List of technologies supported by the satellite modem.
+     */
+    NTRadioTechnology[] supportedRadioTechnologies;
+
+    /**
+     * Whether satellite mode is always on (this indicates the power impact of keeping it on is
+     * very minimal).
+     */
+    boolean isAlwaysOn;
+
+    /**
+     * Whether UE needs to point to a satellite to send and receive data.
+     */
+    boolean needsPointingToSatellite;
+
+    /**
+     * List of features supported by the satellite modem.
+     */
+    SatelliteFeature[] supportedFeatures;
+
+    /**
+     * Whether UE needs a separate SIM profile to communicate with satellite network.
+     */
+    boolean needsSeparateSimProfile;
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/SatelliteFeature.aidl b/radio/aidl/android/hardware/radio/satellite/SatelliteFeature.aidl
new file mode 100644
index 0000000..6284ec8
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/SatelliteFeature.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+/** @hide */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum SatelliteFeature {
+    /* Able to send and receive SMS messages to/from SOS numbers like call/service centers */
+    SOS_SMS = 0,
+    /* Able to send and receive SMS messages to/from emergency numbers like 911 */
+    EMERGENCY_SMS = 1,
+    /* Able to send and receive SMS messages to/from any allowed contacts */
+    SMS = 2,
+    /* Able to send device location to allowed contacts */
+    LOCATION_SHARING = 3
+}
diff --git a/radio/aidl/android/hardware/radio/satellite/SatelliteMode.aidl b/radio/aidl/android/hardware/radio/satellite/SatelliteMode.aidl
new file mode 100644
index 0000000..b764d0e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/satellite/SatelliteMode.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package android.hardware.radio.satellite;
+
+/** @hide */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum SatelliteMode {
+    /* Satellite modem is powered off */
+    POWERED_OFF = 0,
+    /* Satellite modem is in out of service state and not searching for satellite signal */
+    OUT_OF_SERVICE_NOT_SEARCHING = 1,
+    /* Satellite modem is in out of service state and searching for satellite signal */
+    OUT_OF_SERVICE_SEARCHING = 2,
+    /* Satellite modem has found satellite signal and gets connected to the satellite network */
+    ACQUIRED = 3,
+    /* Satellite modem is sending and/or receiving messages */
+    MESSAGE_TRANSFERRING = 4
+}
diff --git a/radio/aidl/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
index c072f6a..7fe8e40 100644
--- a/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.sim.PersoSubstate;
 import android.hardware.radio.sim.PinState;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable AppStatus {
diff --git a/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
index f8b5922..2598dcb 100644
--- a/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
index 1419c51..043bfa4 100644
--- a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
@@ -21,6 +21,7 @@
 import android.hardware.radio.sim.AppStatus;
 import android.hardware.radio.sim.PinState;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CardStatus {
diff --git a/radio/aidl/android/hardware/radio/sim/Carrier.aidl b/radio/aidl/android/hardware/radio/sim/Carrier.aidl
index d25214f..8b27088 100644
--- a/radio/aidl/android/hardware/radio/sim/Carrier.aidl
+++ b/radio/aidl/android/hardware/radio/sim/Carrier.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable Carrier {
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
index edbec2c..d5e0c43 100644
--- a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.sim.Carrier;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CarrierRestrictions {
@@ -25,12 +26,12 @@
     @Backing(type="int")
     /** This enum defines the carrier restriction status values */
     enum CarrierRestrictionStatus {
-       /**
-        * Carrier restriction status value is unknown, used in cases where modem is dependent on
-        * external module to know about the lock status and the module hasn’t yet provided the lock
-        * status. For example, when the lock status is maintained on a cloud server and device has
-        * just booted after out of box and not yet connected to the internet.
-        */
+        /**
+         * Carrier restriction status value is unknown, used in cases where modem is dependent on
+         * external module to know about the lock status and the module hasn’t yet provided the lock
+         * status. For example, when the lock status is maintained on a cloud server and device has
+         * just booted after out of box and not yet connected to the internet.
+         */
         UNKNOWN = 0,
         /** There is no carrier restriction on the device */
         NOT_RESTRICTED = 1,
diff --git a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
index 6aa6926..4c6c1ef 100644
--- a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index 3823a71..1453664 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -37,6 +37,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioSimResponse and IRadioSimIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioSim {
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
index a139040..fc6355d 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
@@ -24,6 +24,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for SIM APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioSimIndication {
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
index 90f172f..48253d4 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -27,6 +27,7 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for SIM APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioSimResponse {
diff --git a/radio/aidl/android/hardware/radio/sim/IccIo.aidl b/radio/aidl/android/hardware/radio/sim/IccIo.aidl
index f173c8e..0877b7a 100644
--- a/radio/aidl/android/hardware/radio/sim/IccIo.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IccIo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable IccIo {
diff --git a/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl b/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl
index efcbbda..ac89698 100644
--- a/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable IccIoResult {
diff --git a/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl b/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
index ba1dda5..b31b081 100644
--- a/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
+++ b/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Carrier specific Information sent by the carrier, which will be used to encrypt IMSI and IMPI.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
index b1385a4..f9414a8 100644
--- a/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Enum representing the status of the received PB indication.
+ * @hide
  */
 @VintfStability
 @Backing(type="byte")
diff --git a/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl b/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl
index f85c84b..4da86c5 100644
--- a/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl
@@ -19,6 +19,7 @@
 /**
  * Additional personalization categories in addition to those specified in 3GPP TS 22.022 and
  * 3GPP2 C.S0068-0.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl b/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl
index 97c3dba..2212fda 100644
--- a/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable PhonebookCapacity {
diff --git a/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl b/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl
index c4db0e6..1653c31 100644
--- a/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl
@@ -19,6 +19,7 @@
 /**
  * Phonebook-record-information specified by EF_ADN (Abbreviated dialing numbers) record of SIM
  * as per 3GPP spec 31.102 v15 Section-4.4.2.3.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/PinState.aidl b/radio/aidl/android/hardware/radio/sim/PinState.aidl
index 85048bb..f5f3108 100644
--- a/radio/aidl/android/hardware/radio/sim/PinState.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PinState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl b/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl
index 553404b..70a2191 100644
--- a/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SelectUiccSub {
diff --git a/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl b/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl
index 9e3e8ed..585118a 100644
--- a/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SessionInfo {
diff --git a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
index 9799f2b..d0e3c39 100644
--- a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SimApdu {
diff --git a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index 6490d51..18f97f7 100644
--- a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
index 69aff66..943f1d2 100644
--- a/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SimRefreshResult {
diff --git a/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl b/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl
index dc47172..334ae3d 100644
--- a/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl
+++ b/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl
@@ -19,6 +19,7 @@
 /**
  * Audio codec which is used on GSM, UMTS, and CDMA. These values must be opaque to the Android
  * framework. Only for display.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/voice/Call.aidl b/radio/aidl/android/hardware/radio/voice/Call.aidl
index b09d7a0..ee0b025 100644
--- a/radio/aidl/android/hardware/radio/voice/Call.aidl
+++ b/radio/aidl/android/hardware/radio/voice/Call.aidl
@@ -19,6 +19,7 @@
 import android.hardware.radio.voice.AudioQuality;
 import android.hardware.radio.voice.UusInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable Call {
diff --git a/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl b/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl
index c4143b9..9b4ecd9 100644
--- a/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl
@@ -18,6 +18,7 @@
 
 /**
  * See also com.android.internal.telephony.gsm.CallForwardInfo
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
index 4d447d7..d97b319 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.voice.CdmaSignalInfoRecord;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaCallWaiting {
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
index 522f7ae..7e5a68d 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -22,6 +22,7 @@
  * the form: display_tag, display_len, and display_len occurrences of the char field if the
  * display_tag is not 10000000 or 10000001. To save space, the records are stored consecutively in
  * a byte buffer. The display_tag, display_len and chari fields are all 1 byte.
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
index 1a4f1b3..f5c656b 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -24,10 +24,11 @@
 import android.hardware.radio.voice.CdmaT53AudioControlInfoRecord;
 import android.hardware.radio.voice.CdmaT53ClirInfoRecord;
 
-@VintfStability
 /**
  * Max length of CdmaInformationRecords[] is CDMA_MAX_NUMBER_OF_INFO_RECS
+ * @hide
  */
+@VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaInformationRecord {
     const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10;
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
index 8bfc5f7..15c22a0 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Line Control Information Record as defined in C.S0005 section 3.7.5.15
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
index 9084b25..b04e273 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -20,6 +20,7 @@
  * Called Party Number Info Rec as defined in C.S0005 section 3.7.5.2
  * Calling Party Number Info Rec as defined in C.S0005 section 3.7.5.3
  * Connected Number Info Rec as defined in C.S0005 section 3.7.5.4
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
index 81fb003..b6444ab 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
index 5c9e2f2..691712e 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.voice.CdmaNumberInfoRecord;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CdmaRedirectingNumberInfoRecord {
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
index 3334475..4302ba4 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
@@ -18,6 +18,7 @@
 
 /**
  * CDMA Signal Information Record as defined in C.S0005 section 3.7.5.5
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
index 9795cf0..44ac2b4 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
@@ -18,6 +18,7 @@
 
 /**
  * T53 Audio Control Information Record
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
index 5ccd251..564d761 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
@@ -18,6 +18,7 @@
 
 /**
  * T53 CLIR Information Record
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/CfData.aidl b/radio/aidl/android/hardware/radio/voice/CfData.aidl
index 8f4c227..84304f4 100644
--- a/radio/aidl/android/hardware/radio/voice/CfData.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CfData.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.voice.CallForwardInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable CfData {
diff --git a/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
index 4021471..0a2ea2c 100644
--- a/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
+++ b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/Dial.aidl b/radio/aidl/android/hardware/radio/voice/Dial.aidl
index ca028ad..a874181 100644
--- a/radio/aidl/android/hardware/radio/voice/Dial.aidl
+++ b/radio/aidl/android/hardware/radio/voice/Dial.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.voice.UusInfo;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable Dial {
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
index d623346..9f8993d 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -18,6 +18,7 @@
 
 /**
  * Indicates how the implementation should handle the emergency call if it is required by Android.
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
index e380ce8..30f29a9 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -37,6 +37,7 @@
  *            3gpp 23.167, Section 6 - Functional description;
  *            3gpp 24.503, Section 5.1.6.8.1 - General;
  *            RFC 5031
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl
index a4ac7aa..80f873a 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl
@@ -31,6 +31,7 @@
  * services are associated with this emergency number.
  *
  * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ * @hide
  */
 @VintfStability
 @Backing(type="int")
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
index c05d237..bf9b9cb 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
@@ -30,6 +30,7 @@
  * duration of a method call. If clients provide colliding serials (including passing the same
  * serial to different methods), multiple responses (one for each method call) must still be served.
  * setResponseFunctions must work with IRadioVoiceResponse and IRadioVoiceIndication.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioVoice {
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
index 437fef6..9de6364 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -28,6 +28,7 @@
 
 /**
  * Interface declaring unsolicited radio indications for voice APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioVoiceIndication {
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
index 39e3ace..21264df 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -25,6 +25,7 @@
 
 /**
  * Interface declaring response functions to solicited radio requests for voice APIs.
+ * @hide
  */
 @VintfStability
 oneway interface IRadioVoiceResponse {
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
index 5c8c819..9a38197 100644
--- a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
index 078722a..4ed17d2 100644
--- a/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.radio.voice.LastCallFailCause;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable LastCallFailCauseInfo {
diff --git a/radio/aidl/android/hardware/radio/voice/SrvccState.aidl b/radio/aidl/android/hardware/radio/voice/SrvccState.aidl
index 08eb877..923518d 100644
--- a/radio/aidl/android/hardware/radio/voice/SrvccState.aidl
+++ b/radio/aidl/android/hardware/radio/voice/SrvccState.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
index b944bf4..c965a7d 100644
--- a/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
+++ b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable SsInfoData {
diff --git a/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
index 7982275..9fe4024 100644
--- a/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
+++ b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -20,6 +20,7 @@
 import android.hardware.radio.voice.CfData;
 import android.hardware.radio.voice.SsInfoData;
 
+/** @hide */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable StkCcUnsolSsResult {
diff --git a/radio/aidl/android/hardware/radio/voice/TtyMode.aidl b/radio/aidl/android/hardware/radio/voice/TtyMode.aidl
index e8dd723..b9203e1 100644
--- a/radio/aidl/android/hardware/radio/voice/TtyMode.aidl
+++ b/radio/aidl/android/hardware/radio/voice/TtyMode.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
index cece4bd..d43462e 100644
--- a/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
+++ b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.voice;
 
+/** @hide */
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
index 220a8fc..5d499ca 100644
--- a/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
+++ b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
@@ -18,6 +18,7 @@
 
 /**
  * User-to-User Signaling Information defined in 3GPP 23.087 v8.0
+ * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
diff --git a/radio/aidl/compat/OWNERS b/radio/aidl/compat/OWNERS
index 471d806..3a7a009 100644
--- a/radio/aidl/compat/OWNERS
+++ b/radio/aidl/compat/OWNERS
@@ -1,3 +1,3 @@
 # Bug component: 20868
-include ../../1.0/vts/OWNERS
+
 twasilczyk@google.com
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index 5cf1378..f5000b9 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -31,20 +31,21 @@
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     shared_libs: [
-        "android.hardware.radio.config-V2-ndk",
+        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V2-ndk",
-        "android.hardware.radio.ims-V1-ndk",
-        "android.hardware.radio.ims.media-V1-ndk",
-        "android.hardware.radio.messaging-V2-ndk",
-        "android.hardware.radio.modem-V2-ndk",
-        "android.hardware.radio.network-V2-ndk",
+        "android.hardware.radio.data-V3-ndk",
+        "android.hardware.radio.ims-V2-ndk",
+        "android.hardware.radio.ims.media-V2-ndk",
+        "android.hardware.radio.messaging-V3-ndk",
+        "android.hardware.radio.modem-V3-ndk",
+        "android.hardware.radio.network-V3-ndk",
         "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V2-ndk",
-        "android.hardware.radio.voice-V2-ndk",
+        "android.hardware.radio.satellite-V1-ndk",
+        "android.hardware.radio.sim-V3-ndk",
+        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
@@ -93,6 +94,9 @@
         "sap/Sap.cpp",
         "sap/SapCallback.cpp",
         "sap/structs.cpp",
+        "satellite/RadioIndication-satellite.cpp",
+        "satellite/RadioResponse-satellite.cpp",
+        "satellite/RadioSatellite.cpp",
         "sim/RadioIndication-sim.cpp",
         "sim/RadioResponse-sim.cpp",
         "sim/RadioSim.cpp",
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
index f042456..ad9127e 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -23,6 +23,7 @@
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
 #include <aidl/android/hardware/radio/modem/IRadioModemIndication.h>
 #include <aidl/android/hardware/radio/network/IRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/satellite/IRadioSatelliteIndication.h>
 #include <aidl/android/hardware/radio/sim/IRadioSimIndication.h>
 #include <aidl/android/hardware/radio/voice/IRadioVoiceIndication.h>
 #include <android/hardware/radio/1.6/IRadioIndication.h>
@@ -60,6 +61,10 @@
             ::aidl::android::hardware::radio::ims::IRadioImsIndication,
             ::aidl::android::hardware::radio::ims::IRadioImsIndicationDefault, true>
             mImsCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::satellite::IRadioSatelliteIndication,
+            ::aidl::android::hardware::radio::satellite::IRadioSatelliteIndicationDefault, true>
+            mSatelliteCb;
 
     // IRadioIndication @ 1.0
     Return<void> radioStateChanged(V1_0::RadioIndicationType type,
@@ -227,6 +232,9 @@
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsIndication> imsCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::satellite::IRadioSatelliteIndication>
+                    satelliteCb);
 
     std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
     std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
@@ -236,6 +244,8 @@
     std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb();
     std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voiceCb();
     std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsIndication> imsCb();
+    std::shared_ptr<::aidl::android::hardware::radio::satellite::IRadioSatelliteIndication>
+    satelliteCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
index e20eed9..b976435 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -24,6 +24,7 @@
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
 #include <aidl/android/hardware/radio/modem/IRadioModemResponse.h>
 #include <aidl/android/hardware/radio/network/IRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/satellite/IRadioSatelliteResponse.h>
 #include <aidl/android/hardware/radio/sim/IRadioSimResponse.h>
 #include <aidl/android/hardware/radio/voice/IRadioVoiceResponse.h>
 #include <android/hardware/radio/1.6/IRadioResponse.h>
@@ -54,6 +55,9 @@
     GuaranteedCallback<::aidl::android::hardware::radio::ims::IRadioImsResponse,
                        ::aidl::android::hardware::radio::ims::IRadioImsResponseDefault>
             mImsCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::satellite::IRadioSatelliteResponse,
+                       ::aidl::android::hardware::radio::satellite::IRadioSatelliteResponseDefault>
+            mSatelliteCb;
 
     // IRadioResponse @ 1.0
     Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
@@ -447,6 +451,9 @@
             std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse> imsCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::satellite::IRadioSatelliteResponse>
+                    satelliteCb);
 
     std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
     std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
@@ -456,6 +463,8 @@
     std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb();
     std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb();
     std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse> imsCb();
+    std::shared_ptr<::aidl::android::hardware::radio::satellite::IRadioSatelliteResponse>
+    satelliteCb();
 };
 
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSatellite.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSatellite.h
new file mode 100644
index 0000000..3ee6db2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSatellite.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/satellite/BnRadioSatellite.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioSatellite : public RadioCompatBase,
+                       public aidl::android::hardware::radio::satellite::BnRadioSatellite {
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus getCapabilities(int32_t serial) override;
+    ::ndk::ScopedAStatus setPower(int32_t serial, bool on) override;
+    ::ndk::ScopedAStatus getPowerState(int32_t serial) override;
+    ::ndk::ScopedAStatus provisionService(
+            int32_t serial, const std::string& imei, const std::string& msisdn,
+            const std::string& imsi,
+            const std::vector<::aidl::android::hardware::radio::satellite::SatelliteFeature>&
+                    features) override;
+    ::ndk::ScopedAStatus addAllowedSatelliteContacts(
+            int32_t serial, const std::vector<std::string>& contacts) override;
+    ::ndk::ScopedAStatus removeAllowedSatelliteContacts(
+            int32_t serial, const std::vector<std::string>& contacts) override;
+    ::ndk::ScopedAStatus sendMessages(int32_t serial, const std::vector<std::string>& messages,
+                                      const std::string& destination, double latitude,
+                                      double longitude) override;
+    ::ndk::ScopedAStatus getPendingMessages(int32_t serial) override;
+    ::ndk::ScopedAStatus getSatelliteMode(int32_t serial) override;
+    ::ndk::ScopedAStatus setIndicationFilter(int32_t serial, int32_t filterBitmask) override;
+    ::ndk::ScopedAStatus startSendingSatellitePointingInfo(int32_t serial) override;
+    ::ndk::ScopedAStatus stopSendingSatellitePointingInfo(int32_t serial) override;
+    ::ndk::ScopedAStatus getMaxCharactersPerTextMessage(int32_t serial) override;
+    ::ndk::ScopedAStatus getTimeForNextSatelliteVisibility(int32_t serial) override;
+
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<
+                    ::aidl::android::hardware::radio::satellite::IRadioSatelliteResponse>&
+                    radioSatelliteResponse,
+            const std::shared_ptr<
+                    ::aidl::android::hardware::radio::satellite::IRadioSatelliteIndication>&
+                    radioSatelliteIndication) override;
+
+  protected:
+    std::shared_ptr<::aidl::android::hardware::radio::satellite::IRadioSatelliteResponse> respond();
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/satellite/RadioIndication-satellite.cpp b/radio/aidl/compat/libradiocompat/satellite/RadioIndication-satellite.cpp
new file mode 100644
index 0000000..39da43d
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/satellite/RadioIndication-satellite.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "RadioSatelliteIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::satellite;
+
+void RadioIndication::setResponseFunction(
+        std::shared_ptr<aidl::IRadioSatelliteIndication> satelliteCb) {
+    mSatelliteCb = satelliteCb;
+}
+
+std::shared_ptr<aidl::IRadioSatelliteIndication> RadioIndication::satelliteCb() {
+    return mSatelliteCb.get();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/satellite/RadioResponse-satellite.cpp b/radio/aidl/compat/libradiocompat/satellite/RadioResponse-satellite.cpp
new file mode 100644
index 0000000..2209c93
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/satellite/RadioResponse-satellite.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "RadioSatelliteResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::satellite;
+
+void RadioResponse::setResponseFunction(
+        std::shared_ptr<aidl::IRadioSatelliteResponse> satelliteCb) {
+    mSatelliteCb = satelliteCb;
+}
+
+std::shared_ptr<aidl::IRadioSatelliteResponse> RadioResponse::satelliteCb() {
+    return mSatelliteCb.get();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/satellite/RadioSatellite.cpp b/radio/aidl/compat/libradiocompat/satellite/RadioSatellite.cpp
new file mode 100644
index 0000000..16a3167
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/satellite/RadioSatellite.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 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 <libradiocompat/RadioSatellite.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "RadioSatellite"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::satellite;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioSatelliteResponse> RadioSatellite::respond() {
+    return mCallbackManager->response().satelliteCb();
+}
+
+ScopedAStatus RadioSatellite::responseAcknowledgement() {
+    LOG(ERROR) << " responseAcknowledgement is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getCapabilities(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getCapabilities is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::setPower(int32_t serial, bool /*on*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " setPower is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getPowerState(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getPowerSate is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::provisionService(
+        int32_t serial, const std::string& /*imei*/, const std::string& /*msisdn*/,
+        const std::string& /*imsi*/,
+        const std::vector<
+                ::aidl::android::hardware::radio::satellite::SatelliteFeature>& /*features*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " provisionService is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::addAllowedSatelliteContacts(
+        int32_t serial, const std::vector<std::string>& /*contacts*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " addAllowedSatelliteContacts is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::removeAllowedSatelliteContacts(
+        int32_t serial, const std::vector<std::string>& /*contacts*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " removeAllowedSatelliteContacts is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::sendMessages(int32_t serial,
+                                           const std::vector<std::string>& /*messages*/,
+                                           const std::string& /*destination*/, double /*latitude*/,
+                                           double /*longitude*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " sendMessage is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getPendingMessages(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getPendingMessages is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getSatelliteMode(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getSatelliteMode is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::setIndicationFilter(int32_t serial, int32_t /*filterBitmask*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " setIndicationFilter is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::startSendingSatellitePointingInfo(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " startSendingSatellitePointingInfo is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::stopSendingSatellitePointingInfo(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " stopSendingSatellitePointingInfo is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getMaxCharactersPerTextMessage(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getMaxCharactersPerTextMessage is unsupported by HIDL HALs";
+    return ok();
+}
+ScopedAStatus RadioSatellite::getTimeForNextSatelliteVisibility(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " getTimeForNextSatelliteVisibility is unsupported by HIDL HALs";
+    return ok();
+}
+
+ScopedAStatus RadioSatellite::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioSatelliteResponse>& response,
+        const std::shared_ptr<aidl::IRadioSatelliteIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index dff0182..1a6ea48 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -34,20 +34,21 @@
     ],
     shared_libs: [
         "android.hardware.radio-library.compat",
-        "android.hardware.radio.config-V2-ndk",
+        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V2-ndk",
-        "android.hardware.radio.ims-V1-ndk",
-        "android.hardware.radio.ims.media-V1-ndk",
-        "android.hardware.radio.messaging-V2-ndk",
-        "android.hardware.radio.modem-V2-ndk",
-        "android.hardware.radio.network-V2-ndk",
+        "android.hardware.radio.data-V3-ndk",
+        "android.hardware.radio.ims-V2-ndk",
+        "android.hardware.radio.ims.media-V2-ndk",
+        "android.hardware.radio.messaging-V3-ndk",
+        "android.hardware.radio.modem-V3-ndk",
+        "android.hardware.radio.network-V3-ndk",
         "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V2-ndk",
-        "android.hardware.radio.voice-V2-ndk",
+        "android.hardware.radio.satellite-V1-ndk",
+        "android.hardware.radio.sim-V3-ndk",
+        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index e79d3c0..8301f10 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -58,6 +58,9 @@
         "radio_network_test.cpp",
         "radio_sap_callback.cpp",
         "radio_sap_test.cpp",
+        "radio_satellite_indication.cpp",
+        "radio_satellite_response.cpp",
+        "radio_satellite_test.cpp",
         "radio_sim_indication.cpp",
         "radio_sim_response.cpp",
         "radio_sim_test.cpp",
@@ -71,17 +74,18 @@
         "libvintf",
     ],
     static_libs: [
-        "android.hardware.radio-V2-ndk",
-        "android.hardware.radio.config-V2-ndk",
-        "android.hardware.radio.data-V2-ndk",
-        "android.hardware.radio.ims-V1-ndk",
-        "android.hardware.radio.ims.media-V1-ndk",
-        "android.hardware.radio.messaging-V2-ndk",
-        "android.hardware.radio.modem-V2-ndk",
-        "android.hardware.radio.network-V2-ndk",
+        "android.hardware.radio-V3-ndk",
+        "android.hardware.radio.config-V3-ndk",
+        "android.hardware.radio.data-V3-ndk",
+        "android.hardware.radio.ims-V2-ndk",
+        "android.hardware.radio.ims.media-V2-ndk",
+        "android.hardware.radio.messaging-V3-ndk",
+        "android.hardware.radio.modem-V3-ndk",
+        "android.hardware.radio.network-V3-ndk",
         "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V2-ndk",
-        "android.hardware.radio.voice-V2-ndk",
+        "android.hardware.radio.satellite-V1-ndk",
+        "android.hardware.radio.sim-V3-ndk",
+        "android.hardware.radio.voice-V3-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
index c04173b..86c1099 100644
--- a/radio/aidl/vts/VtsHalRadioTargetTest.cpp
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -24,6 +24,7 @@
 #include "radio_modem_utils.h"
 #include "radio_network_utils.h"
 #include "radio_sap_utils.h"
+#include "radio_satellite_utils.h"
 #include "radio_sim_utils.h"
 #include "radio_voice_utils.h"
 
@@ -79,6 +80,12 @@
         testing::ValuesIn(android::getAidlHalInstanceNames(IRadioIms::descriptor)),
         android::PrintInstanceNameToString);
 
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSatelliteTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioSatelliteTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioSatellite::descriptor)),
+        android::PrintInstanceNameToString);
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioImsMediaTest);
 INSTANTIATE_TEST_SUITE_P(PerInstance, RadioImsMediaTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IImsMedia::descriptor)),
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
index d8aa024..1690e89 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.h
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -68,6 +68,8 @@
 
 static constexpr const char* FEATURE_TELEPHONY_IMS = "android.hardware.telephony.ims";
 
+static constexpr const char* FEATURE_TELEPHONY_SATELLITE = "android.hardware.telephony.satellite";
+
 #define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
 #define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
 #define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
diff --git a/radio/aidl/vts/radio_satellite_indication.cpp b/radio/aidl/vts/radio_satellite_indication.cpp
new file mode 100644
index 0000000..13e4453
--- /dev/null
+++ b/radio/aidl/vts/radio_satellite_indication.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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 "radio_satellite_utils.h"
+
+RadioSatelliteIndication::RadioSatelliteIndication(RadioServiceTest& parent)
+    : parent_satellite(parent) {}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onPendingMessageCount(RadioIndicationType /*type*/,
+                                                                   int32_t /*count*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onNewMessages(
+        RadioIndicationType /*type*/, const std::vector<std::string>& /*messages*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onMessagesTransferComplete(
+        RadioIndicationType /*type*/, bool /*complete*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onSatellitePointingInfoChanged(
+        RadioIndicationType /*type*/, const PointingInfo& /*pointingInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onSatelliteModeChanged(RadioIndicationType /*type*/,
+                                                                    SatelliteMode /*mode*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onSatelliteRadioTechnologyChanged(
+        RadioIndicationType /*type*/, NTRadioTechnology /*technology*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteIndication::onProvisionStateChanged(
+        RadioIndicationType /*type*/, bool /*provisioned*/,
+        const std::vector<SatelliteFeature>& /*features*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_satellite_response.cpp b/radio/aidl/vts/radio_satellite_response.cpp
new file mode 100644
index 0000000..84d57b2
--- /dev/null
+++ b/radio/aidl/vts/radio_satellite_response.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 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 "radio_satellite_utils.h"
+
+RadioSatelliteResponse::RadioSatelliteResponse(RadioServiceTest& parent)
+    : parent_satellite(parent) {}
+
+ndk::ScopedAStatus RadioSatelliteResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getCapabilitiesResponse(
+        const RadioResponseInfo& info, const SatelliteCapabilities& /*capabilities*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::setPowerResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getPowerStateResponse(const RadioResponseInfo& info,
+                                                                 bool /*on*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::provisionServiceResponse(const RadioResponseInfo& info,
+                                                                    bool /*provisioned*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::addAllowedSatelliteContactsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::removeAllowedSatelliteContactsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::sendMessagesResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getPendingMessagesResponse(
+        const RadioResponseInfo& info, const std::vector<std::string>& /*messages*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getSatelliteModeResponse(
+        const RadioResponseInfo& info, SatelliteMode /*mode*/, NTRadioTechnology /*technology*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::setIndicationFilterResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::startSendingSatellitePointingInfoResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::stopSendingSatellitePointingInfoResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getMaxCharactersPerTextMessageResponse(
+        const RadioResponseInfo& info, int32_t /*charLimit*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSatelliteResponse::getTimeForNextSatelliteVisibilityResponse(
+        const RadioResponseInfo& info, int32_t /*timeInSeconds*/) {
+    rspInfo = info;
+    parent_satellite.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
\ No newline at end of file
diff --git a/radio/aidl/vts/radio_satellite_test.cpp b/radio/aidl/vts/radio_satellite_test.cpp
new file mode 100644
index 0000000..b646ef6
--- /dev/null
+++ b/radio/aidl/vts/radio_satellite_test.cpp
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android/binder_manager.h>
+
+#include "radio_satellite_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(((ret).isOk()))
+
+void RadioSatelliteTest::SetUp() {
+    RadioServiceTest::SetUp();
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the radio satellite tests due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    if (!deviceSupportsFeature(FEATURE_TELEPHONY_SATELLITE)) {
+        ALOGI("Skipping test because satellite is not supported in device.");
+        GTEST_SKIP();
+    }
+
+    satellite = IRadioSatellite::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, satellite.get());
+
+    rsp_satellite = ndk::SharedRefBase::make<RadioSatelliteResponse>(*this);
+    ASSERT_NE(nullptr, rsp_satellite.get());
+
+    ind_satellite = ndk::SharedRefBase::make<RadioSatelliteIndication>(*this);
+    ASSERT_NE(nullptr, ind_satellite.get());
+
+    satellite->setResponseFunctions(rsp_satellite, ind_satellite);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+/*
+ * Test IRadioSatellite.getCapabilities() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getCapabilities) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getCapabilities(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getCapabilities, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.setPower() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, setPower) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->setPower(serial, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("setPower, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.getPowerSate() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getPowerSate) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getPowerState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getPowerState, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.provisionService() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, provisionService) {
+    serial = GetRandomSerialNumber();
+    std::string imei = "imei";
+    std::string msisdn = "msisdn";
+    std::string imsi = "imsi";
+    const std::vector<SatelliteFeature> features{
+            SatelliteFeature::SOS_SMS, SatelliteFeature::EMERGENCY_SMS, SatelliteFeature::SMS};
+    ndk::ScopedAStatus res = satellite->provisionService(serial, imei, msisdn, imsi, features);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("provisionService, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(rsp_satellite->rspInfo.error,
+                                 {RadioError::NONE,
+                                  RadioError::ABORTED,
+                                  RadioError::ACCESS_BARRED,
+                                  RadioError::CANCELLED,
+                                  RadioError::FEATURE_NOT_SUPPORTED,
+                                  RadioError::INTERNAL_ERR,
+                                  RadioError::INVALID_ARGUMENTS,
+                                  RadioError::INVALID_MODEM_STATE,
+                                  RadioError::INVALID_SIM_STATE,
+                                  RadioError::INVALID_STATE,
+                                  RadioError::MODEM_ERR,
+                                  RadioError::MODEM_INCOMPATIBLE,
+                                  RadioError::NETWORK_ERR,
+                                  RadioError::NETWORK_NOT_READY,
+                                  RadioError::NETWORK_REJECT,
+                                  RadioError::NETWORK_TIMEOUT,
+                                  RadioError::NO_MEMORY,
+                                  RadioError::NO_NETWORK_FOUND,
+                                  RadioError::NO_RESOURCES,
+                                  RadioError::NO_SATELLITE_SIGNAL,
+                                  RadioError::NO_SUBSCRIPTION,
+                                  RadioError::OPERATION_NOT_ALLOWED,
+                                  RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::RADIO_TECHNOLOGY_NOT_SUPPORTED,
+                                  RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::REQUEST_RATE_LIMITED,
+                                  RadioError::SIM_ABSENT,
+                                  RadioError::SIM_BUSY,
+                                  RadioError::SIM_ERR,
+                                  RadioError::SIM_FULL,
+                                  RadioError::SUBSCRIBER_NOT_AUTHORIZED,
+                                  RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.addAllowedSatelliteContacts() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, addAllowedSatelliteContacts) {
+    serial = GetRandomSerialNumber();
+    const std::vector<std::string> contacts = {"contact 1", "contact 2"};
+    ndk::ScopedAStatus res = satellite->addAllowedSatelliteContacts(serial, contacts);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("addAllowedSatelliteContacts, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(rsp_satellite->rspInfo.error,
+                                 {RadioError::NONE,
+                                  RadioError::ABORTED,
+                                  RadioError::ACCESS_BARRED,
+                                  RadioError::CANCELLED,
+                                  RadioError::INTERNAL_ERR,
+                                  RadioError::INVALID_ARGUMENTS,
+                                  RadioError::INVALID_CONTACT,
+                                  RadioError::INVALID_MODEM_STATE,
+                                  RadioError::INVALID_SIM_STATE,
+                                  RadioError::INVALID_STATE,
+                                  RadioError::MODEM_ERR,
+                                  RadioError::NETWORK_ERR,
+                                  RadioError::NETWORK_NOT_READY,
+                                  RadioError::NOT_SUFFICIENT_ACCOUNT_BALANCE,
+                                  RadioError::OPERATION_NOT_ALLOWED,
+                                  RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::REQUEST_RATE_LIMITED,
+                                  RadioError::SIM_ABSENT,
+                                  RadioError::SIM_BUSY,
+                                  RadioError::SIM_ERR,
+                                  RadioError::SIM_FULL,
+                                  RadioError::SYSTEM_ERR,
+                                  RadioError::UNIDENTIFIED_SUBSCRIBER}));
+}
+
+/*
+ * Test IRadioSatellite.removeAllowedSatelliteContacts() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, removeAllowedSatelliteContacts) {
+    serial = GetRandomSerialNumber();
+    const std::vector<std::string> contacts = {"contact 1", "contact 2"};
+    ndk::ScopedAStatus res = satellite->removeAllowedSatelliteContacts(serial, contacts);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("removeAllowedSatelliteContacts, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(rsp_satellite->rspInfo.error,
+                                 {RadioError::NONE,
+                                  RadioError::ABORTED,
+                                  RadioError::ACCESS_BARRED,
+                                  RadioError::CANCELLED,
+                                  RadioError::INTERNAL_ERR,
+                                  RadioError::INVALID_ARGUMENTS,
+                                  RadioError::INVALID_CONTACT,
+                                  RadioError::INVALID_MODEM_STATE,
+                                  RadioError::INVALID_SIM_STATE,
+                                  RadioError::INVALID_STATE,
+                                  RadioError::MODEM_ERR,
+                                  RadioError::NETWORK_ERR,
+                                  RadioError::NETWORK_NOT_READY,
+                                  RadioError::NETWORK_REJECT,
+                                  RadioError::NETWORK_TIMEOUT,
+                                  RadioError::NO_MEMORY,
+                                  RadioError::NO_NETWORK_FOUND,
+                                  RadioError::NO_RESOURCES,
+                                  RadioError::NO_SATELLITE_SIGNAL,
+                                  RadioError::NO_SUBSCRIPTION,
+                                  RadioError::NOT_SUFFICIENT_ACCOUNT_BALANCE,
+                                  RadioError::OPERATION_NOT_ALLOWED,
+                                  RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::REQUEST_RATE_LIMITED,
+                                  RadioError::SIM_ABSENT,
+                                  RadioError::SIM_BUSY,
+                                  RadioError::SIM_ERR,
+                                  RadioError::SIM_FULL,
+                                  RadioError::SYSTEM_ERR,
+                                  RadioError::UNIDENTIFIED_SUBSCRIBER}));
+}
+
+/*
+ * Test IRadioSatellite.sendMessages() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, sendMessages) {
+    serial = GetRandomSerialNumber();
+    const std::vector<std::string> messages = {"message 1", "message 2"};
+    std::string destination = "0123456789";
+    ndk::ScopedAStatus res = satellite->sendMessages(serial, messages, destination, 1.0, 2.0);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("sendMessages, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(rsp_satellite->rspInfo.error,
+                                 {RadioError::NONE,
+                                  RadioError::ABORTED,
+                                  RadioError::ACCESS_BARRED,
+                                  RadioError::BLOCKED_DUE_TO_CALL,
+                                  RadioError::CANCELLED,
+                                  RadioError::ENCODING_ERR,
+                                  RadioError::ENCODING_NOT_SUPPORTED,
+                                  RadioError::INTERNAL_ERR,
+                                  RadioError::INVALID_ARGUMENTS,
+                                  RadioError::INVALID_MODEM_STATE,
+                                  RadioError::INVALID_SIM_STATE,
+                                  RadioError::INVALID_SMS_FORMAT,
+                                  RadioError::INVALID_STATE,
+                                  RadioError::MODEM_ERR,
+                                  RadioError::NETWORK_ERR,
+                                  RadioError::NETWORK_NOT_READY,
+                                  RadioError::NETWORK_REJECT,
+                                  RadioError::NETWORK_TIMEOUT,
+                                  RadioError::NO_MEMORY,
+                                  RadioError::NO_NETWORK_FOUND,
+                                  RadioError::NO_RESOURCES,
+                                  RadioError::NO_SMS_TO_ACK,
+                                  RadioError::NO_SATELLITE_SIGNAL,
+                                  RadioError::NO_SUBSCRIPTION,
+                                  RadioError::NOT_SUFFICIENT_ACCOUNT_BALANCE,
+                                  RadioError::OPERATION_NOT_ALLOWED,
+                                  RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::REQUEST_RATE_LIMITED,
+                                  RadioError::SIM_ABSENT,
+                                  RadioError::SIM_BUSY,
+                                  RadioError::SIM_ERR,
+                                  RadioError::SIM_FULL,
+                                  RadioError::SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED,
+                                  RadioError::SMS_SEND_FAIL_RETRY,
+                                  RadioError::SYSTEM_ERR,
+                                  RadioError::SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL,
+                                  RadioError::UNIDENTIFIED_SUBSCRIBER}));
+}
+
+/*
+ * Test IRadioSatellite.getPendingMessages() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getPendingMessages) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getPendingMessages(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getPendingMessages, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(rsp_satellite->rspInfo.error,
+                                 {RadioError::NONE,
+                                  RadioError::ABORTED,
+                                  RadioError::ACCESS_BARRED,
+                                  RadioError::BLOCKED_DUE_TO_CALL,
+                                  RadioError::CANCELLED,
+                                  RadioError::ENCODING_ERR,
+                                  RadioError::ENCODING_NOT_SUPPORTED,
+                                  RadioError::INTERNAL_ERR,
+                                  RadioError::INVALID_ARGUMENTS,
+                                  RadioError::INVALID_MODEM_STATE,
+                                  RadioError::INVALID_SIM_STATE,
+                                  RadioError::INVALID_SMS_FORMAT,
+                                  RadioError::INVALID_STATE,
+                                  RadioError::MODEM_ERR,
+                                  RadioError::NETWORK_ERR,
+                                  RadioError::NETWORK_NOT_READY,
+                                  RadioError::NETWORK_REJECT,
+                                  RadioError::NETWORK_TIMEOUT,
+                                  RadioError::NO_MEMORY,
+                                  RadioError::NO_NETWORK_FOUND,
+                                  RadioError::NO_RESOURCES,
+                                  RadioError::NO_SMS_TO_ACK,
+                                  RadioError::NO_SATELLITE_SIGNAL,
+                                  RadioError::NO_SUBSCRIPTION,
+                                  RadioError::NOT_SUFFICIENT_ACCOUNT_BALANCE,
+                                  RadioError::OPERATION_NOT_ALLOWED,
+                                  RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::REQUEST_RATE_LIMITED,
+                                  RadioError::SIM_ABSENT,
+                                  RadioError::SIM_BUSY,
+                                  RadioError::SIM_ERR,
+                                  RadioError::SIM_FULL,
+                                  RadioError::SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED,
+                                  RadioError::SYSTEM_ERR,
+                                  RadioError::SWITCHED_FROM_SATELLITE_TO_TERRESTRIAL}));
+}
+
+/*
+ * Test IRadioSatellite.getSatelliteMode() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getSatelliteMode) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getSatelliteMode(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getSatelliteMode, rspInfo.error = %s\n", toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.setIndicationFilter() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, setIndicationFilter) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->setIndicationFilter(serial, 0);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("setIndicationFilter, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.startSendingSatellitePointingInfo() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, startSendingSatellitePointingInfo) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->startSendingSatellitePointingInfo(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("startSendingSatellitePointingInfo, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.stopSatelliteLocationUpdate() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, stopSatelliteLocationUpdate) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->stopSendingSatellitePointingInfo(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("stopSendingSatellitePointingInfo, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.getMaxCharactersPerTextMessage() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getMaxCharactersPerTextMessage) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getMaxCharactersPerTextMessage(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getMaxCharactersPerTextMessage, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
+
+/*
+ * Test IRadioSatellite.getTimeForNextSatelliteVisibility() for the response returned.
+ */
+TEST_P(RadioSatelliteTest, getTimeForNextSatelliteVisibility) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = satellite->getTimeForNextSatelliteVisibility(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, rsp_satellite->rspInfo.type);
+    EXPECT_EQ(serial, rsp_satellite->rspInfo.serial);
+
+    ALOGI("getTimeForNextSatelliteVisibility, rspInfo.error = %s\n",
+          toString(rsp_satellite->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            rsp_satellite->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_SIM_STATE,
+             RadioError::INVALID_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::NO_RESOURCES, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::REQUEST_RATE_LIMITED,
+             RadioError::SYSTEM_ERR}));
+}
diff --git a/radio/aidl/vts/radio_satellite_utils.h b/radio/aidl/vts/radio_satellite_utils.h
new file mode 100644
index 0000000..a0fdc7e
--- /dev/null
+++ b/radio/aidl/vts/radio_satellite_utils.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/satellite/BnRadioSatelliteIndication.h>
+#include <aidl/android/hardware/radio/satellite/BnRadioSatelliteResponse.h>
+#include <aidl/android/hardware/radio/satellite/IRadioSatellite.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::satellite;
+
+class RadioSatelliteTest;
+
+/* Callback class for Satellite response */
+class RadioSatelliteResponse : public BnRadioSatelliteResponse {
+  protected:
+    RadioServiceTest& parent_satellite;
+
+  public:
+    RadioSatelliteResponse(RadioServiceTest& parent_satellite);
+    virtual ~RadioSatelliteResponse() = default;
+
+    RadioResponseInfo rspInfo;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus getCapabilitiesResponse(
+            const RadioResponseInfo& info, const SatelliteCapabilities& capabilities) override;
+
+    virtual ndk::ScopedAStatus setPowerResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getPowerStateResponse(const RadioResponseInfo& info,
+                                                     bool on) override;
+
+    virtual ndk::ScopedAStatus provisionServiceResponse(const RadioResponseInfo& info,
+                                                        bool provisioned) override;
+
+    virtual ndk::ScopedAStatus addAllowedSatelliteContactsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus removeAllowedSatelliteContactsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendMessagesResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getPendingMessagesResponse(
+            const RadioResponseInfo& info, const std::vector<std::string>& /*messages*/) override;
+
+    virtual ndk::ScopedAStatus getSatelliteModeResponse(
+            const RadioResponseInfo& info, SatelliteMode mode,
+            satellite::NTRadioTechnology technology) override;
+
+    virtual ndk::ScopedAStatus setIndicationFilterResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startSendingSatellitePointingInfoResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus stopSendingSatellitePointingInfoResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getMaxCharactersPerTextMessageResponse(const RadioResponseInfo& info,
+                                                                      int32_t charLimit) override;
+
+    virtual ndk::ScopedAStatus getTimeForNextSatelliteVisibilityResponse(
+            const RadioResponseInfo& info, int32_t timeInSeconds) override;
+};
+
+/* Callback class for Satellite indication */
+class RadioSatelliteIndication : public BnRadioSatelliteIndication {
+  protected:
+    RadioServiceTest& parent_satellite;
+
+  public:
+    RadioSatelliteIndication(RadioServiceTest& parent_satellite);
+    virtual ~RadioSatelliteIndication() = default;
+
+    virtual ndk::ScopedAStatus onPendingMessageCount(RadioIndicationType type,
+                                                     int32_t count) override;
+
+    virtual ndk::ScopedAStatus onNewMessages(RadioIndicationType type,
+                                             const std::vector<std::string>& messages) override;
+
+    virtual ndk::ScopedAStatus onMessagesTransferComplete(RadioIndicationType type,
+                                                          bool complete) override;
+
+    virtual ndk::ScopedAStatus onSatellitePointingInfoChanged(
+            RadioIndicationType type, const PointingInfo& pointingInfo) override;
+
+    virtual ndk::ScopedAStatus onSatelliteModeChanged(RadioIndicationType type,
+                                                      SatelliteMode mode) override;
+
+    virtual ndk::ScopedAStatus onSatelliteRadioTechnologyChanged(
+            RadioIndicationType type, satellite::NTRadioTechnology technology) override;
+
+    virtual ndk::ScopedAStatus onProvisionStateChanged(
+            RadioIndicationType type, bool provisioned,
+            const std::vector<SatelliteFeature>& features) override;
+};
+
+// The main test class for AIDL Satellite.
+class RadioSatelliteTest : public RadioServiceTest {
+  public:
+    void SetUp() override;
+
+    /* Radio Satellite service handle */
+    std::shared_ptr<IRadioSatellite> satellite;
+    /* Radio Satellite response handle */
+    std::shared_ptr<RadioSatelliteResponse> rsp_satellite;
+    /* Radio Satellite indication handle */
+    std::shared_ptr<RadioSatelliteIndication> ind_satellite;
+};
diff --git a/radio/config/1.0/vts/functional/OWNERS b/radio/config/1.0/vts/functional/OWNERS
deleted file mode 100644
index badd6d7..0000000
--- a/radio/config/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 20868
-jminjie@google.com
-sarahchin@google.com
-amitmahajan@google.com
-shuoq@google.com
-jackyu@google.com
diff --git a/radio/config/1.1/vts/OWNERS b/radio/config/1.1/vts/OWNERS
deleted file mode 100644
index 4109967..0000000
--- a/radio/config/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include /radio/1.0/vts/OWNERS
diff --git a/radio/config/1.2/vts/OWNERS b/radio/config/1.2/vts/OWNERS
deleted file mode 100644
index 4109967..0000000
--- a/radio/config/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-include /radio/1.0/vts/OWNERS
diff --git a/renderscript/1.0/vts/functional/OWNERS b/renderscript/OWNERS
similarity index 84%
rename from renderscript/1.0/vts/functional/OWNERS
rename to renderscript/OWNERS
index d785790..443ebff 100644
--- a/renderscript/1.0/vts/functional/OWNERS
+++ b/renderscript/OWNERS
@@ -1,6 +1,6 @@
 # Bug component: 43047
+
 butlermichael@google.com
 dgross@google.com
-jeanluc@google.com
 miaowang@google.com
 xusongw@google.com
diff --git a/security/README.md b/security/README.md
new file mode 100644
index 0000000..c5b5ba8
--- /dev/null
+++ b/security/README.md
@@ -0,0 +1,109 @@
+# Security-Related HALs
+
+The `security/` subdirectory holds various security-related HALs.  (The final two sections of this
+document also describe security-related HALs that are in other places under `hardware/interfaces/`.)
+
+The most significant HAL is KeyMint (**`IKeyMintDevice`** in the
+`hardware/interfaces/security/keymint/` directory), which allows access to cryptographic
+functionality where the key material is restricted to a secure environment.  This functionality is
+used by Android system services, and is also made available to apps via Android Keystore.
+
+A KeyMint implementation (or an implementation of its predecessor, Keymaster) that runs in an
+isolated execution environment (e.g. ARM TrustZone) is required for most Android devices; see [CDD
+9.11](https://source.android.com/docs/compatibility/13/android-13-cdd#911_keys_and_credentials).
+
+A device may optionally also support a second KeyMint instance, running in a dedicated secure
+processor; this is known as StrongBox ([CDD
+9.11.2](https://source.android.com/docs/compatibility/13/android-13-cdd#9112_strongbox)).
+
+Two specific features of KeyMint are worth highlighting, as they have an impact on the other
+security-related HALs:
+
+- KeyMint supports keys that can only be used when the operation is authenticated by the user,
+  either by their lock screen knowledge factor (LSKF, e.g. PIN or pattern) or by a strong biometric
+  (e.g. fingerprint).
+- KeyMint supports *attestation* of public keys: when an asymmetric keypair is created, the secure
+  environment produces a chain of signed certificates:
+  - starting from a trusted root certificate
+  - terminating in a leaf certificate that holds the public key; this leaf certificate may also
+    describe the state of the device and the policies attached to the key.
+
+## Authentication Verification
+
+User authentication must also take place in a secure environment (see the final section below), but
+the results of that authentication are communicated to KeyMint via Android.  As such, the
+authentication result (a *hardware auth token*) is signed with a per-boot shared HMAC key known only
+to the secure components, so that it's authenticity can be verified.
+
+If an authenticator, for example GateKeeper (described by the **`IGatekeeper`** HAL in
+`hardware/interfaces/gatekeeper/`), is co-located in the same secure environment as KeyMint, it can
+use a local, vendor-specific, method to communicate the shared HMAC key.
+
+However, if the authenticator is in a different environment than the KeyMint instance then a local
+communication mechanism may not be possible.  For example, a StrongBox KeyMint instance running in a
+separate secure processor may not have a communication channel with a TEE on the main processor.
+
+To allow for this, the **`ISharedSecret`** HAL (in `hardware/interfaces/security/sharedsecret`)
+describes an N-party shared key agreement protocol for per-boot derivation of the shared HMAC key,
+based on a pre-provisioned shared secret.  This HAL can be implemented by any security component
+&ndash; whether KeyMint instance or authenticator &ndash; that needs access to the shared HMAC key.
+
+User authentication operations are also timestamped, but a StrongBox KeyMint instance may not have
+access to a secure time source that is aligned with the authenticator's time source.
+
+To allow for this, the **`ISecureClock`** HAL (in `hardware/interfaces/secureclock`) describes a
+challenge-based timestamp authentication protocol.  This HAL is optional; it need only be
+implemented if there is a KeyMint instance without a secure source of time.
+
+## Attestation Key Provisioning
+
+As noted above, key generation may also generate an attestation certificate chain, which requires
+that the secure environment have access to a signing key which in turn chains back to the Google
+root.
+
+Historically these signing keys were created by Google and provided to vendors for installation in
+batches of devices (to prevent their use as unique device identifiers).  However, this mechanism had
+significant disadvantages, as it required secure handling of key material and only allowed for
+coarse-grained revocation.
+
+The remote key provisioning HAL (**`IRemotelyProvisionedComponent`** in
+`hardware/interfaces/security/rkp/`) provides a mechanism whereby signing certificates for
+attestation can be retrieved at runtime from Google servers based on pre-registered device identity
+information.  This mechanism is used to provision certificates for KeyMint's signing keys, but is
+not restricted to that purpose; it can also be used in other scenarios where keys need to be
+provisioned (for example, for [Widevine](https://developers.google.com/widevine/drm/overview)).
+
+## Keymaster
+
+The Keymaster HAL (**`IKeymasterDevice`** in `hardware/interfaces/keymaster/`) is the historical
+ancestor of many of the HALs here (and may still be present on older devices).  Its functionality is
+effectively the union of the following current HALs:
+
+- **`IKeyMintDevice`**
+- **`ISharedSecret`**
+- **`ISecureClock`**
+
+## Related Authentication HALs
+
+Authentication of users needs to happen in a secure environment, using vendor-specific
+functionality, and so involves the use of one of the following HALs (all of which are outside the
+`security/` subdirectory).
+
+- The **`IGatekeeper`** HAL (in `hardware/interfaces/gatekeeper/`) provides user authentication
+  functionality based on the user's lock-screen knowledge factor (LSKF), including throttling
+  behaviour to prevent attacks.  Authentication tokens produced by this HAL are consumed by KeyMint,
+  validated using the shared HMAC key described above.
+  - The optional **`IWeaver`** HAL (in `hardware/interfaces/weaver`) improves the security of LSKF
+    authentication by converting the user's LSKF into a *synthetic password* via hashing and
+    stretching. This is required to be implemented on a separate secure element, which prevents
+    offline attacks on Gatekeeper storage. Note that Weaver does not directly interact with KeyMint;
+    the synthetic password is fed into Gatekeeper in place of the plain user password, and then
+    Gatekeeper interacts with KeyMint as normal.
+- The **`IFingerprint`** and **`IFace`** HAL definitions (under `hardware/interfaces/biometrics/`)
+  allow access to biometric authentication functionality that is implemented in a secure
+  environment.  Authentication tokens produced by these HALs are consumed by KeyMint, validated
+  using the shared HMAC key described above.
+- The optional **`IConfirmationUI`** HAL (in `hardware/interfaces/confirmationui`) supports
+  functionality where the user confirms that they have seen a specific message in a secure manner.
+  Confirmation tokens produced by this HAL are consumed by KeyMint, validated using the shared HMAC
+  key described above.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 82c8a0d..a4fab55 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -126,8 +126,8 @@
      *
      *   o The HMAC field must validate correctly.
      *
-     *   o The challenge field in the auth token must contain the challenge value contained in the
-     *     BeginResult returned from IKeyMintDevice::begin().
+     *   o The challenge field in the timestamp token must contain the challenge value contained in
+     *     the BeginResult returned from IKeyMintDevice::begin().
      *
      * The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
      * auth token to be valid, all of the following has to be true:
@@ -139,9 +139,6 @@
      *
      *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
      *
-     *   o The challenge field in the auth token must contain the challenge value contained in the
-     *     BeginResult returned from IKeyMintDevice::begin().
-     *
      *   o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
      *     than the provided secure timestamp.
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index d401247..36f0106 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -971,7 +971,9 @@
      * Tag::CERTIFICATE_NOT_BEFORE the beginning of the validity of the certificate in UNIX epoch
      * time in milliseconds.  This value is used when generating attestation or self signed
      * certificates.  ErrorCode::MISSING_NOT_BEFORE must be returned if this tag is not provided if
-     * this tag is not provided to generateKey or importKey.
+     * this tag is not provided to generateKey or importKey.  For importWrappedKey, there is no way
+     * to specify the value of this tag for the wrapped key, so a value of 0 must be used for
+     * certificate generation.
      */
     CERTIFICATE_NOT_BEFORE = TagType.DATE | 1008,
 
@@ -979,7 +981,8 @@
      * Tag::CERTIFICATE_NOT_AFTER the end of the validity of the certificate in UNIX epoch time in
      * milliseconds.  This value is used when generating attestation or self signed certificates.
      * ErrorCode::MISSING_NOT_AFTER must be returned if this tag is not provided to generateKey or
-     * importKey.
+     * importKey.  For importWrappedKey, there is no way to specify the value of this tag for the
+     * wrapped key, so a value of 253402300799000 is used for certificate generation.
      */
     CERTIFICATE_NOT_AFTER = TagType.DATE | 1009,
 
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index a4d0302..0568ae6 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,12 +1,12 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IKeyMintDevice/default</fqname>
     </hal>
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IRemotelyProvisionedComponent/default</fqname>
     </hal>
 </manifest>
diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp
index dc0c618..10cbf07 100644
--- a/security/keymint/aidl/default/service.cpp
+++ b/security/keymint/aidl/default/service.cpp
@@ -44,6 +44,8 @@
 }
 
 int main() {
+    // The global logger object required by keymaster's logging macros in keymaster/logger.h.
+    keymaster::SoftKeymasterLogger km_logger;
     // Zero threads seems like a useless pool, but below we'll join this thread to it, increasing
     // the pool size to 1.
     ABinderProcess_setThreadPoolMaxThreadCount(0);
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 6d289ec..4c46719 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -82,13 +82,36 @@
 
     string imei = ::android::base::Trim(out[0]);
     if (imei.compare("null") == 0) {
-        LOG(ERROR) << "Error in getting IMEI from Telephony service: value is null. Cmd: " << cmd;
+        LOG(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: " << cmd;
         return "";
     }
 
     return imei;
 }
 
+// Use `ro.product.<property>_for_attestation` property for attestation if it is present else
+// fallback to use `ro.product.vendor.<property>` if it is present else fallback to
+// `ro.product.<property>`. Similar logic can be seen in Java method `getVendorDeviceIdProperty`
+// in frameworks/base/core/java/android/os/Build.java.
+template <Tag tag>
+void add_attestation_id(AuthorizationSetBuilder* attestation_id_tags,
+                        TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
+    ::android::String8 prop_name =
+            ::android::String8::format("ro.product.%s_for_attestation", prop);
+    std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
+    } else {
+        prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
+        prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+        if (!prop_value.empty()) {
+            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
+        } else {
+            prop_name = ::android::String8::format("ro.product.%s", prop);
+            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
+        }
+    }
+}
 }  // namespace
 
 class AttestKeyTest : public KeyMintAidlTestBase {
@@ -120,6 +143,7 @@
                                             .SetDefaultValidity(),
                                     {} /* attestation signing key */, &attest_key.keyBlob,
                                     &attest_key_characteristics, &attest_key_cert_chain));
+        KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
 
         ASSERT_GT(attest_key_cert_chain.size(), 0);
         EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -132,7 +156,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -141,12 +165,13 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
+        KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
-        CheckedDeleteKey(&attested_key_blob);
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -163,7 +188,7 @@
          */
         attested_key_characteristics.resize(0);
         attested_key_cert_chain.resize(0);
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaEncryptionKey(2048, 65537)
                                       .Digest(Digest::NONE)
@@ -174,12 +199,13 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
+        KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
 
-        CheckedDeleteKey(&attested_key_blob);
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
 
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
                                               hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -197,7 +223,7 @@
         attested_key_characteristics.resize(0);
         attested_key_cert_chain.resize(0);
         uint64_t timestamp = 1619621648000;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -207,6 +233,9 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
+        KeyBlobDeleter attested_deleter3(keymint_, attested_key_blob);
+
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
 
         // The returned key characteristics will include CREATION_DATETIME (checked below)
         // in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
@@ -214,9 +243,6 @@
         // any SecurityLevel::KEYSTORE characteristics).
         CheckCharacteristics(attested_key_blob, attested_key_characteristics);
 
-        CheckedDeleteKey(&attested_key_blob);
-        CheckedDeleteKey(&attest_key.keyBlob);
-
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
 
@@ -226,7 +252,7 @@
         EXPECT_TRUE(sw_enforced.Contains(TAG_CREATION_DATETIME, timestamp))
                 << "expected CREATION_TIMESTAMP in sw_enforced:" << sw_enforced
                 << " not in hw_enforced:" << hw_enforced;
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -308,6 +334,7 @@
         if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
     }
     ASSERT_EQ(ErrorCode::OK, result);
+    KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
 
     EXPECT_GT(attest_key_cert_chain.size(), 1);
     verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -315,7 +342,7 @@
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attest_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attest_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           attest_key_cert_chain[0].encodedCertificate));
 
@@ -333,7 +360,7 @@
     uint64_t serial_int2 = 255;
     vector<uint8_t> serial_blob2(build_serial_blob(serial_int2));
 
-    EXPECT_EQ(ErrorCode::OK,
+    ASSERT_EQ(ErrorCode::OK,
               GenerateKey(AuthorizationSetBuilder()
                                   .RsaSigningKey(2048, 65537)
                                   .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -344,13 +371,13 @@
                                   .SetDefaultValidity(),
                           attest_key, &attested_key_blob, &attested_key_characteristics,
                           &attested_key_cert_chain));
+    KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
-    CheckedDeleteKey(&attested_key_blob);
-    CheckedDeleteKey(&attest_key.keyBlob);
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
 
     AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
                                           SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
 
@@ -376,6 +403,7 @@
     const int chain_size = 6;
     vector<vector<uint8_t>> key_blob_list(chain_size);
     vector<vector<Certificate>> cert_chain_list(chain_size);
+    vector<KeyBlobDeleter> deleters;
 
     for (int i = 0; i < chain_size; i++) {
         string sub = "attest key chaining ";
@@ -412,11 +440,12 @@
             if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -437,10 +466,6 @@
         EXPECT_GT(cert_chain_list[i].size(), i + 1);
         verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
     }
-
-    for (int i = 0; i < chain_size; i++) {
-        CheckedDeleteKey(&key_blob_list[i]);
-    }
 }
 
 /*
@@ -453,6 +478,7 @@
     const int chain_size = 6;
     vector<vector<uint8_t>> key_blob_list(chain_size);
     vector<vector<Certificate>> cert_chain_list(chain_size);
+    vector<KeyBlobDeleter> deleters;
 
     for (int i = 0; i < chain_size; i++) {
         string sub = "Ec attest key chaining ";
@@ -489,11 +515,12 @@
             if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -514,10 +541,6 @@
         EXPECT_GT(cert_chain_list[i].size(), i + 1);
         verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
     }
-
-    for (int i = 0; i < chain_size; i++) {
-        CheckedDeleteKey(&key_blob_list[i]);
-    }
 }
 
 /*
@@ -557,6 +580,7 @@
     const int chain_size = 6;
     vector<vector<uint8_t>> key_blob_list(chain_size);
     vector<vector<Certificate>> cert_chain_list(chain_size);
+    vector<KeyBlobDeleter> deleters;
 
     for (int i = 0; i < chain_size; i++) {
         string sub = "Alt attest key chaining ";
@@ -607,11 +631,12 @@
             if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        deleters.push_back(KeyBlobDeleter(keymint_, key_blob_list[i]));
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -632,10 +657,6 @@
         EXPECT_GT(cert_chain_list[i].size(), i + 1);
         verify_subject_and_serial(cert_chain_list[i][0], serial_int, subject, false);
     }
-
-    for (int i = 0; i < chain_size; i++) {
-        CheckedDeleteKey(&key_blob_list[i]);
-    }
 }
 
 TEST_P(AttestKeyTest, MissingChallenge) {
@@ -653,6 +674,7 @@
                                             .SetDefaultValidity(),
                                     {} /* attestation signing key */, &attest_key.keyBlob,
                                     &attest_key_characteristics, &attest_key_cert_chain));
+        KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
 
         EXPECT_EQ(attest_key_cert_chain.size(), 1);
         EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain)) << "Failed on size " << size;
@@ -664,7 +686,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+        ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -673,7 +695,7 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
-        EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+        ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -681,8 +703,6 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
-
-        CheckedDeleteKey(&attest_key.keyBlob);
     }
 }
 
@@ -700,6 +720,7 @@
                         AuthorizationSetBuilder().EcdsaKey(curve).AttestKey().SetDefaultValidity(),
                         {} /* attestation signing key */, &attest_key.keyBlob,
                         &attest_key_characteristics, &attest_key_cert_chain));
+        KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
 
         ASSERT_GT(attest_key_cert_chain.size(), 0);
         EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -712,7 +733,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -721,13 +742,13 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
+        KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
         ASSERT_GT(attested_key_cert_chain.size(), 0);
-        CheckedDeleteKey(&attested_key_blob);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -743,7 +764,7 @@
         /*
          * Use attestation key to sign EC key
          */
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -752,14 +773,13 @@
                                       .SetDefaultValidity(),
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
+        KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
 
         ASSERT_GT(attested_key_cert_chain.size(), 0);
-        CheckedDeleteKey(&attested_key_blob);
-        CheckedDeleteKey(&attest_key.keyBlob);
 
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -797,7 +817,7 @@
     vector<uint8_t> attested_key_blob;
     vector<KeyCharacteristics> attested_key_characteristics;
     vector<Certificate> attested_key_cert_chain;
-    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
               GenerateKey(AuthorizationSetBuilder()
                                   .EcdsaSigningKey(EcCurve::P_256)
                                   .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -809,11 +829,6 @@
 }
 
 TEST_P(AttestKeyTest, EcdsaAttestationID) {
-    if (is_gsi_image()) {
-        // GSI sets up a standard set of device identifiers that may not match
-        // the device identifiers held by the device.
-        GTEST_SKIP() << "Test not applicable under GSI";
-    }
     // Create attestation key.
     AttestationKey attest_key;
     vector<KeyCharacteristics> attest_key_characteristics;
@@ -825,6 +840,7 @@
                                         .SetDefaultValidity(),
                                 {} /* attestation signing key */, &attest_key.keyBlob,
                                 &attest_key_characteristics, &attest_key_cert_chain));
+    KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
     attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
     ASSERT_GT(attest_key_cert_chain.size(), 0);
     EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -832,39 +848,12 @@
 
     // Collection of valid attestation ID tags.
     auto attestation_id_tags = AuthorizationSetBuilder();
-    // Use ro.product.brand_for_attestation property for attestation if it is present else fallback
-    // to ro.product.brand
-    std::string prop_value =
-            ::android::base::GetProperty("ro.product.brand_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND,
-                          "ro.product.brand_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
-    }
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
-    // Use ro.product.name_for_attestation property for attestation if it is present else fallback
-    // to ro.product.name
-    prop_value = ::android::base::GetProperty("ro.product.name_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT,
-                          "ro.product.name_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
-    }
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "brand");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "device");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "name");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "model");
     add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
-                      "ro.product.manufacturer");
-    // Use ro.product.model_for_attestation property for attestation if it is present else fallback
-    // to ro.product.model
-    prop_value =
-            ::android::base::GetProperty("ro.product.model_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL,
-                          "ro.product.model_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
-    }
 
     string imei = get_imei(0);
     if (!imei.empty()) {
@@ -891,8 +880,8 @@
         }
 
         ASSERT_EQ(result, ErrorCode::OK);
-
-        CheckedDeleteKey(&attested_key_blob);
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
+        KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -902,11 +891,10 @@
         // attestation extension should contain them, so make sure the extra tag is added.
         hw_enforced.push_back(tag);
 
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                               hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
     }
-    CheckedDeleteKey(&attest_key.keyBlob);
 }
 
 TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
@@ -921,6 +909,7 @@
                                         .SetDefaultValidity(),
                                 {} /* attestation signing key */, &attest_key.keyBlob,
                                 &attest_key_characteristics, &attest_key_cert_chain));
+    KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
     attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
     ASSERT_GT(attest_key_cert_chain.size(), 0);
     EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -939,7 +928,9 @@
                     .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
 
     if (isSecondImeiIdAttestationRequired()) {
-        attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-second-imei");
+        // Note: the invalid value here is < 16 bytes long to avoid triggering any implementation
+        // checks on valid IMEI lengths.
+        attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-imei2");
     }
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -963,16 +954,9 @@
                                   &attested_key_characteristics, &attested_key_cert_chain);
         device_id_attestation_check_acceptable_error(invalid_tag.tag, result);
     }
-    CheckedDeleteKey(&attest_key.keyBlob);
 }
 
 TEST_P(AttestKeyTest, SecondIMEIAttestationIDSuccess) {
-    if (is_gsi_image()) {
-        // GSI sets up a standard set of device identifiers that may not match
-        // the device identifiers held by the device.
-        GTEST_SKIP() << "Test not applicable under GSI";
-    }
-
     // Skip the test if there is no second IMEI exists.
     string second_imei = get_imei(1);
     if (second_imei.empty()) {
@@ -994,6 +978,7 @@
                                         .SetDefaultValidity(),
                                 {} /* attestation signing key */, &attest_key.keyBlob,
                                 &attest_key_characteristics, &attest_key_cert_chain));
+    KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
     attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
     EXPECT_EQ(attest_key_cert_chain.size(), 1);
     EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
@@ -1022,8 +1007,8 @@
     }
 
     ASSERT_EQ(result, ErrorCode::OK);
-
-    CheckedDeleteKey(&attested_key_blob);
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
+    KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -1035,20 +1020,12 @@
     KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, imei_blob);
     hw_enforced.push_back(imei_tag);
 
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                           hw_enforced, SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
-
-    CheckedDeleteKey(&attest_key.keyBlob);
 }
 
 TEST_P(AttestKeyTest, MultipleIMEIAttestationIDSuccess) {
-    if (is_gsi_image()) {
-        // GSI sets up a standard set of device identifiers that may not match
-        // the device identifiers held by the device.
-        GTEST_SKIP() << "Test not applicable under GSI";
-    }
-
     // Skip the test if there is no first IMEI exists.
     string imei = get_imei(0);
     if (imei.empty()) {
@@ -1076,6 +1053,7 @@
                                         .SetDefaultValidity(),
                                 {} /* attestation signing key */, &attest_key.keyBlob,
                                 &attest_key_characteristics, &attest_key_cert_chain));
+    KeyBlobDeleter attest_deleter(keymint_, attest_key.keyBlob);
     attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
     EXPECT_EQ(attest_key_cert_chain.size(), 1);
     EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
@@ -1101,8 +1079,8 @@
     }
 
     ASSERT_EQ(result, ErrorCode::OK);
-
-    CheckedDeleteKey(&attested_key_blob);
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
+    KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -1117,11 +1095,9 @@
     KeyParameter sec_imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, sec_imei_blob);
     hw_enforced.push_back(sec_imei_tag);
 
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                           hw_enforced, SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
-
-    CheckedDeleteKey(&attest_key.keyBlob);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
index 78c88f4..d5c6d2a 100644
--- a/security/keymint/aidl/vts/functional/AuthTest.cpp
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -93,17 +93,21 @@
     void TearDown() {
         if (gk_ == nullptr) return;
         gk_->deleteUser(uid_);
+        if (alt_uid_ != 0) {
+            gk_->deleteUser(alt_uid_);
+        }
     }
 
     bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
 
-    std::optional<GatekeeperEnrollResponse> doEnroll(const std::vector<uint8_t>& newPwd,
+    std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid,
+                                                     const std::vector<uint8_t>& newPwd,
                                                      const std::vector<uint8_t>& curHandle = {},
                                                      const std::vector<uint8_t>& curPwd = {}) {
         if (gk_ != nullptr) {
             while (true) {
                 GatekeeperEnrollResponse rsp;
-                Status status = gk_->enroll(uid_, curHandle, curPwd, newPwd, &rsp);
+                Status status = gk_->enroll(uid, curHandle, curPwd, newPwd, &rsp);
                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
                     sleep(1);
@@ -120,7 +124,7 @@
             while (true) {
                 HidlGatekeeperResponse rsp;
                 auto status = hidl_gk_->enroll(
-                        uid_, curHandle, curPwd, newPwd,
+                        uid, curHandle, curPwd, newPwd,
                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
                 if (!status.isOk()) {
                     GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
@@ -155,20 +159,23 @@
         }
     }
 
-    std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd,
+    std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid, const string& newPwd,
                                                      const std::vector<uint8_t>& curHandle = {},
                                                      const string& curPwd = {}) {
-        return doEnroll(std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
+        return doEnroll(uid, std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
                         std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
     }
+    std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd) {
+        return doEnroll(uid_, newPwd);
+    }
 
-    std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
+    std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
                                               const std::vector<uint8_t>& handle,
                                               const std::vector<uint8_t>& pwd) {
         if (gk_ != nullptr) {
             while (true) {
                 GatekeeperVerifyResponse rsp;
-                Status status = gk_->verify(uid_, challenge, handle, pwd, &rsp);
+                Status status = gk_->verify(uid, challenge, handle, pwd, &rsp);
                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
                     sleep(1);
@@ -185,7 +192,7 @@
             while (true) {
                 HidlGatekeeperResponse rsp;
                 auto status = hidl_gk_->verify(
-                        uid_, challenge, handle, pwd,
+                        uid, challenge, handle, pwd,
                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
                 if (!status.isOk()) {
                     GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
@@ -220,10 +227,15 @@
             return std::nullopt;
         }
     }
+    std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
+                                              const std::vector<uint8_t>& handle,
+                                              const string& pwd) {
+        return doVerify(uid, challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+    }
     std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
                                               const std::vector<uint8_t>& handle,
                                               const string& pwd) {
-        return doVerify(challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+        return doVerify(uid_, challenge, handle, pwd);
     }
 
     // Variants of the base class methods but with authentication information included.
@@ -268,6 +280,13 @@
         return plaintext;
     }
 
+    string SignMessage(const vector<uint8_t>& key_blob, const string& message,
+                       const AuthorizationSet& in_params, AuthorizationSet* out_params,
+                       const HardwareAuthToken& hat) {
+        SCOPED_TRACE("SignMessage");
+        return ProcessMessage(key_blob, KeyPurpose::SIGN, message, in_params, out_params, hat);
+    }
+
   protected:
     std::shared_ptr<IGatekeeper> gk_;
     sp<IHidlGatekeeper> hidl_gk_;
@@ -275,6 +294,8 @@
     string password_;
     uint32_t uid_;
     int64_t sid_;
+    uint32_t alt_uid_;
+    int64_t alt_sid_;
     std::vector<uint8_t> handle_;
 };
 
@@ -347,6 +368,126 @@
     }
 }
 
+// Test use of a key that requires user-authentication within recent history, but where
+// the `TimestampToken` provided to the device is unrelated to the in-progress operation.
+TEST_P(AuthTest, TimeoutAuthenticationIncorrectTimestampToken) {
+    if (!GatekeeperAvailable()) {
+        GTEST_SKIP() << "No Gatekeeper available";
+    }
+    if (!timestamp_token_required_) {
+        GTEST_SKIP() << "Test only applies to devices with no secure clock";
+    }
+    if (clock_ == nullptr) {
+        GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+    }
+
+    // Create an AES key that requires authentication within the last 3 seconds.
+    const uint32_t timeout_secs = 3;
+    auto builder = AuthorizationSetBuilder()
+                           .AesEncryptionKey(256)
+                           .BlockMode(BlockMode::ECB)
+                           .Padding(PaddingMode::PKCS7)
+                           .Authorization(TAG_USER_SECURE_ID, sid_)
+                           .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
+                           .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+    vector<uint8_t> keyblob;
+    vector<KeyCharacteristics> key_characteristics;
+    vector<Certificate> cert_chain;
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+    // Verify to get a HAT, arbitrary challenge.
+    const uint64_t challenge = 42;
+    const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
+    ASSERT_TRUE(hat.has_value());
+    EXPECT_EQ(hat->userId, sid_);
+
+    // KeyMint implementation has no clock, so only detects timeout via timestamp token provided
+    // on update()/finish().  However, for this test we ensure that that the timestamp token has a
+    // *different* challenge value.
+    const string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    AuthorizationSet out_params;
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
+
+    secureclock::TimeStampToken time_token;
+    EXPECT_EQ(ErrorCode::OK,
+              GetReturnErrorCode(clock_->generateTimeStamp(challenge_ + 1, &time_token)));
+    string output;
+    EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+              Finish(message, {} /* signature */, &output, hat, time_token));
+}
+
+// Test use of a key with multiple USER_SECURE_ID values.  For variety, use an EC signing key
+// generated with attestation.
+TEST_P(AuthTest, TimeoutAuthenticationMultiSid) {
+    if (!GatekeeperAvailable()) {
+        GTEST_SKIP() << "No Gatekeeper available";
+    }
+    if (timestamp_token_required_ && clock_ == nullptr) {
+        GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+    }
+
+    // Enroll a password for a second user.
+    alt_uid_ = 20001;
+    const string alt_password = "correcthorsebatterystaple2";
+    std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+    ASSERT_TRUE(rsp.has_value());
+    alt_sid_ = rsp->secureUserId;
+    const std::vector<uint8_t> alt_handle = rsp->data;
+
+    // Create an attested EC key that requires authentication within the last 3 seconds from either
+    // secure ID. Also allow any authenticator type.
+    const uint32_t timeout_secs = 3;
+    auto builder = AuthorizationSetBuilder()
+                           .EcdsaSigningKey(EcCurve::P_256)
+                           .Digest(Digest::NONE)
+                           .Digest(Digest::SHA_2_256)
+                           .SetDefaultValidity()
+                           .AttestationChallenge("challenge")
+                           .AttestationApplicationId("app_id")
+                           .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+                           .Authorization(TAG_USER_SECURE_ID, sid_)
+                           .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY)
+                           .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+    vector<uint8_t> keyblob;
+    vector<KeyCharacteristics> key_characteristics;
+    vector<Certificate> cert_chain;
+    auto result = GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain);
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(AuthorizationSetBuilder()
+                                                                .EcdsaKey(EcCurve::P_256)
+                                                                .AttestKey()
+                                                                .SetDefaultValidity(),
+                                                        builder, &keyblob, &key_characteristics,
+                                                        &cert_chain);
+        }
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
+
+    // Verify first user to get a HAT that should work.
+    const uint64_t challenge = 42;
+    const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge, handle_, password_);
+    ASSERT_TRUE(hat.has_value());
+    EXPECT_EQ(hat->userId, sid_);
+
+    const string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+    AuthorizationSet out_params;
+    const string signature = SignMessage(keyblob, message, params, &out_params, hat.value());
+
+    // Verify second user to get a HAT that should work.
+    const uint64_t alt_challenge = 43;
+    const std::optional<HardwareAuthToken> alt_hat =
+            doVerify(alt_uid_, alt_challenge, alt_handle, alt_password);
+    ASSERT_TRUE(alt_hat.has_value());
+    EXPECT_EQ(alt_hat->userId, alt_sid_);
+
+    const string alt_signature =
+            SignMessage(keyblob, message, params, &out_params, alt_hat.value());
+}
+
 // Test use of a key that requires an auth token for each action on the operation, with
 // a per-operation challenge value included.
 TEST_P(AuthTest, AuthPerOperation) {
@@ -404,6 +545,93 @@
     ASSERT_GT(dodgy_hat->mac.size(), 0);
     dodgy_hat->mac[0] ^= 0x01;
     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+              Finish(message, {} /* signature */, &ciphertext, dodgy_hat.value()));
+}
+
+// Test use of a key that requires an auth token for each action on the operation, with
+// a per-operation challenge value included, with multiple secure IDs allowed.
+TEST_P(AuthTest, AuthPerOperationMultiSid) {
+    if (!GatekeeperAvailable()) {
+        GTEST_SKIP() << "No Gatekeeper available";
+    }
+
+    // Enroll a password for a second user.
+    alt_uid_ = 20001;
+    const string alt_password = "correcthorsebatterystaple2";
+    std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
+    ASSERT_TRUE(rsp.has_value());
+    alt_sid_ = rsp->secureUserId;
+    const std::vector<uint8_t> alt_handle = rsp->data;
+
+    // Create an AES key that requires authentication per-action.
+    auto builder = AuthorizationSetBuilder()
+                           .AesEncryptionKey(256)
+                           .BlockMode(BlockMode::ECB)
+                           .Padding(PaddingMode::PKCS7)
+                           .Authorization(TAG_USER_SECURE_ID, sid_)
+                           .Authorization(TAG_USER_SECURE_ID, alt_sid_)
+                           .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY);
+    vector<uint8_t> keyblob;
+    vector<KeyCharacteristics> key_characteristics;
+    vector<Certificate> cert_chain;
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+    // Get a HAT for first user with the challenge from an in-progress operation.
+    const string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    AuthorizationSet out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+    const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge_, handle_, password_);
+    ASSERT_TRUE(hat.has_value());
+    EXPECT_EQ(hat->userId, sid_);
+    string ciphertext;
+    EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
+
+    // Get a HAT for second user with the challenge from an in-progress operation.
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+    const std::optional<HardwareAuthToken> alt_hat =
+            doVerify(alt_uid_, challenge_, alt_handle, alt_password);
+    ASSERT_TRUE(alt_hat.has_value());
+    EXPECT_EQ(alt_hat->userId, alt_sid_);
+    string alt_ciphertext;
+    EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, alt_hat.value()));
+}
+
+// Test use of a key that requires an auth token for each action on the operation, but
+// which gets passed a HAT of the wrong type
+TEST_P(AuthTest, AuthPerOperationWrongAuthType) {
+    if (!GatekeeperAvailable()) {
+        GTEST_SKIP() << "No Gatekeeper available";
+    }
+
+    // Create an AES key that requires authentication per-action, but with no valid authenticator
+    // types.
+    auto builder =
+            AuthorizationSetBuilder()
+                    .AesEncryptionKey(256)
+                    .BlockMode(BlockMode::ECB)
+                    .Padding(PaddingMode::PKCS7)
+                    .Authorization(TAG_USER_SECURE_ID, sid_)
+                    .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::FINGERPRINT);
+    vector<uint8_t> keyblob;
+    vector<KeyCharacteristics> key_characteristics;
+    vector<Certificate> cert_chain;
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+    // Get a HAT with the challenge from an in-progress operation.
+    const string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    AuthorizationSet out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+    const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
+    ASSERT_TRUE(hat.has_value());
+    EXPECT_EQ(hat->userId, sid_);
+
+    // Should fail because auth type doesn't (can't) match.
+    string ciphertext;
+    EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
               Finish(message, {} /* signature */, &ciphertext, hat.value()));
 }
 
diff --git a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
index fb014cf..7ccd246 100644
--- a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
@@ -36,11 +36,14 @@
 //
 //      adb push keymint-blobs /data/local/tmp/keymint-blobs
 //
-// 5) Run the "*After*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
-//    pointing to the directory with the keyblobs:
+// 5) Run the "*After*" subset of these tests, with the following command-line arguments
+//    `--keyblob_dir <dir>`: pointing to the directory with the keyblobs.
+//    `--expect_upgrade {yes|no}` (Optional): To specify if users expect an upgrade on the keyBlobs,
+//                                            will be "yes" by default.
 //
 //      VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*After*" \
-//                               --keyblob_dir /data/local/tmp/keymint-blobs
+//                               --keyblob_dir /data/local/tmp/keymint-blobs \
+//                               --expect_upgrade {yes|no}
 //
 //    (Note that this skips the `CreateKeyBlobs` test, which would otherwise replace the saved
 //    keyblobs with freshly generated ones.).
@@ -426,12 +429,18 @@
 //
 //     VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UpgradeKeyBlobsAfter*" \
 //                              --keyblob_dir /data/local/tmp/keymint-blobs
+//                              --expect_upgrade {yes|no}
 //
 // - this replaces the keyblob contents in that directory; if needed, save the upgraded keyblobs
 //   with:
 //      adb pull /data/local/tmp/keymint-blobs/
 TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsAfter) {
-    UpgradeKeyBlobs(/* expectUpgrade= */ true);
+    bool expectUpgrade = true;  // this test expects upgrade to happen by default
+    if (expect_upgrade.has_value() && expect_upgrade == false) {
+        std::cout << "Not expecting key upgrade due to --expect_upgrade no\n";
+        expectUpgrade = false;
+    }
+    UpgradeKeyBlobs(expectUpgrade);
 }
 
 // To run this test:
@@ -574,7 +583,7 @@
                                               .SetDefaultValidity(),
                                       attest_key, &attested_key_blob, &attested_key_characteristics,
                                       &attested_key_cert_chain));
-                CheckedDeleteKey(&attested_key_blob);
+                KeyBlobDeleter(keymint_, attested_key_blob);
             } else {
                 FAIL() << "Unexpected name: " << name;
             }
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 433857c..5f8ec0e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -71,6 +71,11 @@
 // additional overhead, for the digest algorithmIdentifier required by PKCS#1.
 const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
 
+size_t count_tag_invalid_entries(const std::vector<KeyParameter>& authorizations) {
+    return std::count_if(authorizations.begin(), authorizations.end(),
+                         [](const KeyParameter& e) -> bool { return e.tag == Tag::INVALID; });
+}
+
 typedef KeyMintAidlTestBase::KeyData KeyData;
 // Predicate for testing basic characteristics validity in generation or import.
 bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
@@ -84,6 +89,8 @@
             return false;
         }
 
+        EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+
         // Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
         if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
 
@@ -174,6 +181,18 @@
 bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
 bool KeyMintAidlTestBase::dump_Attestations = false;
 std::string KeyMintAidlTestBase::keyblob_dir;
+std::optional<bool> KeyMintAidlTestBase::expect_upgrade = std::nullopt;
+
+KeyBlobDeleter::~KeyBlobDeleter() {
+    if (key_blob_.empty()) {
+        return;
+    }
+    Status result = keymint_->deleteKey(key_blob_);
+    key_blob_.clear();
+    EXPECT_TRUE(result.isOk()) << result.getServiceSpecificError() << "\n";
+    ErrorCode rc = GetReturnErrorCode(result);
+    EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED) << result << "\n";
+}
 
 uint32_t KeyMintAidlTestBase::boot_patch_level(
         const vector<KeyCharacteristics>& key_characteristics) {
@@ -228,16 +247,6 @@
     return version >= 2;
 }
 
-ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
-    if (result.isOk()) return ErrorCode::OK;
-
-    if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
-        return static_cast<ErrorCode>(result.getServiceSpecificError());
-    }
-
-    return ErrorCode::UNKNOWN_ERROR;
-}
-
 void KeyMintAidlTestBase::InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint) {
     ASSERT_NE(keyMint, nullptr);
     keymint_ = std::move(keyMint);
@@ -512,13 +521,9 @@
     return GetReturnErrorCode(result);
 }
 
-void KeyMintAidlTestBase::CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
-    ErrorCode result = DeleteKey(key_blob, keep_key_blob);
-    EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
-}
-
 void KeyMintAidlTestBase::CheckedDeleteKey() {
-    CheckedDeleteKey(&key_blob_);
+    ErrorCode result = DeleteKey(&key_blob_, /* keep_key_blob = */ false);
+    EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
 }
 
 ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
@@ -1602,7 +1607,8 @@
     auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr);
     if (res <= 0) return false;
 
-    const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"};
+    const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P",
+                                         "SM4450", "SM7450", "SM6450"};
 
     for (const string model : allowed_soc_models) {
         if (model.compare(buffer.data()) == 0) {
@@ -2003,6 +2009,16 @@
     return AssertionSuccess();
 }
 
+ErrorCode GetReturnErrorCode(const Status& result) {
+    if (result.isOk()) return ErrorCode::OK;
+
+    if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+        return static_cast<ErrorCode>(result.getServiceSpecificError());
+    }
+
+    return ErrorCode::UNKNOWN_ERROR;
+}
+
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob) {
     const uint8_t* p = blob.data();
     return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
@@ -2052,6 +2068,27 @@
     return retval;
 }
 
+void assert_mgf_digests_present_in_key_characteristics(
+        const vector<KeyCharacteristics>& key_characteristics,
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests) {
+    AuthorizationSet auths;
+    for (auto& entry : key_characteristics) {
+        auths.push_back(AuthorizationSet(entry.authorizations));
+    }
+    for (auto digest : expected_mgf_digests) {
+        ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+    }
+}
+
+bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
+                           android::hardware::security::keymint::Digest expected_mgf_digest) {
+    AuthorizationSet auths;
+    for (auto& entry : key_characteristics) {
+        auths.push_back(AuthorizationSet(entry.authorizations));
+    }
+    return auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, expected_mgf_digest);
+}
+
 namespace {
 
 void check_cose_key(const vector<uint8_t>& data, bool testMode) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index d8c9f11..8934a57 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -57,6 +57,18 @@
 const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key";
 const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
 
+// RAII class to ensure that a keyblob is deleted regardless of how a test exits.
+class KeyBlobDeleter {
+  public:
+    KeyBlobDeleter(const shared_ptr<IKeyMintDevice>& keymint, const vector<uint8_t>& key_blob)
+        : keymint_(keymint), key_blob_(key_blob) {}
+    ~KeyBlobDeleter();
+
+  private:
+    shared_ptr<IKeyMintDevice> keymint_;
+    vector<uint8_t> key_blob_;
+};
+
 class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
   public:
     struct KeyData {
@@ -70,6 +82,8 @@
     // Directory to store/retrieve keyblobs, using subdirectories named for the
     // KeyMint instance in question (e.g. "./default/", "./strongbox/").
     static std::string keyblob_dir;
+    // To specify if users expect an upgrade on the keyBlobs.
+    static std::optional<bool> expect_upgrade;
 
     void SetUp() override;
     void TearDown() override {
@@ -92,8 +106,6 @@
 
     bool Curve25519Supported();
 
-    ErrorCode GetReturnErrorCode(const Status& result);
-
     ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
                           vector<KeyCharacteristics>* key_characteristics) {
         return GenerateKey(key_desc, std::nullopt /* attest_key */, key_blob, key_characteristics,
@@ -157,7 +169,6 @@
 
     ErrorCode DestroyAttestationIds();
 
-    void CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
     void CheckedDeleteKey();
 
     ErrorCode Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
@@ -419,6 +430,11 @@
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
 ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
 vector<uint8_t> make_name_from_str(const string& name);
+void assert_mgf_digests_present_in_key_characteristics(
+        const vector<KeyCharacteristics>& key_characteristics,
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests);
+bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
+                           android::hardware::security::keymint::Digest expected_mgf_digest);
 void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
                         vector<uint8_t>* payload_value);
 void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
@@ -430,6 +446,8 @@
 ::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
                                                    bool strict_issuer_check = true);
 
+ErrorCode GetReturnErrorCode(const Status& result);
+
 #define INSTANTIATE_KEYMINT_AIDL_TEST(name)                                          \
     INSTANTIATE_TEST_SUITE_P(PerInstance, name,                                      \
                              testing::ValuesIn(KeyMintAidlTestBase::build_params()), \
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 1297d1d..022dd3f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -693,6 +693,7 @@
                     builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
                 }
                 ASSERT_EQ(ErrorCode::OK, GenerateKey(builder, &key_blob, &key_characteristics));
+                KeyBlobDeleter deleter(keymint_, key_blob);
 
                 EXPECT_GT(key_blob.size(), 0U);
                 CheckSymmetricParams(key_characteristics);
@@ -703,8 +704,6 @@
                 EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::AES));
                 EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                         << "Key size " << key_size << "missing";
-
-                CheckedDeleteKey(&key_blob);
             }
         }
     }
@@ -877,6 +876,7 @@
                                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                                              .SetDefaultValidity(),
                                                      &key_blob, &key_characteristics));
+                KeyBlobDeleter deleter(keymint_, key_blob);
 
                 EXPECT_GT(key_blob.size(), 0U);
                 CheckSymmetricParams(key_characteristics);
@@ -887,8 +887,6 @@
                 EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::TRIPLE_DES));
                 EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                         << "Key size " << key_size << "missing";
-
-                CheckedDeleteKey(&key_blob);
             }
         }
     }
@@ -924,6 +922,7 @@
                                                              .AttestationApplicationId(app_id)
                                                              .SetDefaultValidity(),
                                                      &key_blob, &key_characteristics));
+                KeyBlobDeleter deleter(keymint_, key_blob);
 
                 EXPECT_GT(key_blob.size(), 0U);
                 CheckSymmetricParams(key_characteristics);
@@ -934,8 +933,6 @@
                 EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::TRIPLE_DES));
                 EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                         << "Key size " << key_size << "missing";
-
-                CheckedDeleteKey(&key_blob);
             }
         }
     }
@@ -1003,6 +1000,7 @@
                                                      .Padding(PaddingMode::NONE)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1014,8 +1012,6 @@
         EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                 << "Key size " << key_size << "missing";
         EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1139,6 +1135,7 @@
             }
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1159,8 +1156,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1214,6 +1209,7 @@
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
                                       .SetDefaultValidity(),
                               attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1240,8 +1236,6 @@
         ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
                 << "Verification of attested certificate failed "
                 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1294,6 +1288,7 @@
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
                                       .SetDefaultValidity(),
                               attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1318,8 +1313,6 @@
         ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
                 << "Verification of attested certificate failed "
                 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1365,6 +1358,7 @@
         }
     }
     ASSERT_EQ(ErrorCode::OK, result);
+    KeyBlobDeleter deleter(keymint_, key_blob);
 
     ASSERT_GT(key_blob.size(), 0U);
     AuthorizationSet auths;
@@ -1405,8 +1399,6 @@
     EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           cert_chain_[0].encodedCertificate));
-
-    CheckedDeleteKey(&key_blob);
 }
 
 /*
@@ -1437,6 +1429,7 @@
                                       .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
                                       .SetDefaultValidity(),
                               &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1452,8 +1445,6 @@
         ASSERT_EQ(cert_chain_.size(), 1);
         verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1518,6 +1509,7 @@
                                   .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
                                   .SetDefaultValidity(),
                           &key_blob, &key_characteristics));
+    KeyBlobDeleter deleter(keymint_, key_blob);
 
     ASSERT_GT(key_blob.size(), 0U);
     CheckBaseParams(key_characteristics);
@@ -1534,8 +1526,6 @@
     verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
     EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
     ASSERT_EQ(cert_chain_.size(), 1);
-
-    CheckedDeleteKey(&key_blob);
 }
 
 /*
@@ -1556,6 +1546,7 @@
                                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1575,8 +1566,6 @@
         }
         EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
                 << "key usage count limit " << 1U << " missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1625,6 +1614,7 @@
             }
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1655,8 +1645,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1726,6 +1714,7 @@
                                                      .Digest(Digest::NONE)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1734,8 +1723,6 @@
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
         EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1759,6 +1746,8 @@
                                            .SetDefaultValidity(),
                                    &key_blob, &key_characteristics);
     ASSERT_EQ(result, ErrorCode::OK);
+    KeyBlobDeleter deleter(keymint_, key_blob);
+
     ASSERT_GT(key_blob.size(), 0U);
 
     EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -1771,8 +1760,6 @@
 
     EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
     EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
-
-    CheckedDeleteKey(&key_blob);
 }
 
 /*
@@ -1879,6 +1866,7 @@
             }
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1897,8 +1885,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1936,6 +1922,7 @@
                                            .SetDefaultValidity(),
                                    &key_blob, &key_characteristics);
     ASSERT_EQ(ErrorCode::OK, result);
+    KeyBlobDeleter deleter(keymint_, key_blob);
     ASSERT_GT(key_blob.size(), 0U);
     CheckBaseParams(key_characteristics);
     CheckCharacteristics(key_blob, key_characteristics);
@@ -1954,8 +1941,6 @@
     EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           cert_chain_[0].encodedCertificate));
-
-    CheckedDeleteKey(&key_blob);
 }
 
 /*
@@ -2024,6 +2009,7 @@
             }
         }
         ASSERT_EQ(result, ErrorCode::OK);
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2043,8 +2029,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
                                               hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 
     // Collection of invalid attestation ID tags.
@@ -2171,6 +2155,7 @@
             continue;
         }
         ASSERT_EQ(result, ErrorCode::OK);
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2190,8 +2175,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
                                               hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2346,6 +2329,7 @@
         }
     }
     ASSERT_EQ(result, ErrorCode::OK);
+    KeyBlobDeleter deleter(keymint_, key_blob);
     ASSERT_GT(key_blob.size(), 0U);
 
     EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -2365,8 +2349,6 @@
     ASSERT_EQ(std::search(cert_chain_[0].encodedCertificate.begin(),
                           cert_chain_[0].encodedCertificate.end(), needle.begin(), needle.end()),
               cert_chain_[0].encodedCertificate.end());
-
-    CheckedDeleteKey(&key_blob);
 }
 
 /*
@@ -2394,6 +2376,7 @@
                                       .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
                                       .SetDefaultValidity(),
                               &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -2409,8 +2392,6 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2464,6 +2445,7 @@
                                                      .AttestationApplicationId(app_id)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -2479,8 +2461,6 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2522,6 +2502,7 @@
             }
         }
         ASSERT_EQ(ErrorCode::OK, result);
+        KeyBlobDeleter deleter(keymint_, key_blob);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -2539,8 +2520,6 @@
         EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2561,6 +2540,7 @@
                                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -2578,8 +2558,6 @@
         }
         EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
                 << "key usage count limit " << 1U << " missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2587,22 +2565,24 @@
  * NewKeyGenerationTest.EcdsaDefaultSize
  *
  * Verifies that failing to specify a curve for EC key generation returns
- * UNSUPPORTED_KEY_SIZE.
+ * UNSUPPORTED_KEY_SIZE or UNSUPPORTED_EC_CURVE.
  */
 TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) {
-    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_ALGORITHM, Algorithm::EC)
-                                  .SigningKey()
-                                  .Digest(Digest::NONE)
-                                  .SetDefaultValidity()));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .Authorization(TAG_ALGORITHM, Algorithm::EC)
+                                      .SigningKey()
+                                      .Digest(Digest::NONE)
+                                      .SetDefaultValidity());
+    ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
+                result == ErrorCode::UNSUPPORTED_EC_CURVE)
+            << "unexpected result " << result;
 }
 
 /*
  * NewKeyGenerationTest.EcdsaInvalidCurve
  *
  * Verifies that specifying an invalid curve for EC key generation returns
- * UNSUPPORTED_KEY_SIZE.
+ * UNSUPPORTED_KEY_SIZE or UNSUPPORTED_EC_CURVE.
  */
 TEST_P(NewKeyGenerationTest, EcdsaInvalidCurve) {
     for (auto curve : InvalidCurves()) {
@@ -2615,7 +2595,8 @@
                                           .SetDefaultValidity(),
                                   &key_blob, &key_characteristics);
         ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
-                    result == ErrorCode::UNSUPPORTED_EC_CURVE);
+                    result == ErrorCode::UNSUPPORTED_EC_CURVE)
+                << "unexpected result " << result;
     }
 
     ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
@@ -2711,6 +2692,7 @@
                           AuthorizationSetBuilder().HmacKey(key_size).Digest(digest).Authorization(
                                   TAG_MIN_MAC_LENGTH, 128),
                           &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -2720,8 +2702,6 @@
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
         EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                 << "Key size " << key_size << "missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2747,6 +2727,7 @@
                                                      .AttestationApplicationId(app_id)
                                                      .Authorization(TAG_MIN_MAC_LENGTH, 128),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         ASSERT_EQ(cert_chain_.size(), 0);
@@ -2757,8 +2738,6 @@
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
         EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
                 << "Key size " << key_size << "missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -2780,6 +2759,7 @@
                                                      .Authorization(TAG_MIN_MAC_LENGTH, 128)
                                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
                                              &key_blob, &key_characteristics));
+        KeyBlobDeleter deleter(keymint_, key_blob);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -2797,8 +2777,6 @@
         }
         EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
                 << "key usage count limit " << 1U << " missing";
-
-        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -3456,7 +3434,6 @@
  * Verifies ECDSA signature/verification for all digests and required curves.
  */
 TEST_P(SigningOperationsTest, EcdsaAllDigestsAndCurves) {
-
     string message = "1234567890";
     string corrupt_message = "2234567890";
     for (auto curve : ValidCurves()) {
@@ -3892,6 +3869,7 @@
                                 .Digest(Digest::SHA_2_256)
                                 .Authorization(TAG_MIN_MAC_LENGTH, 160),
                         KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+    KeyBlobDeleter sign_deleter(keymint_, signing_key);
     EXPECT_EQ(ErrorCode::OK,
               ImportKey(AuthorizationSetBuilder()
                                 .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -3900,6 +3878,7 @@
                                 .Digest(Digest::SHA_2_256)
                                 .Authorization(TAG_MIN_MAC_LENGTH, 160),
                         KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+    KeyBlobDeleter verify_deleter(keymint_, verification_key);
 
     string message = "This is a message.";
     string signature = SignMessage(
@@ -3915,9 +3894,6 @@
     // Verification key should work.
     VerifyMessage(verification_key, message, signature,
                   AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
-
-    CheckedDeleteKey(&signing_key);
-    CheckedDeleteKey(&verification_key);
 }
 
 /*
@@ -3938,6 +3914,7 @@
                                 .Digest(Digest::SHA_2_256)
                                 .Authorization(TAG_MIN_MAC_LENGTH, 160),
                         KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+    KeyBlobDeleter sign_deleter(keymint_, signing_key);
     EXPECT_EQ(ErrorCode::OK,
               ImportKey(AuthorizationSetBuilder()
                                 .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -3946,6 +3923,7 @@
                                 .Digest(Digest::SHA_2_256)
                                 .Authorization(TAG_MIN_MAC_LENGTH, 160),
                         KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+    KeyBlobDeleter verify_deleter(keymint_, verification_key);
 
     string message = "This is a message.";
     string signature = SignMessage(
@@ -3967,9 +3945,6 @@
 
     signature[0] += 1;  // Corrupt a signature
     EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, signature, &output));
-
-    CheckedDeleteKey(&signing_key);
-    CheckedDeleteKey(&verification_key);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
@@ -4755,6 +4730,102 @@
     }
 }
 
+/*
+ * ImportKeyTest.RsaOaepMGFDigestSuccess
+ *
+ * Include MGF-Digest explicitly in import key authorization list.
+ * Test should import RSA key with OAEP padding and mgf-digests and verify that imported key
+ * should have the correct characteristics.
+ */
+TEST_P(ImportKeyTest, RsaOaepMGFDigestSuccess) {
+    auto mgf_digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+    size_t key_size = 2048;
+
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .OaepMGFDigest(mgf_digests)
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .RsaEncryptionKey(key_size, 65537)
+                                               .Digest(Digest::SHA_2_256)
+                                               .Padding(PaddingMode::RSA_OAEP)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, rsa_2048_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+    CheckCryptoParam(TAG_KEY_SIZE, key_size);
+    CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
+    CheckOrigin();
+
+    // Make sure explicitly specified mgf-digests exist in key characteristics.
+    assert_mgf_digests_present_in_key_characteristics(key_characteristics_, mgf_digests);
+
+    string message = "Hello";
+
+    for (auto digest : mgf_digests) {
+        SCOPED_TRACE(testing::Message() << "digest-" << digest);
+        auto params = AuthorizationSetBuilder()
+                              .Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest)
+                              .Digest(Digest::SHA_2_256)
+                              .Padding(PaddingMode::RSA_OAEP);
+        string ciphertext1 = LocalRsaEncryptMessage(message, params);
+        if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+        EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+        string ciphertext2 = LocalRsaEncryptMessage(message, params);
+        if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+        EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+        // OAEP randomizes padding so every result should be different (with astronomically high
+        // probability).
+        EXPECT_NE(ciphertext1, ciphertext2);
+
+        string plaintext1 = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
+        string plaintext2 = DecryptMessage(ciphertext2, params);
+        EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;
+
+        // Decrypting corrupted ciphertext should fail.
+        size_t offset_to_corrupt = ciphertext1.size() - 1;
+        char corrupt_byte = ~ciphertext1[offset_to_corrupt];
+        ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+        string result;
+        EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+        EXPECT_EQ(0U, result.size());
+    }
+}
+
+/*
+ * ImportKeyTest.RsaOaepMGFDigestDefaultSuccess
+ *
+ * Don't specify MGF-Digest explicitly in import key authorization list.
+ * Test should import RSA key with OAEP padding and default mgf-digest (SHA1) and
+ * verify that imported key should have the correct characteristics. Default
+ * mgf-digest shouldn't be included in key charecteristics.
+ */
+TEST_P(ImportKeyTest, RsaOaepMGFDigestDefaultSuccess) {
+    size_t key_size = 2048;
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .RsaEncryptionKey(key_size, 65537)
+                                               .Digest(Digest::SHA_2_256)
+                                               .Padding(PaddingMode::RSA_OAEP)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, rsa_2048_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+    CheckCryptoParam(TAG_KEY_SIZE, key_size);
+    CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
+    CheckOrigin();
+
+    // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
+    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
 
 auto wrapped_key = hex2str(
@@ -5180,16 +5251,19 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
     auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+    auto mgf_digest = Digest::SHA1;
 
     size_t key_size = 2048;  // Need largish key for SHA-512 test.
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .RsaEncryptionKey(key_size, 65537)
-                                  .Padding(PaddingMode::RSA_OAEP)
-                                  .Digest(digests)
-                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA1)
-                                  .SetDefaultValidity()));
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaEncryptionKey(key_size, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(digests)
+                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .SetDefaultValidity()));
+
+    // Make sure explicitly specified mgf-digest exist in key characteristics.
+    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
 
     string message = "Hello";
 
@@ -5315,6 +5389,20 @@
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
+    std::vector<Digest> mgf1DigestsInAuths;
+    mgf1DigestsInAuths.reserve(digests.size());
+    const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
+    std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
+        if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
+            KeyParameterValue value = param.value;
+            mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
+        }
+    });
+
+    std::sort(digests.begin(), digests.end());
+    std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
+    EXPECT_EQ(digests, mgf1DigestsInAuths);
+
     string message = "Hello";
 
     for (auto digest : digests) {
@@ -5369,6 +5457,9 @@
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
+    // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
+    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
     auto params =
@@ -5403,14 +5494,19 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultFail) {
     size_t key_size = 2048;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
-                                  .RsaEncryptionKey(key_size, 65537)
-                                  .Padding(PaddingMode::RSA_OAEP)
-                                  .Digest(Digest::SHA_2_256)
-                                  .SetDefaultValidity()));
+    auto mgf_digest = Digest::SHA_2_256;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .RsaEncryptionKey(key_size, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .SetDefaultValidity()));
+
+    // Make sure explicitly specified mgf-digest exist in key characteristics.
+    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    // Make sure default mgf-digest is not included in key characteristics.
+    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
 
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
@@ -5434,14 +5530,17 @@
  * with incompatible MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .RsaEncryptionKey(2048, 65537)
-                                  .Padding(PaddingMode::RSA_OAEP)
-                                  .Digest(Digest::SHA_2_256)
-                                  .SetDefaultValidity()));
+    auto mgf_digest = Digest::SHA_2_256;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaEncryptionKey(2048, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .SetDefaultValidity()));
+    // Make sure explicitly specified mgf-digest exist in key characteristics.
+    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+
     string message = "Hello World!";
 
     auto params = AuthorizationSetBuilder()
@@ -5458,14 +5557,17 @@
  * with unsupported MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .RsaEncryptionKey(2048, 65537)
-                                  .Padding(PaddingMode::RSA_OAEP)
-                                  .Digest(Digest::SHA_2_256)
-                                  .SetDefaultValidity()));
+    auto mgf_digest = Digest::SHA_2_256;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaEncryptionKey(2048, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .SetDefaultValidity()));
+    // Make sure explicitly specified mgf-digest exist in key characteristics.
+    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+
     string message = "Hello World!";
 
     auto params = AuthorizationSetBuilder()
@@ -8498,16 +8600,16 @@
     // Early boot keys can be created after early boot.
     auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
             CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+    KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+    KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+    KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+    KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
 
     for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
         ASSERT_GT(keyData.blob.size(), 0U);
         AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
         EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
     }
-    CheckedDeleteKey(&aesKeyData.blob);
-    CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
 }
 
 /*
@@ -8521,6 +8623,10 @@
                 builder->AttestationChallenge("challenge");
                 builder->AttestationApplicationId("app_id");
             });
+    KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+    KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+    KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+    KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
 
     for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
         // Strongbox may not support factory attestation. Key creation might fail with
@@ -8532,14 +8638,6 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
         EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
     }
-    CheckedDeleteKey(&aesKeyData.blob);
-    CheckedDeleteKey(&hmacKeyData.blob);
-    if (rsaKeyData.blob.size() != 0U) {
-        CheckedDeleteKey(&rsaKeyData.blob);
-    }
-    if (ecdsaKeyData.blob.size() != 0U) {
-        CheckedDeleteKey(&ecdsaKeyData.blob);
-    }
 }
 
 /*
@@ -8584,6 +8682,11 @@
 TEST_P(EarlyBootKeyTest, DISABLED_FullTest) {
     auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
             CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+    KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+    KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+    KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+    KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
+
     // TAG_EARLY_BOOT_ONLY should be in hw-enforced.
     EXPECT_TRUE(HwEnforcedAuthorizations(aesKeyData.characteristics).Contains(TAG_EARLY_BOOT_ONLY));
     EXPECT_TRUE(
@@ -8608,19 +8711,13 @@
     EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseRsaKey(rsaKeyData.blob));
     EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseEcdsaKey(ecdsaKeyData.blob));
 
-    CheckedDeleteKey(&aesKeyData.blob);
-    CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
-
     // Should not be able to create new keys
-    std::tie(aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData) =
+    auto [aesKeyData2, hmacKeyData2, rsaKeyData2, ecdsaKeyData2] =
             CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
-
-    CheckedDeleteKey(&aesKeyData.blob);
-    CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
+    KeyBlobDeleter aes_deleter2(keymint_, aesKeyData2.blob);
+    KeyBlobDeleter hmac_deleter2(keymint_, hmacKeyData2.blob);
+    KeyBlobDeleter rsa_deleter2(keymint_, rsaKeyData2.blob);
+    KeyBlobDeleter ecdsa_deleter2(keymint_, ecdsaKeyData2.blob);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(EarlyBootKeyTest);
@@ -8638,6 +8735,10 @@
 TEST_P(UnlockedDeviceRequiredTest, DISABLED_KeysBecomeUnusable) {
     auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
             CreateTestKeys(TAG_UNLOCKED_DEVICE_REQUIRED, ErrorCode::OK);
+    KeyBlobDeleter aes_deleter(keymint_, aesKeyData.blob);
+    KeyBlobDeleter hmac_deleter(keymint_, hmacKeyData.blob);
+    KeyBlobDeleter rsa_deleter(keymint_, rsaKeyData.blob);
+    KeyBlobDeleter ecdsa_deleter(keymint_, ecdsaKeyData.blob);
 
     EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
     EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
@@ -8651,17 +8752,13 @@
     EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseHmacKey(hmacKeyData.blob));
     EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseRsaKey(rsaKeyData.blob));
     EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseEcdsaKey(ecdsaKeyData.blob));
-
-    CheckedDeleteKey(&aesKeyData.blob);
-    CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(UnlockedDeviceRequiredTest);
 
 using VsrRequirementTest = KeyMintAidlTestBase;
 
+// @VsrTest = VSR-3.10-008
 TEST_P(VsrRequirementTest, Vsr13Test) {
     int vsr_api_level = get_vsr_api_level();
     if (vsr_api_level < __ANDROID_API_T__) {
@@ -8670,6 +8767,7 @@
     EXPECT_GE(AidlVersion(), 2) << "VSR 13+ requires KeyMint version 2";
 }
 
+// @VsrTest = VSR-3.10-013.001
 TEST_P(VsrRequirementTest, Vsr14Test) {
     int vsr_api_level = get_vsr_api_level();
     if (vsr_api_level < __ANDROID_API_U__) {
@@ -8719,6 +8817,19 @@
                         std::string(argv[i + 1]);
                 ++i;
             }
+            if (std::string(argv[i]) == "--expect_upgrade") {
+                if (i + 1 >= argc) {
+                    std::cerr << "Missing argument for --expect_upgrade\n";
+                    return 1;
+                }
+                std::string arg = argv[i + 1];
+                aidl::android::hardware::security::keymint::test::KeyMintAidlTestBase::
+                        expect_upgrade =
+                                arg == "yes"
+                                        ? true
+                                        : (arg == "no" ? false : std::optional<bool>(std::nullopt));
+                ++i;
+            }
         }
     }
     return RUN_ALL_TESTS();
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 3cb783c..780c3d2 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <iomanip>
 #include <iterator>
 #include <memory>
 #include <set>
@@ -115,6 +116,36 @@
     return std::make_tuple(std::move(pubX), std::move(pubY));
 }
 
+ErrMsgOr<bytevec> getRawPublicKey(const EVP_PKEY_Ptr& pubKey) {
+    if (pubKey.get() == nullptr) {
+        return "pkey is null.";
+    }
+    int keyType = EVP_PKEY_base_id(pubKey.get());
+    switch (keyType) {
+        case EVP_PKEY_EC: {
+            auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pubKey.get()));
+            if (ecKey.get() == nullptr) {
+                return "Failed to get ec key";
+            }
+            return ecKeyGetPublicKey(ecKey.get());
+        }
+        case EVP_PKEY_ED25519: {
+            bytevec rawPubKey;
+            size_t rawKeySize = 0;
+            if (!EVP_PKEY_get_raw_public_key(pubKey.get(), NULL, &rawKeySize)) {
+                return "Failed to get raw public key.";
+            }
+            rawPubKey.resize(rawKeySize);
+            if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey.data(), &rawKeySize)) {
+                return "Failed to get raw public key.";
+            }
+            return rawPubKey;
+        }
+        default:
+            return "Unknown key type.";
+    }
+}
+
 ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
     auto ec_key = EC_KEY_Ptr(EC_KEY_new());
     if (ec_key.get() == nullptr) {
@@ -390,6 +421,36 @@
     return entryName + " has an invalid value.\n";
 }
 
+std::string checkMapPatchLevelEntry(bool isFactory, const cppbor::Map& devInfo,
+                                    const std::string& entryName) {
+    std::string error = checkMapEntry(isFactory, devInfo, cppbor::UINT, entryName);
+    if (!error.empty()) {
+        return error;
+    }
+
+    if (isFactory) {
+        return "";
+    }
+
+    const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+    std::string dateString = std::to_string(val->asUint()->unsignedValue());
+    if (dateString.size() == 6) {
+        dateString += "01";
+    }
+    if (dateString.size() != 8) {
+        return entryName + " should in the format YYYYMMDD or YYYYMM\n";
+    }
+
+    std::tm t;
+    std::istringstream ss(dateString);
+    ss >> std::get_time(&t, "%Y%m%d");
+    if (!ss) {
+        return entryName + " should in the format YYYYMMDD or YYYYMM\n";
+    }
+
+    return "";
+}
+
 bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
     return devInfo.get("security_level") && devInfo.get("security_level")->asTstr() &&
            devInfo.get("security_level")->asTstr()->value() == "tee";
@@ -490,6 +551,10 @@
                     error += "Err: Unrecognized key entry: <" + key->asTstr()->value() + ">,\n";
                 }
             }
+            // Checks that only apply to v3.
+            error += checkMapPatchLevelEntry(isFactory, *parsed, "system_patch_level");
+            error += checkMapPatchLevelEntry(isFactory, *parsed, "boot_patch_level");
+            error += checkMapPatchLevelEntry(isFactory, *parsed, "vendor_patch_level");
             FALLTHROUGH_INTENDED;
         case 2:
             for (const auto& entry : kAttestationIdEntrySet) {
@@ -706,11 +771,10 @@
 
 // Validates the certificate chain and returns the leaf public key.
 ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
-    uint8_t rawPubKey[64];
-    size_t rawPubKeySize = sizeof(rawPubKey);
+    bytevec rawPubKey;
     for (size_t i = 0; i < chain.size(); ++i) {
         // Root must be self-signed.
-        size_t signingCertIndex = (i > 1) ? i - 1 : i;
+        size_t signingCertIndex = (i > 0) ? i - 1 : i;
         auto& keyCertItem = chain[i];
         auto& signingCertItem = chain[signingCertIndex];
         if (!keyCertItem || !keyCertItem->asBstr()) {
@@ -724,7 +788,7 @@
         if (!keyCert) {
             return keyCert.message();
         }
-        auto signingCert = parseX509Cert(keyCertItem->asBstr()->value());
+        auto signingCert = parseX509Cert(signingCertItem->asBstr()->value());
         if (!signingCert) {
             return signingCert.message();
         }
@@ -749,17 +813,16 @@
             return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
                    signerSubj + " Issuer subject is " + certIssuer;
         }
-
-        rawPubKeySize = sizeof(rawPubKey);
-        if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey, &rawPubKeySize)) {
-            return "Failed to get raw public key.";
+        if (i == chain.size() - 1) {
+            auto key = getRawPublicKey(pubKey);
+            if (!key) key.moveMessage();
+            rawPubKey = key.moveValue();
         }
     }
-
-    return bytevec(rawPubKey, rawPubKey + rawPubKeySize);
+    return rawPubKey;
 }
 
-std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsPub) {
+std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsCoseKeyBytes) {
     for (const auto& [signerName, udsCertChain] : udsCerts) {
         if (!signerName || !signerName->asTstr()) {
             return "Signer Name must be a Tstr.";
@@ -775,8 +838,31 @@
         if (!leafPubKey) {
             return leafPubKey.message();
         }
+        auto coseKey = CoseKey::parse(udsCoseKeyBytes);
+        if (!coseKey) return coseKey.moveMessage();
+
+        auto curve = coseKey->getIntValue(CoseKey::CURVE);
+        if (!curve) {
+            return "CoseKey must contain curve.";
+        }
+        bytevec udsPub;
+        if (curve == CoseKeyCurve::P256 || curve == CoseKeyCurve::P384) {
+            auto pubKey = coseKey->getEcPublicKey();
+            if (!pubKey) return pubKey.moveMessage();
+            // convert public key to uncompressed form by prepending 0x04 at begin.
+            pubKey->insert(pubKey->begin(), 0x04);
+            udsPub = pubKey.moveValue();
+        } else if (curve == CoseKeyCurve::ED25519) {
+            auto& pubkey = coseKey->getMap().get(cppcose::CoseKey::PUBKEY_X);
+            if (!pubkey || !pubkey->asBstr()) {
+                return "Invalid public key.";
+            }
+            udsPub = pubkey->asBstr()->value();
+        } else {
+            return "Unknown curve.";
+        }
         if (*leafPubKey != udsPub) {
-            return "Leaf public key in UDS certificat chain doesn't match UDS public key.";
+            return "Leaf public key in UDS certificate chain doesn't match UDS public key.";
         }
     }
     return "";
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 7477f80..15ea817 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -3,7 +3,7 @@
 ## Objective
 
 Design a HAL to support over-the-air provisioning of certificates for asymmetric
-keys. The HAL must interact effectively with Keystore (and other daemons) and
+keys. The HAL must interact effectively with Keystore (and other services) and
 protect device privacy and security.
 
 Note that this API was originally designed for KeyMint, with the intention that
@@ -20,125 +20,54 @@
 To more securely and reliably get keys and certificates to Android devices, we
 need to create a system where no party outside of the device's secure components
 is responsible for managing private keys. The strategy we've chosen is to
-deliver certificates over the air, using an asymmetric key pair created
-on-device in the factory as a root of trust to create an authenticated, secure
-channel. In this document we refer to this device-unique asymmetric key pair as
-Device Key (DK), its public half DK\_pub, its private half DK\_priv and a Device
-Key Certificate containing DK\_pub is denoted DKC.
+deliver certificates over the air, using an asymmetric key pair derived from a
+unique device secret (UDS) as a root of trust for authenticated requests from
+the secure components. We refer to the public half of this asymmetric key pair
+as UDS\_pub.
 
-In order for the provisioning service to use DK (or a key authenticated by DK),
-it must know whether a given DK\_pub is known and trusted. To prove trust, we
-ask device OEMs to use one of two mechanisms:
+In order for the provisioning service to trust UDS\_pub we ask device OEMs to
+use one of two mechanisms:
 
-1.  (Preferred, recommended) The device OEM extracts DK\_pub from each device it
-    manufactures and uploads the public keys to a backend server.
+1.  (Preferred, recommended) The device OEM extracts the UDS\_pub from each
+    device they manufacture and uploads the public keys to a backend server.
 
-1.  The device OEM signs the DK\_pub to produce DKC and stores it on the device.
-    This has the advantage that they don't need to upload a DK\_pub for every
-    device immediately, but the disadvantage that they have to manage their
-    private signing keys, which means they have to have HSMs, configure and
-    secure them correctly, etc. Some backend providers may also require that the
-    OEM passes a factory security audit, and additionally promises to upload the
-    keys eventually as well.
+1.  The device OEM signs the UDS\_pub and stores the certificates on the device
+    rather than uploading a UDS\_pub for every device immediately. However,
+    there are many disadvantages and costs associated with this option as the
+    OEM will need to pass a security audit of their factory's physical security,
+    CA and HSM configuration, and incident response processes before the OEM's
+    public key is registered with the provisioning server.
 
-Note that in the full elaboration of this plan, DK\_pub is not the key used to
-establish a secure channel. Instead, DK\_pub is just the first public key in a
-chain of public keys which ends with the KeyMint public key, KM\_pub. All keys
-in the chain are device-unique and are joined in a certificate chain called the
-_Boot Certificate Chain_ (BCC), because in phases 2 and 3 of the remote
-provisioning project it is a chain of certificates corresponding to boot phases.
-We speak of the BCC even for phase 1, though in phase 1 it contains only a
-single self-signed DKC. This is described in more depth in the Phases section
-below.
+Note that in the full elaboration of this plan, UDS\_pub is not the key used to
+sign certificate requests. Instead, UDS\_pub is just the first public key in a
+chain of public keys that end the KeyMint public key. All keys in the chain are
+transitively derived from the UDS and joined in a certificate chain following
+the specification of the [Android Profile for DICE](android-profile-for-dice).
 
-The BCC is authenticated by DK\_pub. To authenticate DK\_pub, we may have
-additional DKCs, from the SoC vendor, the device OEM, or both. Those are not
-part of the BCC but included as optional fields in the certificate request
-structure.
-
-The format of the the DK and BCC is specified within [Open Profile for DICE]
-(https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md).  To
-map phrases within this document to their equivalent terminology in the DICE
-specification, read the terms as follows: the DK corresponds to the UDS-derived
-key pair, DKC corresponds to the UDS certificate, and the BCC entries between
-DK\_pub and KM\_pub correspond to a chain of CDI certificates.
-
-Note: In addition to allowing 32 byte hash values for fields in the BCC payload,
-this spec additionally constrains some of the choices allowed in open-DICE.
-Specifically, these include which entries are required and which are optional in
-the BCC payload, and which algorithms are acceptable for use.
+[android-profile-for-dice]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md
 
 ### Phases
 
-RKP will be deployed in three phases, in terms of managing the root of trust
+RKP will be deployed with phased management of the root of trust
 binding between the device and the backend. To briefly describe them:
 
-* Phase 1: In phase 1 there is only one entry in the BCC; DK_pub and KM_pub are
-  the same key and the certificate is self-signed.
-* Phase 2: This is identical to phase 1, except it leverages the hardware root
-  of trust process described by DICE. Instead of trust being rooted in the TEE,
-  it is now rooted in the ROM by key material blown into fuses which are only
-  accessible to the ROM code.
-* Phase 3: This is identical to Phase 2, except the SoC vendor also does the
-  public key extraction or certification in their facilities, along with the OEM
-  doing it in the factory. This tightens up the "supply chain" and aims to make
-  key upload management more secure.
+* Degenerate DICE (Phase 1): A TEE root of trust key pair is used to sign
+  certificate requests; a single self-signed certificate signifies this phase.
+* DICE (Phase 2): A hardware root of trust key pair is only accessible to ROM
+  or ROM extension code; the boot process follows the [Android Profile for
+  DICE](android-profile-for-dice).
+* SoC vendor certified DICE (Phase 3): This is identical to Phase 2, except the
+  SoC vendor also does the UDS\_pub extraction or certification in their
+  facilities, along with the OEM doing it in the factory. This tightens up the
+  "supply chain" and aims to make key upload management more secure.
 
 ### Privacy considerations
 
-Because DK and the DKCs are unique, immutable, unspoofable hardware-bound
-identifiers for the device, we must limit access to them to the absolute minimum
-possible. We do this in two ways:
-
-1.  We require KeyMint (which knows the BCC and either knows or at least has the
-ability to use KM\_priv) to refuse to ever divulge the BCC or additional
-signatures in plaintext. Instead, KeyMint requires the caller to provide an
-_Endpoint Encryption Key_ (EEK), with which it will encrypt the data before
-returning it. When provisioning production keys, the EEK must be signed by an
-approved authority whose public key is embedded in KeyMint. When certifying test
-keys, KeyMint will accept any EEK without checking the signature, but will
-encrypt and return a test BCC, rather than the real one.  The result is that
-only an entity in possession of an Trusted EEK (TEEK) private key can discover
-the plaintext of the production BCC.
-1.  Having thus limited access to the public keys to the trusted party only, we
-need to prevent the entity from abusing this unique device identifier.  The
-approach and mechanisms for doing that are beyond the scope of this document
-(they must be addressed in the server design), but generally involve taking care
-to ensure that we do not create any links between user IDs, IP addresses or
-issued certificates and the device pubkey.
-
-Although the details of the mechanisms for preventing the entity from abusing
-the BCC are, as stated, beyond the scope of this document, there is a subtle
-design decision here made specifically to enable abuse prevention. Specifically
-the `CertificateRequest` message sent to the server is (in
-[CDDL](https://tools.ietf.org/html/rfc8610)):
-
-```
-cddl
-CertificateRequest = [
-    DeviceInfo,
-    challenge : bstr,
-    ProtectedData,
-    MacedKeysToSign
-]
-```
-
-The public keys to be attested by the server are in `MacedKeysToSign`, which is
-a COSE\_Mac0 structure, MACed with a key that is found in `ProtectedData`. The
-MAC key is signed by DK\_pub.
-
-This structure allows the backend component that has access to EEK\_priv to
-decrypt `ProtectedData`, validate that the request is from an authorized device,
-check that the request is fresh and verify and extract the MAC key. That backend
-component never sees any data related to the keys to be signed, but can provide
-the MAC key to another backend component that can verify `MacedKeysToSign` and
-proceed to generate the certificates.
-
-In this way, we can partition the provisioning server into one component that
-knows the device identity, as represented by DK\_pub, but never sees the keys to
-be certified or certificates generated, and another component that sees the keys
-to be certified and certificates generated but does not know the device
-identity.
+Because the UDS, CDIs and derived values are unique, immutable, unspoofable
+hardware-bound identifiers for the device, we must limit access to them. We
+require that the values are never exposed in public APIs and are only available
+to the minimum set of system components that require access to them to function
+correctly.
 
 ### Key and cryptographic message formatting
 
@@ -195,24 +124,6 @@
 choice for algorithm implies the implementor should also choose the P256 public
 key group further down in the COSE structure.
 
-### Testability
-
-It's critical that the remote provisioning implementation be testable, to
-minimize the probability that broken devices are sold to end users. To support
-testing, the remote provisioning HAL methods take a `testMode` argument. Keys
-created in test mode are tagged to indicate this. The provisioning server will
-check for the test mode tag and issue test certificates that do not chain back
-to a trusted public key. In test mode, any EEK will be accepted, enabling
-testing tools to use EEKs for which they have the private key so they can
-validate the content of certificate requests. The BCC included in the
-`CertificateRequest` must contain freshly-generated keys, not the real BCC keys.
-
-Keystore (or similar) will need to be able to handle both testMode keys and
-production keys and keep them distinct, generating test certificate requests
-when asked with a test EEK and production certificate requests when asked with a
-production EEK. Likewise, the interface used to instruct Keystore to create keys
-will need to be able to specify whether test or production keys are desired.
-
 ## Design
 
 ### Certificate provisioning flow
@@ -220,25 +131,20 @@
 TODO(jbires): Replace this with a `.png` containing a sequence diagram.  The
 provisioning flow looks something like this:
 
-Provisioner -> Keystore: Prepare N keys
-Keystore -> KeyMint: generateKeyPair
-KeyMint -> KeyMint: Generate  key pair
-KeyMint --> Keystore: key\_blob,pubkey
-Keystore -> Keystore: Store key\_blob,pubkey
-Provisioner -> Server: Get TEEK
-Server --> Provisioner: TEEK
-Provisioner -> Keystore: genCertReq(N, TEEK)
-Keystore -> KeyMint: genCertReq(pubkeys, TEEK)
-KeyMint -> KeyMint: Sign pubkeys & encrypt BCC
-KeyMint --> Keystore: signature, encrypted BCC
-Keystore -> Keystore: Construct cert\_request
-Keystore --> Provisioner: cert\_request
-Provisioner --> Server: cert\_request
-Server -> Server: Validate cert\_request
+rkpd -> KeyMint: generateKeyPair
+KeyMint -> KeyMint: Generate key pair
+KeyMint --> rkpd: key\_blob,pubkey
+rkpd -> rkpd: Store key\_blob,pubkey
+rkpd -> Server: Get challenge
+Server --> rkpd: challenge
+rkpd -> KeyMint: genCertReq(pubkeys, challenge)
+KeyMint -> KeyMint: Sign CSR
+KeyMint --> rkpd: signed CSR
+rkpd --> Server: CSR
+Server -> Server: Validate CSR
 Server -> Server: Generate certificates
-Server --> Provisioner: certificates
-Provisioner -> Keystore: certificates
-Keystore -> Keystore: Store certificates
+Server --> rkpd: certificates
+rkpd -> rkpd: Store certificates
 
 The actors in the above diagram are:
 
@@ -246,10 +152,12 @@
     the uploaded device public keys and is responsible for providing encryption
     keys, decrypting and validating requests, and generating certificates in
     response to requests.
-*   **Provisioner** is an application that is responsible for communicating with
-    the server and all of the system components that require key certificates
-    from the server. It also implements the policy that defines how many key
-    pairs each client should keep in their pool.
+*   **rkpd** is, optionally, a modular system component that is responsible for
+    communicating with the server and all of the system components that require
+    key certificates from the server. It also implements the policy that defines
+    how many key pairs each client should keep in their pool. When a system
+    ships with rkpd as a modular component, it may be updated independently from
+    the rest of the system.
 *   **Keystore** is the [Android keystore
     daemon](https://developer.android.com/training/articles/keystore) (or, more
     generally, whatever system component manages communications with a
@@ -257,111 +165,6 @@
 *   **KeyMint** is the secure area component that manages cryptographic keys and
     performs attestations (or perhaps some other secure area component).
 
-### `BCC`
-
-The _Boot Certificate Chain_ (BCC) is the chain of certificates that contains
-DK\_pub as well as other often device-unique certificates. The BCC is
-represented as a COSE\_Key containing DK\_pub followed by an array of
-COSE\_Sign1 "certificates" containing public keys and optional additional
-information, ordered from root to leaf, with each certificate signing the next.
-The first certificate in the array is signed by DK\_pub, the last certificate
-has the KeyMint (or whatever) signing key's public key, KM\_pub. In phase 1
-there is only one entry; DK\_pub and KM\_pub are the same key and the
-certificate is self-signed.
-
-Each COSE\_Sign1 certificate is a CBOR Web Token (CWT) as described in [RFC
-8392](https://tools.ietf.org/html/rfc8392) with additional fields as described
-in the Open Profile for DICE. Of these additional fields, only the
-_subjectPublicKey_ and _keyUsage_ fields are expected to be present for the
-KM\_pub entry (that is, the last entry) in a BCC, but all fields required by the
-Open Profile for DICE are expected for other entries (each of which corresponds
-to a particular firmware component or boot stage). The CWT fields _iss_ and
-_sub_ identify the issuer and subject of the certificate and are consistent
-along the BCC entries; the issuer of a given entry matches the subject of the
-previous entry.
-
-The BCC is designed to be constructed using the Open Profile for DICE. In this
-case the DK key pair is derived from the UDS as described by that profile and
-all BCC entries before the leaf are CBOR CDI certificates chained from DK\_pub.
-The KM key pair is not part of the derived DICE chain. It is generated (not
-derived) by the KeyMint module, certified by the last key in the DICE chain, and
-added as the leaf BCC entry. The key usage field in this leaf certificate must
-indicate the key is not used to sign certificates. If a UDS certificate is
-available on the device it should appear in the certificate request as the leaf
-of a DKCertChain in AdditionalDKSignatures (see
-[CertificateRequest](#certificaterequest)).
-
-#### Mode
-
-The Open Profile for DICE specifies four possible modes with the most important
-mode being `normal`. A certificate must only set the mode to `normal` when all
-of the following conditions are met when loading and verifying the software
-component that is being described by the certificate:
-
-*   verified boot with anti-rollback protection is enabled
-*   only the verified boot authorities for production images are enabled
-*   debug ports, fuses or other debug facilities are disabled
-*   device booted software from the normal primary source e.g. internal flash
-
-If any of these conditions are not met then it is recommended to explicitly
-acknowledge this fact by using the `debug` mode. The mode should never be `not
-configured`.
-
-#### Configuration descriptor
-
-The Open Profile for DICE allows for an arbitrary configuration descriptor. For
-BCC entries, this configuration descriptor is a CBOR map with the following
-optional fields. If no fields are relevant, an empty map should be encoded.
-Additional implementation-specific fields may be added using key values not in
-the range \[-70000, -70999\] (these are reserved for future additions here).
-
-```
-| Name              | Key    | Value type | Meaning                           |
-| ----------------- | ------ | ---------- | ----------------------------------|
-| Component name    | -70002 | tstr       | Name of firmware component / boot |
-:                   :        :            : stage                             :
-| Component version | -70003 | int / tstr | Version of firmware component /   |
-:                   :        :            : boot stage                        :
-| Resettable        | -70004 | null       | If present, key changes on factory|
-:                   :        :            : reset                             :
-```
-
-Please see
-[ProtectedData.aidl](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl)
-for a full CDDL definition of the BCC.
-
-### `CertificateRequest`
-
-The full CBOR message that will be sent to the server to request certificates
-is:
-
-```cddl
-CertificateRequest = [
-    DeviceInfo,
-    challenge : bstr,       // Provided by the server
-    ProtectedData,          // See ProtectedData.aidl
-    MacedKeysToSign         // See IRemotelyProvisionedComponent.aidl
-]
-
-DeviceInfo = [
-    VerifiedDeviceInfo,     // See DeviceInfo.aidl
-    UnverifiedDeviceInfo
-]
-
-// Unverified info is anything provided by the HLOS. Subject to change out of
-// step with the HAL.
-UnverifiedDeviceInfo = {
-    ? "fingerprint" : tstr,
-}
-
-```
-
-It will be the responsibility of Keystore and the Provisioner to construct the
-`CertificateRequest`. The HAL provides a method to generate the elements that
-need to be constructed on the secure side, which are the tag field of
-`MacedKeysToSign`, `VerifiedDeviceInfo`, and the ciphertext field of
-`ProtectedData`.
-
 ### HAL
 
 The remote provisioning HAL provides a simple interface that can be implemented
diff --git a/security/rkp/aidl/Android.bp b/security/rkp/aidl/Android.bp
index e2ce649..e9e2021 100644
--- a/security/rkp/aidl/Android.bp
+++ b/security/rkp/aidl/Android.bp
@@ -28,6 +28,10 @@
         },
         rust: {
             enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.virt",
+            ],
         },
     },
     versions_with_info: [
diff --git a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 8456148..f668536 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -32,79 +32,9 @@
      * non-canonical to group similar entries semantically.
      *
      * The DeviceInfo has changed across versions 1, 2, and 3 of the HAL. All versions of the
-     * DeviceInfo CDDL are described as follows. Please refer to the CDDL structure version
-     * that corresponds to the HAL version you are working with:
+     * DeviceInfo CDDL are described in the DeviceInfoV*.cddl files. Please refer to the CDDL
+     * structure version that corresponds to the HAL version you are working with.
      *
-     * Version 3, introduced in Android 14:
-     *     DeviceInfo = {
-     *         "brand" : tstr,
-     *         "manufacturer" : tstr,
-     *         "product" : tstr,
-     *         "model" : tstr,
-     *         "device" : tstr,
-     *         "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
-     *         "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
-     *         "vbmeta_digest": bstr,                         ; Taken from the AVB values
-     *         ? "os_version" : tstr,                         ; Same as
-     *                                                        ; android.os.Build.VERSION.release
-     *                                                        ; Not optional for TEE.
-     *         "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
-     *         "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
-     *         "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
-     *         "security_level" : "tee" / "strongbox",
-     *         "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
-     *                          ; implementation is contained in. 0 otherwise.
-     *     }
-     *
-     * ---------------------------------------------------------------------------------------------
-     *
-     * Version 2, introduced in Android 13:
-     *     DeviceInfo = {
-     *         "brand" : tstr,
-     *         "manufacturer" : tstr,
-     *         "product" : tstr,
-     *         "model" : tstr,
-     *         "device" : tstr,
-     *         "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
-     *         "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
-     *         "vbmeta_digest": bstr,                         ; Taken from the AVB values
-     *         ? "os_version" : tstr,                         ; Same as
-     *                                                        ; android.os.Build.VERSION.release
-     *                                                        ; Not optional for TEE.
-     *         "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
-     *         "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
-     *         "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
-     *         "version" : 2,                                 ; The CDDL schema version.
-     *         "security_level" : "tee" / "strongbox",
-     *         "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
-     *                          ; implementation is contained in. 0 otherwise.
-     *
-     * ---------------------------------------------------------------------------------------------
-     *
-     * Version 1, introduced in Android 12:
-     *     DeviceInfo = {
-     *         ? "brand" : tstr,
-     *         ? "manufacturer" : tstr,
-     *         ? "product" : tstr,
-     *         ? "model" : tstr,
-     *         ? "board" : tstr,
-     *         ? "vb_state" : "green" / "yellow" / "orange",  ; Taken from the AVB values
-     *         ? "bootloader_state" : "locked" / "unlocked",  ; Taken from the AVB values
-     *         ? "vbmeta_digest": bstr,                       ; Taken from the AVB values
-     *         ? "os_version" : tstr,                         ; Same as
-     *                                                        ; android.os.Build.VERSION.release
-     *         ? "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
-     *         ? "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
-     *         ? "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
-     *         "version" : 1,                                 ; The CDDL schema version.
-     *         "security_level" : "tee" / "strongbox"
-     *         "att_id_state": "locked" / "open",  ; Attestation IDs State. If "locked", this
-     *                                             ; indicates a device's attestable IDs are
-     *                                             ; factory-locked and immutable. If "open",
-     *                                             ; this indicates the device is still in a
-     *                                             ; provisionable state and the attestable IDs
-     *                                             ; are not yet frozen.
-     *     }
      */
     byte[] deviceInfo;
 }
diff --git a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV1.cddl b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV1.cddl
new file mode 100644
index 0000000..056316b
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV1.cddl
@@ -0,0 +1,24 @@
+; Version 1, introduced in Android 12:
+DeviceInfo = {
+    ? "brand" : tstr,
+    ? "manufacturer" : tstr,
+    ? "product" : tstr,
+    ? "model" : tstr,
+    ? "board" : tstr,
+    ? "vb_state" : "green" / "yellow" / "orange",  ; Taken from the AVB values
+    ? "bootloader_state" : "locked" / "unlocked",  ; Taken from the AVB values
+    ? "vbmeta_digest": bstr,                       ; Taken from the AVB values
+    ? "os_version" : tstr,                         ; Same as
+                                                   ; android.os.Build.VERSION.release
+    ? "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
+    ? "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
+    ? "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
+    "version" : 1,                                 ; The CDDL schema version.
+    "security_level" : "tee" / "strongbox"
+    "att_id_state": "locked" / "open",  ; Attestation IDs State. If "locked", this
+                                        ; indicates a device's attestable IDs are
+                                        ; factory-locked and immutable. If "open",
+                                        ; this indicates the device is still in a
+                                        ; provisionable state and the attestable IDs
+                                        ; are not yet frozen.
+}
diff --git a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV2.cddl
new file mode 100644
index 0000000..e49471e
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV2.cddl
@@ -0,0 +1,21 @@
+; Version 2, introduced in Android 13:
+DeviceInfo = {
+    "brand" : tstr,
+    "manufacturer" : tstr,
+    "product" : tstr,
+    "model" : tstr,
+    "device" : tstr,
+    "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
+    "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
+    "vbmeta_digest": bstr,                         ; Taken from the AVB values
+    ? "os_version" : tstr,                         ; Same as
+                                                   ; android.os.Build.VERSION.release
+                                                   ; Not optional for TEE.
+    "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
+    "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
+    "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
+    "version" : 2,                                 ; The CDDL schema version.
+    "security_level" : "tee" / "strongbox",
+    "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
+                     ; implementation is contained in. 0 otherwise.
+}
\ No newline at end of file
diff --git a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV3.cddl b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV3.cddl
new file mode 100644
index 0000000..e841706
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfoV3.cddl
@@ -0,0 +1,20 @@
+; Version 3, introduced in Android 14:
+DeviceInfo = {
+    "brand" : tstr,
+    "manufacturer" : tstr,
+    "product" : tstr,
+    "model" : tstr,
+    "device" : tstr,
+    "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
+    "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
+    "vbmeta_digest": bstr,                         ; Taken from the AVB values
+    ? "os_version" : tstr,                         ; Same as
+                                                   ; android.os.Build.VERSION.release
+                                                   ; Not optional for TEE.
+    "system_patch_level" : uint,     ; YYYYMM, must match KeyMint OS_PATCHLEVEL
+    "boot_patch_level" : uint,       ; YYYYMMDD, must match KeyMint BOOT_PATCHLEVEL
+    "vendor_patch_level" : uint,     ; YYYYMMDD, must match KeyMint VENDOR_PATCHLEVEL
+    "security_level" : "tee" / "strongbox",
+    "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
+                     ; implementation is contained in. 0 otherwise.
+}
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 2a4cba1..21c5315 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -185,77 +185,7 @@
      *
      *        In either case, the root is self-signed.
      *
-     *            EekChain = [ + SignedSignatureKey, SignedEek ]
-     *
-     *            SignedSignatureKey = [              ; COSE_Sign1
-     *                protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
-     *                },
-     *                unprotected: {},
-     *                payload: bstr .cbor SignatureKeyEd25519 /
-     *                         bstr .cbor SignatureKeyP256,
-     *                signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
-     *                           bstr ECDSA(.cbor SignatureKeySignatureInput)
-     *            ]
-     *
-     *            SignatureKeyEd25519 = {             ; COSE_Key
-     *                 1 : 1,                         ; Key type : Octet Key Pair
-     *                 3 : AlgorithmEdDSA,            ; Algorithm
-     *                 -1 : 6,                        ; Curve : Ed25519
-     *                 -2 : bstr                      ; Ed25519 public key
-     *            }
-     *
-     *            SignatureKeyP256 = {                ; COSE_Key
-     *                 1 : 2,                         ; Key type : EC2
-     *                 3 : AlgorithmES256,            ; Algorithm
-     *                 -1 : 1,                        ; Curve: P256
-     *                 -2 : bstr,                     ; X coordinate
-     *                 -3 : bstr                      ; Y coordinate
-     *            }
-     *
-     *            SignatureKeySignatureInput = [
-     *                context: "Signature1",
-     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
-     *                external_aad: bstr .size 0,
-     *                payload: bstr .cbor SignatureKeyEd25519 /
-     *                         bstr .cbor SignatureKeyP256
-     *            ]
-     *
-     *            ; COSE_Sign1
-     *            SignedEek = [
-     *                protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
-     *                unprotected: {},
-     *                payload: bstr .cbor EekX25519 / .cbor EekP256,
-     *                signature: bstr PureEd25519(.cbor EekSignatureInput) /
-     *                           bstr ECDSA(.cbor EekSignatureInput)
-     *            ]
-     *
-     *            EekX25519 = {            ; COSE_Key
-     *                1 : 1,               ; Key type : Octet Key Pair
-     *                2 : bstr             ; KID : EEK ID
-     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 4,              ; Curve : X25519
-     *                -2 : bstr            ; X25519 public key, little-endian
-     *            }
-     *
-     *            EekP256 = {              ; COSE_Key
-     *                1 : 2,               ; Key type : EC2
-     *                2 : bstr             ; KID : EEK ID
-     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 1,              ; Curve : P256
-     *                -2 : bstr            ; Sender X coordinate
-     *                -3 : bstr            ; Sender Y coordinate
-     *            }
-     *
-     *            EekSignatureInput = [
-     *                context: "Signature1",
-     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
-     *                external_aad: bstr .size 0,
-     *                payload: bstr .cbor EekX25519 / .cbor EekP256
-     *            ]
-     *
-     *            AlgorithmES256 = -7      ; RFC 8152 section 8.1
-     *            AlgorithmEdDSA = -8      ; RFC 8152 section 8.2
+     *        See generateCertificateRequest.cddl for CDDL definitions.
      *
      *        If the contents of endpointEncryptionKey do not match the SignedEek structure above,
      *        the method must return STATUS_INVALID_EEK.
@@ -283,25 +213,9 @@
      *            HMAC-256(EK_mac, .cbor KeysToMacStructure)
      *
      *        Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below).  The MACed
-     *        data is the "tag" field of a COSE_Mac0 structure like:
+     *        data is the "tag" field of a MacedKeys COSE_Mac0 structure.
      *
-     *            MacedKeys = [                            ; COSE_Mac0
-     *                protected : bstr .cbor {
-     *                    1 : 5,                           ; Algorithm : HMAC-256
-     *                },
-     *                unprotected : {},
-     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
-     *                payload: bstr .cbor [ * PublicKey ],
-     *                tag: bstr
-     *            ]
-     *
-     *            KeysToMacStructure = [
-     *                context : "MAC0",
-     *                protected : bstr .cbor { 1 : 5 },    ; Algorithm : HMAC-256
-     *                external_aad : bstr .size 0,
-     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
-     *                payload : bstr .cbor [ * PublicKey ]
-     *            ]
+     *        See generateCertificateRequest.cddl for CDDL definitions.
      */
     byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
             in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
@@ -322,167 +236,9 @@
      *        use different semantic data for this field, but the supported sizes must be between 0
      *        and 64 bytes, inclusive.
      *
-     * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
+     * @return a CBOR Certificate Signing Request (Csr) serialized into a byte array.
      *
-     * Csr = AuthenticatedRequest<CsrPayload>
-     *
-     * CsrPayload = [                      ; CBOR Array defining the payload for Csr
-     *     version: 3,                     ; The CsrPayload CDDL Schema version.
-     *     CertificateType,                ; The type of certificate being requested.
-     *     DeviceInfo,                     ; Defined in DeviceInfo.aidl
-     *     KeysToSign,                     ; Provided by the method parameters
-     * ]
-     *
-     *  ; A tstr identifying the type of certificate. The set of supported certificate types may
-     *  ; be extended without requiring a version bump of the HAL. Custom certificate types may
-     *  ; be used, but the provisioning server may reject the request for an unknown certificate
-     *  ; type. The currently defined certificate types are:
-     *  ;  - "widevine"
-     *  ;  - "keymint"
-     *  CertificateType = tstr
-     *
-     * KeysToSign = [ * PublicKey ]   ; Please see MacedPublicKey.aidl for the PublicKey definition.
-     *
-     * AuthenticatedRequest<T> = [
-     *     version: 1,              ; The AuthenticatedRequest CDDL Schema version.
-     *     UdsCerts,
-     *     DiceCertChain,
-     *     SignedData<[
-     *         challenge: bstr .size (0..64), ; Provided by the method parameters
-     *         bstr .cbor T,
-     *     ]>,
-     * ]
-     *
-     * ; COSE_Sign1 (untagged)
-     * SignedData<Data> = [
-     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
-     *     unprotected: {},
-     *     payload: bstr .cbor Data / nil,
-     *     signature: bstr      ; PureEd25519(CDI_Leaf_Priv, SignedDataSigStruct<Data>) /
-     *                          ; ECDSA(CDI_Leaf_Priv, SignedDataSigStruct<Data>)
-     * ]
-     *
-     * ; Sig_structure for SignedData
-     * SignedDataSigStruct<Data> = [
-     *     context: "Signature1",
-     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
-     *     external_aad: bstr .size 0,
-     *     payload: bstr .cbor Data / nil,
-     * ]
-     *
-     * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
-     * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
-     * ; The SignerName is a free-form string describing who generated the signature. The root
-     * ; certificate will need to be communicated to the verifier out of band, along with the
-     * ; SignerName that is expected for the given root certificate.
-     * UdsCerts = {
-     *     * SignerName => UdsCertChain
-     * }
-     *
-     * ; SignerName is a string identifier that indicates both the signing authority as
-     * ; well as the format of the UdsCertChain
-     * SignerName = tstr
-     *
-     * UdsCertChain = [
-     *     2* X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
-     *                              ; cert, "Leaf" contains UDS_Public. There may also be
-     *                              ; intermediate certificates between Root and Leaf.
-     * ]
-     *
-     * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
-     * X509Certificate = bstr
-     *
-     * ; The DICE Chain contains measurements about the device firmware.
-     * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
-     * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
-     * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
-     * DiceCertChain = [
-     *     PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384,  ; UDS_Pub
-     *     + DiceChainEntry,                ; First CDI_Certificate -> Last CDI_Certificate
-     *                                      ; Last certificate corresponds to KeyMint's DICE key.
-     * ]
-     *
-     * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
-     * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
-     * ; defines its own configuration values for the Configuration Descriptor field. See
-     * ; the Open Profile for DICE for more details on the fields. SHA256, SHA384 and SHA512 are
-     * ; acceptable hash algorithms. The digest bstr values in the payload are the digest values
-     * ; without any padding. Note that this implies that the digest is a 32-byte bstr for SHA256
-     * ; and a 48-byte bstr for SHA384. This is an intentional, minor deviation from Open Profile
-     * ; for DICE, which specifies all digests are 64 bytes.
-     * DiceChainEntryPayload = {                    ; CWT [RFC8392]
-     *     1 : tstr,                                ; Issuer
-     *     2 : tstr,                                ; Subject
-     *     -4670552 : bstr .cbor PubKeyEd25519 /
-     *                bstr .cbor PubKeyECDSA256,
-     *                bstr .cbor PubKeyECDSA384,    ; Subject Public Key
-     *     -4670553 : bstr                          ; Key Usage
-     *
-     *     ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
-     *     ;       described above.
-     *     -4670545 : bstr,                         ; Code Hash
-     *     ? -4670546 : bstr,                       ; Code Descriptor
-     *     ? -4670547 : bstr,                       ; Configuration Hash
-     *     -4670548 : bstr .cbor {                  ; Configuration Descriptor
-     *         ? -70002 : tstr,                         ; Component name
-     *         ? -70003 : int / tstr,                   ; Component version
-     *         ? -70004 : null,                         ; Resettable
-     *     },
-     *     -4670549 : bstr,                         ; Authority Hash
-     *     ? -4670550 : bstr,                       ; Authority Descriptor
-     *     -4670551 : bstr,                         ; Mode
-     * }
-     *
-     * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
-     * ; entry in the DICE chain array.
-     * DiceChainEntry = [                            ; COSE_Sign1 (untagged)
-     *     protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
-     *     unprotected: {},
-     *     payload: bstr .cbor DiceChainEntryPayload,
-     *     signature: bstr ; PureEd25519(SigningKey, DiceChainEntryInput) /
-     *                     ; ECDSA(SigningKey, DiceChainEntryInput)
-     *                     ; See RFC 8032 for details of how to encode the signature value
-     *                     ; for Ed25519.
-     * ]
-     *
-     * DiceChainEntryInput = [
-     *     context: "Signature1",
-     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
-     *     external_aad: bstr .size 0,
-     *     payload: bstr .cbor DiceChainEntryPayload
-     * ]
-     *
-     * ; The following section defines some types that are reused throughout the above
-     * ; data structures.
-     * ; NOTE: Integer encoding is different for Ed25519 and P256 keys:
-     * ;       - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
-     * ;       - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
-     * PubKeyEd25519 = {                ; COSE_Key
-     *     1 : 1,                       ; Key type : octet key pair
-     *     3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
-     *     -1 : 6,                      ; Curve : Ed25519
-     *     -2 : bstr                    ; X coordinate, little-endian
-     * }
-     *
-     * PubKeyECDSA256 = {               ; COSE_Key
-     *     1 : 2,                       ; Key type : EC2
-     *     3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
-     *     -1 : 1,                      ; Curve: P256
-     *     -2 : bstr,                   ; X coordinate, big-endian
-     *     -3 : bstr                    ; Y coordinate, big-endian
-     * }
-     *
-     * PubKeyECDSA384 = {               ; COSE_Key
-     *     1 : 2,                       ; Key type : EC2
-     *     3 : AlgorithmES384,          ; Algorithm : ECDSA w/ SHA-384
-     *     -1 : 2,                      ; Curve: P384
-     *     -2 : bstr,                   ; X coordinate
-     *     -3 : bstr                    ; Y coordinate
-     * }
-     *
-     * AlgorithmES256 = -7
-     * AlgorithmES384 = -35
-     * AlgorithmEdDSA = -8
+     *         See generateCertificateRequestV2.cddl for CDDL definitions.
      */
     byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
 }
diff --git a/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index 1e41d1b..a290817 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -28,33 +28,8 @@
      * only to the secure environment, as proof that the public key was generated by that
      * environment. In CDDL, assuming the contained key is a P-256 public key:
      *
-     *     MacedPublicKey = [                     ; COSE_Mac0
-     *         protected: bstr .cbor { 1 : 5},    ; Algorithm : HMAC-256
-     *         unprotected: { },
-     *         payload : bstr .cbor PublicKey,
-     *         tag : bstr HMAC-256(K_mac, MAC_structure)
-     *     ]
+     * See MacedPublicKey.cddl for CDDL definition.
      *
-     *     ; NOTE: -70000 is deprecated for v3 HAL implementations.
-     *     ; NOTE: Integer encoding is different for Ed25519 and P256 keys:
-     *     ;       - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
-     *     ;       - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
-     *     PublicKey = {               ; COSE_Key
-     *         1 : 2,                  ; Key type : EC2
-     *         3 : -7,                 ; Algorithm : ES256
-     *         -1 : 1,                 ; Curve : P256
-     *         -2 : bstr,              ; X coordinate, big-endian
-     *         -3 : bstr,              ; Y coordinate, big-endian
-     *         -70000 : nil            ; Presence indicates this is a test key. If set, K_mac is
-     *                                 ; all zeros.
-     *     },
-     *
-     *     MAC_structure = [
-     *         context : "MAC0",
-     *         protected : bstr .cbor { 1 : 5 },
-     *         external_aad : bstr .size 0,
-     *         payload : bstr .cbor PublicKey
-     *     ]
      */
     byte[] macedKey;
 }
diff --git a/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.cddl b/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.cddl
new file mode 100644
index 0000000..6ae4be4
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.cddl
@@ -0,0 +1,15 @@
+MacedPublicKey = [                     ; COSE_Mac0 [RFC9052 s6.2]
+    protected: bstr .cbor { 1 : 5},    ; Algorithm : HMAC-256
+    unprotected: { },
+    payload : bstr .cbor PublicKey,
+    tag : bstr ; HMAC-256(K_mac, MAC_structure)
+]
+
+MAC_structure = [                      ; [RFC9052 s6.3]
+    context : "MAC0",
+    protected : bstr .cbor { 1 : 5 },
+    external_aad : bstr .size 0,
+    payload : bstr .cbor PublicKey
+]
+
+; INCLUDE PublicKey.cddl for: PublicKey
diff --git a/security/rkp/aidl/android/hardware/security/keymint/PublicKey.cddl b/security/rkp/aidl/android/hardware/security/keymint/PublicKey.cddl
new file mode 100644
index 0000000..4c1050d
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/PublicKey.cddl
@@ -0,0 +1,13 @@
+; NOTE: -70000 is deprecated for v3 HAL implementations.
+; NOTE: Integer encoding is different for Ed25519 and P256 keys:
+;       - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
+;       - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
+PublicKey = {               ; COSE_Key [RFC9052 s7]
+    1 : 2,                  ; Key type : EC2
+    3 : -7,                 ; Algorithm : ES256
+    -1 : 1,                 ; Curve : P256
+    -2 : bstr,              ; X coordinate, big-endian
+    -3 : bstr,              ; Y coordinate, big-endian
+    ? -70000 : nil          ; Presence indicates this is a test key. If set, K_mac is
+                            ; all zeros.
+}
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl
new file mode 100644
index 0000000..fb11492
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl
@@ -0,0 +1,93 @@
+; CDDL for the deprecated version 1 generateCertificateRequest method
+; in IRemotelyProvisionedComponent.aidl
+
+EekChain = [ + SignedSignatureKey, SignedEek ]
+
+SignedSignatureKey = [              ; COSE_Sign1 [RFC9052 s4.2]
+    protected: bstr .cbor {
+        1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
+    },
+    unprotected: {},
+    payload: bstr .cbor SignatureKeyEd25519 /
+                bstr .cbor SignatureKeyP256,
+    signature: bstr ; PureEd25519(.cbor SignatureKeySignatureInput) /
+                    ; ECDSA(.cbor SignatureKeySignatureInput)
+]
+
+SignatureKeyEd25519 = {             ; COSE_Key [RFC9052 s7]
+        1 : 1,                         ; Key type : Octet Key Pair
+        3 : AlgorithmEdDSA,            ; Algorithm
+        -1 : 6,                        ; Curve : Ed25519
+        -2 : bstr                      ; Ed25519 public key
+}
+
+SignatureKeyP256 = {                ; COSE_Key [RC9052 s7]
+        1 : 2,                         ; Key type : EC2
+        3 : AlgorithmES256,            ; Algorithm
+        -1 : 1,                        ; Curve: P256
+        -2 : bstr,                     ; X coordinate
+        -3 : bstr                      ; Y coordinate
+}
+
+SignatureKeySignatureInput = [
+    context: "Signature1",
+    body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+    external_aad: bstr .size 0,
+    payload: bstr .cbor SignatureKeyEd25519 /
+                bstr .cbor SignatureKeyP256
+]
+
+SignedEek = [                       ; COSE_Sign1 [RFC9052 s4.2]
+    protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+    unprotected: {},
+    payload: bstr .cbor EekX25519 / EekP256,
+    signature: bstr ; PureEd25519(.cbor EekSignatureInput) /
+                    ; ECDSA(.cbor EekSignatureInput)
+]
+
+EekX25519 = {            ; COSE_Key [RFC9052 s7]
+    1 : 1,               ; Key type : Octet Key Pair
+    2 : bstr             ; KID : EEK ID
+    3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+    -1 : 4,              ; Curve : X25519
+    -2 : bstr            ; X25519 public key, little-endian
+}
+
+EekP256 = {              ; COSE_Key [RFC9052 s7]
+    1 : 2,               ; Key type : EC2
+    2 : bstr             ; KID : EEK ID
+    3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+    -1 : 1,              ; Curve : P256
+    -2 : bstr            ; Sender X coordinate
+    -3 : bstr            ; Sender Y coordinate
+}
+
+EekSignatureInput = [
+    context: "Signature1",
+    body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+    external_aad: bstr .size 0,
+    payload: bstr .cbor EekX25519 / EekP256
+]
+
+AlgorithmES256 = -7      ; [RFC8152 s8.1]
+AlgorithmEdDSA = -8      ; [RFC8152 s8.2]
+
+MacedKeys = [                            ; COSE_Mac0 [RFC9052 s6.2]
+    protected : bstr .cbor {
+        1 : 5,                           ; Algorithm : HMAC-256
+    },
+    unprotected : {},
+    ; Payload is PublicKeys from keysToSign argument, in provided order.
+    payload: bstr .cbor [ * PublicKey ],
+    tag: bstr
+]
+
+KeysToMacStructure = [                   ; [RFC9052 s6.3]
+    context : "MAC0",
+    protected : bstr .cbor { 1 : 5 },    ; Algorithm : HMAC-256
+    external_aad : bstr .size 0,
+    ; Payload is PublicKeys from keysToSign argument, in provided order.
+    payload : bstr .cbor [ * PublicKey ]
+]
+
+; INCLUDE PublicKey.cddl for: PublicKey
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
new file mode 100644
index 0000000..80f7cbd
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -0,0 +1,166 @@
+; CDDL for the generateCertificateRequestV2 method in
+; IRemotelyProvisionedComponent.aidl
+
+Csr = AuthenticatedRequest<CsrPayload>
+
+CsrPayload = [                      ; CBOR Array defining the payload for Csr
+    version: 3,                     ; The CsrPayload CDDL Schema version.
+    CertificateType,                ; The type of certificate being requested.
+    DeviceInfo,                     ; Defined in the relevant DeviceInfoV*.cddl file.
+    KeysToSign,                     ; Provided by the method parameters
+]
+
+; A tstr identifying the type of certificate. The set of supported certificate types may
+; be extended without requiring a version bump of the HAL. Custom certificate types may
+; be used, but the provisioning server may reject the request for an unknown certificate
+; type. The currently defined certificate types are:
+;  - "widevine"
+;  - "keymint"
+CertificateType = tstr
+
+KeysToSign = [ * PublicKey ]   ; Please see PublicKey.cddl for the PublicKey definition.
+
+AuthenticatedRequest<T> = [
+    version: 1,              ; The AuthenticatedRequest CDDL Schema version.
+    UdsCerts,
+    DiceCertChain,
+    SignedData<[
+        challenge: bstr .size (0..64), ; Provided by the method parameters
+        bstr .cbor T,
+    ]>,
+]
+
+; COSE_Sign1 (untagged) [RFC9052 s4.2]
+SignedData<Data> = [
+    protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+    unprotected: {},
+    payload: bstr .cbor Data / nil,
+    signature: bstr     ; PureEd25519(CDI_Leaf_Priv, SignedDataSigStruct<Data>) /
+                        ; ECDSA(CDI_Leaf_Priv, SignedDataSigStruct<Data>)
+]
+
+; Sig_structure for SignedData [ RFC9052 s4.4]
+SignedDataSigStruct<Data> = [
+    context: "Signature1",
+    protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+    external_aad: bstr .size 0,
+    payload: bstr .cbor Data / nil,
+]
+
+; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
+; example, this could be provided by the hardware vendor, who certifies all of their chips.
+; The SignerName is a free-form string describing who generated the signature. The root
+; certificate will need to be communicated to the verifier out of band, along with the
+; SignerName that is expected for the given root certificate.
+UdsCerts = {
+    * SignerName => UdsCertChain
+}
+
+; SignerName is a string identifier that indicates both the signing authority as
+; well as the format of the UdsCertChain
+SignerName = tstr
+
+UdsCertChain = [
+    2* X509Certificate      ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+                            ; cert, "Leaf" contains UDS_Public. There may also be
+                            ; intermediate certificates between Root and Leaf.
+]
+
+; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
+X509Certificate = bstr
+
+; The DICE Chain contains measurements about the device firmware.
+; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
+; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
+; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+DiceCertChain = [
+    PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384,  ; UDS_Pub
+    + DiceChainEntry,               ; First CDI_Certificate -> Last CDI_Certificate
+                                    ; Last certificate corresponds to KeyMint's DICE key.
+]
+
+; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
+; defines its own configuration values for the Configuration Descriptor field. See
+; the Open Profile for DICE for more details on the fields. SHA256, SHA384 and SHA512 are
+; acceptable hash algorithms. The digest bstr values in the payload are the digest values
+; without any padding. Note that this implies that the digest is a 32-byte bstr for SHA256
+; and a 48-byte bstr for SHA384. This is an intentional, minor deviation from Open Profile
+; for DICE, which specifies all digests are 64 bytes.
+DiceChainEntryPayload = {                    ; CWT [RFC8392]
+    1 : tstr,                                ; Issuer
+    2 : tstr,                                ; Subject
+    -4670552 : bstr .cbor PubKeyEd25519 /
+            bstr .cbor PubKeyECDSA256 /
+            bstr .cbor PubKeyECDSA384,    ; Subject Public Key
+    -4670553 : bstr                          ; Key Usage
+
+    ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
+    ;       described above.
+    -4670545 : bstr,                         ; Code Hash
+    ? -4670546 : bstr,                       ; Code Descriptor
+    -4670547 : bstr,                         ; Configuration Hash
+    -4670548 : bstr .cbor {                  ; Configuration Descriptor
+        ? -70002 : tstr,                         ; Component name
+        ? -70003 : int / tstr,                   ; Component version
+        ? -70004 : null,                         ; Resettable
+        ? -70005 : uint,                         ; Security version
+    },
+    -4670549 : bstr,                         ; Authority Hash
+    ? -4670550 : bstr,                       ; Authority Descriptor
+    -4670551 : bstr,                         ; Mode
+}
+
+; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+; entry in the DICE chain array.
+DiceChainEntry = [                            ; COSE_Sign1 (untagged), [RFC9052 s4.2]
+    protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+    unprotected: {},
+    payload: bstr .cbor DiceChainEntryPayload,
+    signature: bstr ; PureEd25519(SigningKey, DiceChainEntryInput) /
+                    ; ECDSA(SigningKey, DiceChainEntryInput)
+                    ; See RFC 8032 for details of how to encode the signature value
+                    ; for Ed25519.
+]
+
+DiceChainEntryInput = [
+    context: "Signature1",
+    protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+    external_aad: bstr .size 0,
+    payload: bstr .cbor DiceChainEntryPayload
+]
+
+; The following section defines some types that are reused throughout the above
+; data structures.
+; NOTE: Integer encoding is different for Ed25519 and P256 keys:
+;       - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
+;       - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
+PubKeyEd25519 = {                ; COSE_Key [RFC9052 s7]
+    1 : 1,                       ; Key type : octet key pair
+    3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
+    -1 : 6,                      ; Curve : Ed25519
+    -2 : bstr                    ; X coordinate, little-endian
+}
+
+PubKeyECDSA256 = {               ; COSE_Key [RFC9052 s7]
+    1 : 2,                       ; Key type : EC2
+    3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
+    -1 : 1,                      ; Curve: P256
+    -2 : bstr,                   ; X coordinate, big-endian
+    -3 : bstr                    ; Y coordinate, big-endian
+}
+
+PubKeyECDSA384 = {               ; COSE_Key [RFC9052 s7]
+    1 : 2,                       ; Key type : EC2
+    3 : AlgorithmES384,          ; Algorithm : ECDSA w/ SHA-384
+    -1 : 2,                      ; Curve: P384
+    -2 : bstr,                   ; X coordinate, big-endian
+    -3 : bstr                    ; Y coordinate, big-endian
+}
+
+AlgorithmES256 = -7              ; [RFC9053 s2.1]
+AlgorithmES384 = -35             ; [RFC9053 s2.1]
+AlgorithmEdDSA = -8              ; [RFC9053 s2.2]
+
+; INCLUDE PublicKey.cddl for: PublicKey
+; INCLUDE DeviceInfoV3.cddl for: DeviceInfo
diff --git a/sensors/2.1/vts/functional/AndroidTest.xml b/sensors/2.1/vts/functional/AndroidTest.xml
index 2ef8dc6..2d21c7f 100644
--- a/sensors/2.1/vts/functional/AndroidTest.xml
+++ b/sensors/2.1/vts/functional/AndroidTest.xml
@@ -22,13 +22,13 @@
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="VtsHalSensorsV2_1TargetTest->/data/local/tmp/VtsHalSensorsV2_1TargetTest" />
+        <option name="push" value="VtsHalSensorsV2_1TargetTest->/data/local/tests/unrestricted/VtsHalSensorsV2_1TargetTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-timeout" value="900000" />
         <option name="runtime-hint" value="300000"/>
-        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="native-test-device-path" value="/data/local/tests/unrestricted" />
         <option name="module-name" value="VtsHalSensorsV2_1TargetTest" />
     </test>
 </configuration>
diff --git a/sensors/2.1/vts/functional/TEST_MAPPING b/sensors/2.1/vts/functional/TEST_MAPPING
new file mode 100644
index 0000000..0129f39
--- /dev/null
+++ b/sensors/2.1/vts/functional/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalSensorsV2_1TargetTest"
+    }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "VtsHalSensorsV2_1TargetTest"
+    }
+  ]
+}
diff --git a/sensors/aidl/TEST_MAPPING b/sensors/aidl/TEST_MAPPING
new file mode 100644
index 0000000..6de4549
--- /dev/null
+++ b/sensors/aidl/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsAidlHalSensorsTargetTest"
+    }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "VtsAidlHalSensorsTargetTest"
+    }
+  ]
+}
diff --git a/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp
index 3bdd8b6..ca3eb14 100644
--- a/sensors/aidl/default/Sensor.cpp
+++ b/sensors/aidl/default/Sensor.cpp
@@ -268,7 +268,7 @@
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
-    mSensorInfo.flags = 0;
+    mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
 };
 
 void MagnetometerSensor::readEventPayload(EventPayload& payload) {
@@ -343,7 +343,7 @@
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
     mSensorInfo.requiredPermission = "";
-    mSensorInfo.flags = 0;
+    mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
 };
 
 void GyroSensor::readEventPayload(EventPayload& payload) {
diff --git a/sensors/aidl/vts/AndroidTest.xml b/sensors/aidl/vts/AndroidTest.xml
index 99caf28..2d3382e 100644
--- a/sensors/aidl/vts/AndroidTest.xml
+++ b/sensors/aidl/vts/AndroidTest.xml
@@ -22,13 +22,13 @@
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="VtsAidlHalSensorsTargetTest->/data/local/tmp/VtsAidlHalSensorsTargetTest" />
+        <option name="push" value="VtsAidlHalSensorsTargetTest->/data/local/tests/unrestricted/VtsAidlHalSensorsTargetTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-timeout" value="900000" />
         <option name="runtime-hint" value="300000"/>
-        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="native-test-device-path" value="/data/local/tests/unrestricted" />
         <option name="module-name" value="VtsAidlHalSensorsTargetTest" />
     </test>
 </configuration>
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index 618acbb..456aee7 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -921,9 +921,15 @@
             continue;
         }
 
+        // Skip sensors with no events
+        const std::vector<Event> events = callback.getEvents(sensor.sensorHandle);
+        if (events.empty()) {
+            continue;
+        }
+
         // Ensure that the first event received is not stale by ensuring that its timestamp is
         // sufficiently different from the previous event
-        const Event newEvent = callback.getEvents(sensor.sensorHandle).front();
+        const Event newEvent = events.front();
         std::chrono::milliseconds delta =
                 duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds(
                         newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 2c1cdfb..f8c857b 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -40,6 +40,7 @@
     : mIsEnabled(false),
       mSamplingPeriodNs(0),
       mLastSampleTimeNs(0),
+      mStopThread(false),
       mCallback(callback),
       mMode(OperationMode::NORMAL) {
     mRunThread = std::thread(startThread, this);
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index aa6e881..b381580 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -806,9 +806,15 @@
             continue;
         }
 
+        // Skip sensors with no events
+        const std::vector<EventType> events = callback.getEvents(sensor.sensorHandle);
+        if (events.empty()) {
+            continue;
+        }
+
         // Ensure that the first event received is not stale by ensuring that its timestamp is
         // sufficiently different from the previous event
-        const EventType newEvent = callback.getEvents(sensor.sensorHandle).front();
+        const EventType newEvent = events.front();
         milliseconds delta = duration_cast<milliseconds>(
                 nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
         milliseconds sensorMinDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index e6e0888..a15e7fe 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -124,7 +124,8 @@
 
   private:
     static constexpr uint64_t kBufferUsage =
-            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
+            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN |
+                                  BufferUsage::CPU_WRITE_RARELY);
     AllocatorWrapperT<AllocatorT> mAllocator;
     sp<MapperT> mMapper;
 
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
deleted file mode 100644
index ed739cf..0000000
--- a/soundtrigger/2.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-elaurent@google.com
-mnaganov@google.com
-ytai@google.com
diff --git a/soundtrigger/2.0/vts/functional/OWNERS b/soundtrigger/2.0/vts/functional/OWNERS
deleted file mode 100644
index 3c24468..0000000
--- a/soundtrigger/2.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 48436
-elaurent@google.com
-mdooley@google.com
-ytai@google.com
diff --git a/soundtrigger/2.1/vts/functional/OWNERS b/soundtrigger/2.1/vts/functional/OWNERS
deleted file mode 100644
index 3c24468..0000000
--- a/soundtrigger/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 48436
-elaurent@google.com
-mdooley@google.com
-ytai@google.com
diff --git a/soundtrigger/2.2/vts/functional/OWNERS b/soundtrigger/2.2/vts/functional/OWNERS
deleted file mode 100644
index 43126f6..0000000
--- a/soundtrigger/2.2/vts/functional/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 48436
-ytai@google.com
-mdooley@google.com
diff --git a/soundtrigger/2.3/cli/OWNERS b/soundtrigger/2.3/cli/OWNERS
deleted file mode 100644
index 4fd27f3..0000000
--- a/soundtrigger/2.3/cli/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/base:/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
diff --git a/soundtrigger/2.3/vts/functional/OWNERS b/soundtrigger/2.3/vts/functional/OWNERS
deleted file mode 100644
index 3c24468..0000000
--- a/soundtrigger/2.3/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 48436
-elaurent@google.com
-mdooley@google.com
-ytai@google.com
diff --git a/soundtrigger/OWNERS b/soundtrigger/OWNERS
new file mode 100644
index 0000000..3b35d27
--- /dev/null
+++ b/soundtrigger/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 48436
+
+include platform/frameworks/base:/media/aidl/android/media/soundtrigger_middleware/OWNERS
+include platform/frameworks/base:/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
+
+elaurent@google.com
+mdooley@google.com
+mnaganov@google.com
diff --git a/soundtrigger/aidl/cli/OWNERS b/soundtrigger/aidl/cli/OWNERS
deleted file mode 100644
index 9f87c4c..0000000
--- a/soundtrigger/aidl/cli/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/base:/media/aidl/android/media/soundtrigger_middleware/OWNERS
diff --git a/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl b/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
deleted file mode 100644
index 2e7330e..0000000
--- a/staging/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-package android.hardware.media.c2;
-
-import android.hardware.common.NativeHandle;
-/**
- * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
- * output buffers. This keeps # of dequeued buffers from Surface less than
- * configured max # of dequeued buffers all the time.
- */
-parcelable SurfaceSyncObj {
-    /**
-     * ASharedMemory for synchronization data. Layout is below
-     *
-     * |lock(futex)                               4bytes|
-     * |conditional_variable(futex)               4bytes|
-     * |# of max dequeable buffer                 4bytes|
-     * |# of dequeued buffer                      4bytes|
-     * |Status of the surface                     4bytes|
-     *      INIT        = 0, Configuring surface is not finished.
-     *      ACTIVE      = 1, Surface is ready to allocate(dequeue).
-     *      SWITCHING   = 2, Switching to the new surface. It is blocked
-     *                       to allocate(dequeue) a buffer until switching
-     *                       completes.
-     */
-    NativeHandle syncMemory;
-    /**
-     * BufferQueue id.
-     */
-    long bqId;
-    /**
-     * Generation id.
-     */
-    int generationId;
-    /**
-     * Consumer usage flags. See +ndk
-     * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
-     */
-    long consumerUsage;
-}
diff --git a/tetheroffload/OWNERS b/tetheroffload/OWNERS
new file mode 100644
index 0000000..e033269
--- /dev/null
+++ b/tetheroffload/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 261923493
+
+include platform/packages/modules/Connectivity:/Tethering/OWNERS
+
+kenghua@google.com
diff --git a/tetheroffload/control/1.1/Android.bp b/tetheroffload/control/1.1/Android.bp
index 7871c2c..0daa90e 100644
--- a/tetheroffload/control/1.1/Android.bp
+++ b/tetheroffload/control/1.1/Android.bp
@@ -22,7 +22,7 @@
         "android.hidl.base@1.0",
     ],
     apex_available: [
-        "//apex_available:platform", // Used by InProcessTethering
+        "//apex_available:platform",
         "com.android.tethering",
     ],
     gen_java: true,
diff --git a/thermal/aidl/Android.bp b/thermal/aidl/Android.bp
index efc763c..9382b94 100644
--- a/thermal/aidl/Android.bp
+++ b/thermal/aidl/Android.bp
@@ -35,6 +35,9 @@
         java: {
             platform_apis: true,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 835fbfa..4b0eb65 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -128,7 +128,8 @@
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
     // Expect to fail with null callback
     status = mThermal->registerThermalChangedCallback(nullptr);
-    ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+    ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
+        || status.getExceptionCode() == EX_NULL_POINTER);
     std::shared_ptr<ThermalCallback> localThermalCallback =
             ndk::SharedRefBase::make<ThermalCallback>();
     // Expect to succeed with different callback
@@ -139,7 +140,8 @@
     ASSERT_TRUE(status.isOk()) << status.getMessage();
     // Expect to fail with null callback
     status = mThermal->unregisterThermalChangedCallback(nullptr);
-    ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+    ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
+        || status.getExceptionCode() == EX_NULL_POINTER);
 }
 
 // Test Thermal->registerThermalChangedCallbackWithType.
@@ -150,7 +152,8 @@
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
     // Expect to fail with null callback
     status = mThermal->registerThermalChangedCallbackWithType(nullptr, TemperatureType::SKIN);
-    ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+    ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
+        || status.getExceptionCode() == EX_NULL_POINTER);
     std::shared_ptr<ThermalCallback> localThermalCallback =
             ndk::SharedRefBase::make<ThermalCallback>();
     // Expect to succeed with different callback
@@ -162,7 +165,8 @@
     ASSERT_TRUE(status.isOk()) << status.getMessage();
     // Expect to fail with null callback
     status = mThermal->unregisterThermalChangedCallback(nullptr);
-    ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+    ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
+        || status.getExceptionCode() == EX_NULL_POINTER);
 }
 
 // Test Thermal->getCurrentTemperatures().
diff --git a/threadnetwork/aidl/Android.bp b/threadnetwork/aidl/Android.bp
index 5aa16a7..c621b81 100644
--- a/threadnetwork/aidl/Android.bp
+++ b/threadnetwork/aidl/Android.bp
@@ -1,6 +1,5 @@
 aidl_interface {
     name: "android.hardware.threadnetwork",
-    owner: "google",
     vendor_available: true,
     srcs: [
         "android/hardware/threadnetwork/*.aidl",
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
index bcd5704..62c8c9e 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -9,22 +9,21 @@
 //  in whole or in part, without the express written permission of
 //  Google LLC.
 
-cc_defaults {
-    name: "threadnetwork_service_default",
-    vintf_fragments: ["threadnetwork-default.xml"],
+cc_binary {
+    name: "android.hardware.threadnetwork-service",
     vendor: true,
     relative_install_path: "hw",
 
     shared_libs: [
-        "android.hardware.threadnetwork-V1-ndk",
-        "libbase",
         "libbinder_ndk",
-        "libcutils",
         "liblog",
-        "libutils",
     ],
 
     static_libs: [
+        "android.hardware.threadnetwork-V1-ndk",
+        "libbase",
+        "libcutils",
+        "libutils",
         "openthread-common",
         "openthread-hdlc",
         "openthread-platform",
@@ -33,6 +32,8 @@
         "openthread-url",
     ],
 
+    stl: "c++_static",
+
     srcs: [
         "main.cpp",
         "service.cpp",
@@ -41,22 +42,10 @@
     ],
 }
 
-cc_binary {
-    name: "android.hardware.threadnetwork-service.sim",
-    defaults: ["threadnetwork_service_default"],
-    init_rc: ["android.hardware.threadnetwork-service.sim.rc"],
-    required: ["ot-rcp"],
-}
-
-cc_binary {
-    name: "android.hardware.threadnetwork-service",
-    defaults: ["threadnetwork_service_default"],
-}
-
 cc_fuzz {
     name: "android.hardware.threadnetwork-service.fuzzer",
 
-    defaults:["service_fuzzer_defaults"],
+    defaults: ["service_fuzzer_defaults"],
     shared_libs: [
         "libbinder_ndk",
     ],
@@ -85,3 +74,36 @@
         ],
     },
 }
+
+prebuilt_etc {
+    name: "threadnetwork-default.xml",
+    src: "threadnetwork-default.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "threadnetwork-service-sim.rc",
+    src: "threadnetwork-service-sim.rc",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.threadnetwork",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.threadnetwork-service",
+        "ot-rcp",
+    ],
+    prebuilts: [
+        "threadnetwork-default.xml", // vintf_fragment
+        "threadnetwork-service-sim.rc", // init_rc
+        "android.hardware.thread_network.prebuilt.xml", // permission
+    ],
+}
diff --git a/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc b/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
deleted file mode 100644
index 2fb409c..0000000
--- a/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service vendor.threadnetwork_hal /vendor/bin/hw/android.hardware.threadnetwork-service.sim spinel+hdlc+forkpty:///vendor/bin/ot-rcp?forkpty-arg=1
-    class hal
-    user thread_network
diff --git a/threadnetwork/aidl/default/file_contexts b/threadnetwork/aidl/default/file_contexts
new file mode 100644
index 0000000..39ba3b5
--- /dev/null
+++ b/threadnetwork/aidl/default/file_contexts
@@ -0,0 +1,4 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/etc(/.*)?                                                  u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.threadnetwork-service            u:object_r:hal_threadnetwork_default_exec:s0
+/bin/ot-rcp                                                 u:object_r:ot_rcp_exec:s0
diff --git a/threadnetwork/aidl/default/manifest.json b/threadnetwork/aidl/default/manifest.json
new file mode 100644
index 0000000..61e6dc1
--- /dev/null
+++ b/threadnetwork/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.threadnetwork",
+    "version": 1
+}
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index 3d38cb8..9358eba 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -59,10 +59,6 @@
     AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump);
 }
 
-ThreadChip::~ThreadChip() {
-    AIBinder_DeathRecipient_delete(mDeathRecipient.get());
-}
-
 void ThreadChip::onBinderDiedJump(void* context) {
     reinterpret_cast<ThreadChip*>(context)->onBinderDied();
 }
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index 1ab6d54..680580a 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -34,7 +34,7 @@
 class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
   public:
     ThreadChip(char* url);
-    ~ThreadChip();
+    ~ThreadChip() {}
 
     ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
     ndk::ScopedAStatus close() override;
diff --git a/threadnetwork/aidl/default/threadnetwork-service-sim.rc b/threadnetwork/aidl/default/threadnetwork-service-sim.rc
new file mode 100644
index 0000000..3b889eb
--- /dev/null
+++ b/threadnetwork/aidl/default/threadnetwork-service-sim.rc
@@ -0,0 +1,3 @@
+service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service spinel+hdlc+forkpty:///apex/com.android.hardware.threadnetwork/bin/ot-rcp?forkpty-arg=1
+    class hal
+    user thread_network
diff --git a/tv/OWNERS b/tv/OWNERS
new file mode 100644
index 0000000..ee7f272
--- /dev/null
+++ b/tv/OWNERS
@@ -0,0 +1,12 @@
+# TV tuner
+# Bug component: 136752
+# TV input
+# Bug component: 826094
+
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
+
+hgchen@google.com
+quxiangfang@google.com
+shubang@google.com
+yixiaoluo@google.com
+
diff --git a/tv/cec/1.0/default/OWNERS b/tv/cec/1.0/default/OWNERS
deleted file mode 100644
index c1d3f1d..0000000
--- a/tv/cec/1.0/default/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
diff --git a/tv/cec/OWNERS b/tv/cec/OWNERS
deleted file mode 100644
index 71e74c0..0000000
--- a/tv/cec/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 826094
-include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
diff --git a/tv/hdmi/OWNERS b/tv/hdmi/OWNERS
deleted file mode 100644
index d9c6783..0000000
--- a/tv/hdmi/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 826094
-include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
\ No newline at end of file
diff --git a/tv/input/OWNERS b/tv/input/OWNERS
index ae65f67..e69de29 100644
--- a/tv/input/OWNERS
+++ b/tv/input/OWNERS
@@ -1,5 +0,0 @@
-# Bug component: 105688
-hgchen@google.com
-shubang@google.com
-quxiangfang@google.com
-yixiaoluo@google.com
diff --git a/tv/tuner/1.0/default/OWNERS b/tv/tuner/1.0/default/OWNERS
deleted file mode 100644
index 1b3d095..0000000
--- a/tv/tuner/1.0/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-nchalko@google.com
-amyjojo@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/1.0/vts/OWNERS b/tv/tuner/1.0/vts/OWNERS
deleted file mode 100644
index 9bdafca..0000000
--- a/tv/tuner/1.0/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 136752
-nchalko@google.com
-amyjojo@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/1.1/default/OWNERS b/tv/tuner/1.1/default/OWNERS
deleted file mode 100644
index 1b3d095..0000000
--- a/tv/tuner/1.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-nchalko@google.com
-amyjojo@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/1.1/vts/OWNERS b/tv/tuner/1.1/vts/OWNERS
deleted file mode 100644
index 9bdafca..0000000
--- a/tv/tuner/1.1/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 136752
-nchalko@google.com
-amyjojo@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/aidl/default/OWNERS b/tv/tuner/aidl/default/OWNERS
deleted file mode 100644
index bf2b609..0000000
--- a/tv/tuner/aidl/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-hgchen@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/aidl/vts/OWNERS b/tv/tuner/aidl/vts/OWNERS
deleted file mode 100644
index 5b33bf2..0000000
--- a/tv/tuner/aidl/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 136752
-
-hgchen@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/tv/tuner/config/OWNERS b/tv/tuner/config/OWNERS
deleted file mode 100644
index bf2b609..0000000
--- a/tv/tuner/config/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-hgchen@google.com
-shubang@google.com
-quxiangfang@google.com
diff --git a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
index 19830a6..0883de2 100644
--- a/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
+++ b/usb/1.1/vts/functional/VtsHalUsbV1_1TargetTest.cpp
@@ -95,6 +95,7 @@
                                             Status retval) override {
         UsbClientCallbackArgs arg;
         if (retval == Status::SUCCESS) {
+            arg.usb_last_port_status.status.portName = currentPortStatus[0].status.portName.c_str();
             arg.usb_last_port_status.status.supportedModes =
                 currentPortStatus[0].status.supportedModes;
             arg.usb_last_port_status.status.currentMode = currentPortStatus[0].status.currentMode;
@@ -165,9 +166,12 @@
     auto res = usb_cb_2->WaitForCallback(kCallbackNameNotifyPortStatusChange_1_1);
     EXPECT_TRUE(res.no_timeout);
     EXPECT_EQ(2, res.args->last_usb_cookie);
-    EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.currentMode);
-    EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.supportedModes);
-    EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
+    // if there are no type-c ports, skip below checks
+    if (!res.args->usb_last_port_status.status.portName.empty()) {
+        EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.currentMode);
+        EXPECT_EQ(PortMode::NONE, res.args->usb_last_port_status.status.supportedModes);
+        EXPECT_EQ(Status::SUCCESS, res.args->usb_last_status);
+    }
 }
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbHidlTest);
 INSTANTIATE_TEST_SUITE_P(
diff --git a/usb/OWNERS b/usb/OWNERS
index 2b1d34d..3611b4d 100644
--- a/usb/OWNERS
+++ b/usb/OWNERS
@@ -1,4 +1,8 @@
 # Bug component: 175220
 
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
 albertccwang@google.com
 badhri@google.com
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
index 9621f2c..c6d1a52 100644
--- a/uwb/aidl/default/Android.bp
+++ b/uwb/aidl/default/Android.bp
@@ -11,8 +11,8 @@
     name: "android.hardware.uwb-service",
     crate_name: "uwb_default_hal",
     relative_install_path: "hw",
-    vintf_fragments: ["uwb-service.xml"],
     vendor: true,
+    prefer_rlib: true,
     rustlibs: [
         "android.hardware.uwb-V1-rust",
         "liblogger",
@@ -30,3 +30,47 @@
         "src/service.rs",
     ],
 }
+
+prebuilt_etc {
+    name: "uwb-service.rc",
+    src: "uwb-service.rc",
+    vendor: true,
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "uwb-service.xml",
+    src: "uwb-service.xml",
+    sub_dir: "vintf",
+    vendor: true,
+    installable: false,
+}
+
+apex_key {
+    name: "com.android.hardware.uwb.key",
+    public_key: "com.android.hardware.uwb.avbpubkey",
+    private_key: "com.android.hardware.uwb.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.uwb.certificate",
+    certificate: "com.android.hardware.uwb",
+}
+
+apex {
+    name: "com.android.hardware.uwb",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.uwb.key",
+    certificate: ":com.android.hardware.uwb.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.uwb-service",
+    ],
+    prebuilts: [
+        "uwb-service.rc", // init_rc
+        "uwb-service.xml", // vintf_fragments
+    ],
+}
diff --git a/uwb/aidl/default/com.android.hardware.uwb.avbpubkey b/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
new file mode 100644
index 0000000..7a7fce8
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pem b/uwb/aidl/default/com.android.hardware.uwb.pem
new file mode 100644
index 0000000..cd38ef8
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQChE5EVDbSAKAru
+myK22LP72i2ivpJGi8DqRjgA5r6Zz3OKwtvrtSBaTtACv3j6ZALLndA2sgxbt64B
+ik1vU1tpnrGnaqcdlgDio6QIfpavWEcZ9rOHuGXvLlv3Tzc2gyr1UKsaGtce+os8
+jbfyEl4keN59oI2D8Nj1VVKYRKS+mrp4+hnvt3itGbvIKLCgGBYlcSxIiWKDfJXy
+jQEpb5pZy3wCdn2CCrTb64oclkmYbGcfoYuSBV6+PBrGa2b0b5aWm40YFbgZ5h+j
+Hlkb7sX7Vz499DK1lbm8rRt+EkHZ/9IFS1DBSj6MK3LKyGspj7BzJ25UQI23B3pM
+iaNsjBR1gGwqJxWpjuuZm9qdNPMSUUSxs/EB0GX96jnC5HFjh3sLOWKqqP6SRCZW
+xYRzjAno1L1jjPXdDqM9n2aJHu35+YVG/sFn20eIBSxH9u1hSnOw8ccc0Zo774cc
+oTJHKlL9GUO5SEGLkz3XTMEe6e55yujChymMe5jz8jkkCaXqsNDB0AMUtQ6g0Kzu
+FNUdTS2DAr/Xo7qxJ6VoDwOx/OQeDQSjSuojt/JMHEp6QMir+/axVWuxIaegjElH
+Kmx7Ie6ZGZscaTxKFEYEkWaIeJKTml0NxEitrJAibc58itj93zBMP2EDve46ghWJ
+SlmeeVmn0CuYeE8EHwZSB4I7EaHP1QIDAQABAoICADQESZnu7xdj1wPu/Wrm2FjA
+wHQJ7trxTr9ZJcTEv1CUec+Z1cNsnqILSYlZpAvYOD7hG9hN70e/LWY573+//4lA
+Qka6XnVjd625AsPrfWXqsCtmS9vMZL60zeYzorTr7veBsX+go0/RwR0w9vIplFVa
+4x7Wtlyhbq7retzJbhpPhWCEA9Qx/7qG0Ol2mnNY0+4Lei2CkFm95f6KIpHrBIFz
+AP0anrVcF8PdcKCCuAmNGFBSruvc6Beu+UaScJEHaC4C1bGtceKLOjRHHKe0mCLu
+rZ78OVQCohSYIoS4CKQJxR0IkW+aNlC1x0BNMK4fRPArD6oNnrY4p/oHiMsJAaHc
+tLWeUqvlSAdK0C5ejUzdjTiZW7rzI2gluy+BBKY1nByQsVWK7saG6hEON63idfl+
+GwPPb253n49UIk3UlUy1PxVb/othlw0dlD7p4wAlOJoRlOuJnqAifwWckS2rpNHO
+9wR1tak8hLi2LMDJqu/GlHoSqkb+JdAV5yujLQ8k1So/y/4bvNY2pRpXPydxkOew
+FY/BOoslS6RD5/XHfSJsK/Oq53Y+d04qdV7jwgrp4lqFEqMwJgzVEoC5cMvJVeK9
+/wjUdWw9hg0DSk8LVmNbIWZjZs4C39uQljmt8s+exSmzm5MSQU3K11vGRGKOsPlA
+5ZzRRaV81lBYKhATE8aRAoIBAQDfPgJ3l/38RPyoNrJuhOPH4UJj0rDX0+5ezqla
+iAXDxec55lM8qbPDW3jl/MWE3LePVokKN8DBxwZxi9Po4UEQ4hG4+zIyPcT1AQlH
++kHGG0TBtJox8J+DkG5oW79wXCn6tyl8ZLwWNa6T/3vIi3BNadnoe3AFqgcHVwHz
+e/tl0z6Tz56r/eNN6dl01+D31rirqiYRbe3982ZiX3JfS3t+AIQoxcU4suU+DC37
+G5h0zbzjgXP+ZrpPfh6O7JwH7Ac83nJAYBsVcHU4P/ZstkIWjuzleEQcDcsj3sHu
+NO2/wbReo/8Yvk0q2vUQm9IkWlU83H2KLPzIa1VuzTfPql0bAoIBAQC4tlP393ly
+krhmRLs6msAjXp5oZzoyHnrYvn+5LlKoPul98EqAW9GczLSlgjYO3w2DqnimBhU/
+YorWvkhcSJsrjiEn7CZ3UXuXoLciRiyHk/3xSDP4CLZ8tvUcEGs34LITXMPlrIk1
+WfYseSukE1TB6GDEj4MsxFILKhwnxGWeD9x9+ejOPj7+Jk3oTiZPVc67LR0MDgDz
+hRZW/8VOsequ+B/TF9LiwUHI3Ps3Geh3kKMR6DQaxXW08HDk1NGsZmKXq+O+JWFT
+3ZwCNnXqUCpm9YsD6QXTHILtBHVS5cxE65BFs08WEAqcgDhr3Yczz8L/UN/qR+FH
+RSOcymVFHQXPAoIBAQDK8Lsbbw+UGj64yGhysdnD5dINnwXmXiHPC/3Gb+sVqr3l
+060Nc5QYXvpL0PraKi+wXVFc+YwAXGZOKHfut38H0wubZreeFqsKsvN1/Fl4t2dM
+1FpsVbscxdqogedJRG9hHMrY61ZUtl5K6jDkAWaI6VYP0s7mR0f2czEx4B6M1XmI
+s3AiGD5foNtvLaS0iPz+CUJsC8wTVQZZHT2CxcKwq9V4nzkHrxFY04elQ9PXMwSo
+qRECTu7FvvgWo5/AT9/QhMPGI9fbKI1XIkZpU1JG4Y0XmboI6r0lkaYoXvNWo8fN
+VTZcjvrln4CypYRmSbw9BJAXYYg2xeQ3QtWesdfLAoIBAQCM9ifyjpvSQgITmdRA
+jySeWXEOP+j7oqMhkY+rZJyT5R8Pizdv6aJ3xQj/XfWfN736gzf7i5zfeHZ4F1Ll
+iktQ2/CVpPReDoMBXhckQuVsuhYL8owmd4+8cWtw9V69j+6WNC8Tsa4sVvE1U2to
+lZATQyHGH7d9jH0IJCTEfG8IRxZ/1R5DduFf1x+Rb0JxPQy9b1pBftZfAWvhDOQo
+gEKXMKgo0n+PqOhpP6s/i7gKtwibe9d3rsV7RhsBpyA0LxaCpRzyWViDRhXu4lzu
+aitR04U5gLV/PLz14Hcgwlo3JoY9iu+J6MgQUxG7z52EfsNTUQbwpdZYK31YBGVw
+bwulAoIBAQClsNAtbbwmExh3P0rjkgQOVy7FMQXgOyldR/LYTRI6Zbt47Jb4eO6M
+vfKK4C67/RoD1PEWgdboY8axPNj3dR1RdAuyTOOJfhJYVCW2eRS2fjSjYmUnLoFB
+N2ABYE8yKmmcPIlcJzXs3Jzeb+URxtDrvuEWPBHm8Ia1u29t42W7pg4AZHitilTl
+Su1Xi+Ic2n0NVzqZzLVUb6dKr2NFAjynthOCFXbbwD6awFeTxFIXVGT9TPTaiIlA
+Ssnh+yii4NHRoZjivUCsrfEfn+NiCzOgrfXTtUiRDvhZHdpqAIqQ6lpju7naCCwG
+vApJsLERxjCi0eqDwVx/e6xbeOVUZc/m
+-----END PRIVATE KEY-----
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pk8 b/uwb/aidl/default/com.android.hardware.uwb.pk8
new file mode 100644
index 0000000..8855197
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.pk8
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.x509.pem b/uwb/aidl/default/com.android.hardware.uwb.x509.pem
new file mode 100644
index 0000000..762ad88
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF1TCCA70CFEagTJLwbnblSQu8MjFHXcEDFQ1MMA0GCSqGSIb3DQEBCwUAMIGl
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
+LmFuZHJvaWQuaGFyZHdhcmUudXdiMCAXDTIzMDgyMTA0MTE0M1oYDzQ3NjEwNzE3
+MDQxMTQzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
+BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
+B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
+BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnV3YjCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAJpvvE7i50v4hE5VmlFTiOsQ+zOYWF+MjzEMXcqLQDzs
+26XBYJV7O3TwgrQNp1XV8KCPTAF8APEyGb237rlZO/3KvS9zYa3zFfEMPg5pnFmR
+QLWSfqrXm7ttKIQHNVAjqrLnlt8pjvKS/t/UXLAWgHiXnd2ZX62tQjyDouszLEwP
+59zJbkgX9o6fwEssdRTpuyoRoyPylfK3Thk22RBSTt+pS6pwqeUj4vttrPr7k7YU
+S5CeB7XVBRPRzXFrpasgzQqp2deOpqxC44H90+pl7QmBHFrnGk+90lcOPYgqF2Ah
+DfCBxAHzn8ioSsAJ0U34yqoNbWIUX3ZHgq1ru1uctdLwGMrKmqsw4uvfXLV+sjoi
+qUFW+9uEOHAVnmZEO2T7LAlUIoAGgdd58EJ+hdXP2yvNpGVPestrwWttAaMJoEJN
+qEWt67+iEjdEpVn0lUFo+up42mYEXGUAOpoc6t5WJinrQTY4JK/OIGJPUiOjbUTI
+T/hQTddr0HNGsKP2zRv0d49VtVht6wR0HlO1srCFZAGxRIdBtjjenu1l7ALMWlHw
+4YXLSpQoeYfavV8C3j5bzz6KaDj6HcKvRbyHRX8+JL9kFDgpOD1yI/jaaPepRAe6
+qek5jEJMEFj0tFifB8e0CZbURreXa1tErWybfuDkaNBDtAHL333/IQGI0vV7zr0x
+AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAFqnBngYd7rXHwIXHYKZuRMf+NLQxNFN
+f0m6ioFYgNnMwoMQidBHdRsJ2qTb9zfyt5O1/5Wel8Ix9aUCRbJejyX2lYXNIJNC
+ykahkoP+3CEA8QtPkmtWzNraDJRh2eYn6V5DJOWyvkz02DsHA4mxatYkF7dUfqLx
+f/y1y3cbnTyAraotTRb3W/F/zEYbcCzwlFZDT/IASVM89WRDE76+rp7/wDNJ0aEJ
+l6cQaUWDPbrvDWZaptRWfnebPtg81v03qKauwrBADddxu+/Nqs0iczBdsP1tdXr/
+Hxs47D7+fZnytVQglldBG4yky9YceL22yft/bCNDe5d7nF1/iUpJNbRIcrZxD86Z
+wwPpo0VMJ+r6VuD6UGQTS6Zyi94QD3GYYkGrPPwyrLKpp1EU6dV32bWCNp5eQojY
+FyTse/lfAJ9/Xu3klHYuR9xOaJiH+2MmtJTwKdjvK5h+EIiVbyrDJJHBd9sWav3a
+Emo+wKaIxQzXEUjWxUwy7eAAwq5WzawLMMQ97P0zIgasNIlUHW2cvBzVsQlM1tN7
+2t+7UPs5RifK5hadK6Ge1oqkG0xC1t65E7yGwrPMzKuz9aPgg7j1YAaETcKuFOHG
+rZr/0kALZc6VKNSZ8eM2P5ObrelLOe4ED9Ha1ZhmnCDXN9BP2gwqmCekwfNJ3cPA
+GObJiF81f9ZM
+-----END CERTIFICATE-----
diff --git a/uwb/aidl/default/file_contexts b/uwb/aidl/default/file_contexts
new file mode 100644
index 0000000..6ec53ed
--- /dev/null
+++ b/uwb/aidl/default/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.uwb-service          u:object_r:hal_uwb_default_exec:s0
\ No newline at end of file
diff --git a/uwb/aidl/default/manifest.json b/uwb/aidl/default/manifest.json
new file mode 100644
index 0000000..3f2f911
--- /dev/null
+++ b/uwb/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.uwb",
+    "version": 1
+}
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index 7c2c300..9587efb 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -6,7 +6,7 @@
 use async_trait::async_trait;
 use binder::{Result, Strong};
 
-use tokio::fs::File;
+use tokio::fs::{File, OpenOptions};
 use tokio::io::{AsyncReadExt, AsyncWriteExt};
 use tokio::sync::Mutex;
 
@@ -22,7 +22,7 @@
         callbacks: Strong<dyn IUwbClientCallback>,
         #[allow(dead_code)]
         tasks: tokio::task::JoinSet<()>,
-        write: File,
+        serial: File,
     },
 }
 
@@ -65,37 +65,41 @@
     async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
         log::debug!("open: {:?}", &self.path);
 
-        let serial = File::open(&self.path)
+        let serial = OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(false)
+            .open(&self.path)
             .await
             .and_then(makeraw)
             .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
 
-        let mut read = serial
-            .try_clone()
-            .await
-            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
-        let write = serial;
-
         let mut state = self.state.lock().await;
 
         if let State::Closed = *state {
             let client_callbacks = callbacks.clone();
 
             let mut tasks = tokio::task::JoinSet::new();
+            let mut reader = serial
+                .try_clone()
+                .await
+                .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
 
             tasks.spawn(async move {
                 loop {
                     const UWB_HEADER_SIZE: usize = 4;
 
                     let mut buffer = vec![0; UWB_HEADER_SIZE];
-                    read.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
+                    reader
+                        .read_exact(&mut buffer[0..UWB_HEADER_SIZE])
                         .await
                         .unwrap();
 
                     let length = buffer[3] as usize + UWB_HEADER_SIZE;
 
                     buffer.resize(length, 0);
-                    read.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
+                    reader
+                        .read_exact(&mut buffer[UWB_HEADER_SIZE..length])
                         .await
                         .unwrap();
 
@@ -108,7 +112,7 @@
             *state = State::Opened {
                 callbacks: callbacks.clone(),
                 tasks,
-                write,
+                serial,
             };
 
             Ok(())
@@ -155,8 +159,8 @@
     async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
         log::debug!("sendUciMessage");
 
-        if let State::Opened { write, .. } = &mut *self.state.lock().await {
-            write
+        if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
+            serial
                 .write(data)
                 .await
                 .map(|written| written as i32)
diff --git a/uwb/aidl/default/uwb-service.rc b/uwb/aidl/default/uwb-service.rc
new file mode 100644
index 0000000..d6a8eda
--- /dev/null
+++ b/uwb/aidl/default/uwb-service.rc
@@ -0,0 +1,3 @@
+service vendor.uwb_hal /apex/com.android.hardware.uwb/bin/hw/android.hardware.uwb-service ${ro.vendor.uwb.dev}
+    class hal
+    user uwb
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index 049ec73..00943fd 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -18,7 +18,6 @@
 #include <android-base/logging.h>
 #include <android/hardware/vr/1.0/IVr.h>
 #include <gtest/gtest.h>
-#include <hardware/vr.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
 #include <log/log.h>
diff --git a/weaver/aidl/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
index f51034a..ae816ef 100644
--- a/weaver/aidl/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
@@ -20,8 +20,8 @@
 import android.hardware.weaver.WeaverReadResponse;
 
 /**
- * Weaver provides secure storage of secret values that may only be read if the
- * corresponding key has been presented.
+ * Weaver provides secure persistent storage of secret values that may only be
+ * read if the corresponding key has been presented.
  *
  * The storage must be secure as the device's user authentication and encryption
  * relies on the security of these values. The cardinality of the domains of the
@@ -76,7 +76,8 @@
     WeaverReadResponse read(in int slotId, in byte[] key);
 
     /**
-     * Overwrites the identified slot with the provided key and value.
+     * Overwrites the identified slot with the provided key and value, rendering
+     * the previous contents of the slot permanently unrecoverable.
      *
      * The new values are written regardless of the current state of the slot in
      * order to remain idempotent.
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 7bc2eeb..83e1193 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -887,6 +887,15 @@
     return true;
 }
 
+StaLinkLayerLinkStats::StaLinkState convertLegacyMlLinkStateToAidl(wifi_link_state state) {
+    if (state == wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE) {
+        return StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE;
+    } else if (state == wifi_link_state::WIFI_LINK_STATE_IN_USE) {
+        return StaLinkLayerLinkStats::StaLinkState::IN_USE;
+    }
+    return StaLinkLayerLinkStats::StaLinkState::UNKNOWN;
+}
+
 bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats,
                                          StaLinkLayerStats* aidl_stats) {
     if (!aidl_stats) {
@@ -898,6 +907,7 @@
     for (const auto& link : legacy_ml_stats.links) {
         StaLinkLayerLinkStats linkStats = {};
         linkStats.linkId = link.stat.link_id;
+        linkStats.state = convertLegacyMlLinkStateToAidl(link.stat.state);
         linkStats.radioId = link.stat.radio;
         linkStats.frequencyMhz = link.stat.frequency;
         linkStats.beaconRx = link.stat.beacon_rx;
diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
index 5c334f8..995a13d 100644
--- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
+++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
@@ -123,6 +123,9 @@
     // Add two radio stats
     legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
     legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+    wifi_link_state states[sizeof(wifi_link_state)] = {wifi_link_state::WIFI_LINK_STATE_UNKNOWN,
+                                                       wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE,
+                                                       wifi_link_state::WIFI_LINK_STATE_IN_USE};
     // Add two links.
     legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
     legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
@@ -133,6 +136,7 @@
         link.stat.beacon_rx = rand();
         // MLO link id: 0 - 15
         link.stat.link_id = rand() % 16;
+        link.stat.state = states[rand() % sizeof(states)];
         // Maximum number of radios is limited to 3 for testing.
         link.stat.radio = rand() % 4;
         link.stat.frequency = rand();
@@ -241,6 +245,18 @@
     int l = 0;
     for (legacy_hal::LinkStats& link : legacy_ml_stats.links) {
         EXPECT_EQ(link.stat.link_id, (uint8_t)converted.iface.links[l].linkId);
+        StaLinkLayerLinkStats::StaLinkState expectedState;
+        switch (link.stat.state) {
+            case wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE:
+                expectedState = StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE;
+                break;
+            case wifi_link_state::WIFI_LINK_STATE_IN_USE:
+                expectedState = StaLinkLayerLinkStats::StaLinkState::IN_USE;
+                break;
+            default:
+                expectedState = StaLinkLayerLinkStats::StaLinkState::UNKNOWN;
+        }
+        EXPECT_EQ(expectedState, converted.iface.links[l].state);
         EXPECT_EQ(link.stat.radio, converted.iface.links[l].radioId);
         EXPECT_EQ(link.stat.frequency, (uint32_t)converted.iface.links[l].frequencyMhz);
         EXPECT_EQ(link.stat.beacon_rx, (uint32_t)converted.iface.links[l].beaconRx);
diff --git a/wifi/aidl/default/wifi.cpp b/wifi/aidl/default/wifi.cpp
index 34a7f35..255266b 100644
--- a/wifi/aidl/default/wifi.cpp
+++ b/wifi/aidl/default/wifi.cpp
@@ -16,6 +16,7 @@
 
 #include "wifi.h"
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 
 #include "aidl_return_util.h"
@@ -91,6 +92,7 @@
         if (!chip.get()) continue;
         chip->dump(fd, args, numArgs);
     }
+    ::android::base::WriteStringToFd("\n", fd);
     return STATUS_OK;
 }
 
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
index 6dd9156..8265e5b 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -1452,14 +1452,24 @@
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
                    << legacyErrorToString(legacy_status);
+        if (legacy_matrix != nullptr) {
+            free(legacy_matrix);
+        }
         return {aidl_combinations, createWifiStatusFromLegacyError(legacy_status)};
     }
 
     if (!aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix,
                                                                       &aidl_combinations)) {
         LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToAidl() ";
+        if (legacy_matrix != nullptr) {
+            free(legacy_matrix);
+        }
         return {aidl_combinations, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
     }
+
+    if (legacy_matrix != nullptr) {
+        free(legacy_matrix);
+    }
     return {aidl_combinations, ndk::ScopedAStatus::ok()};
 }
 
diff --git a/wifi/aidl/default/wifi_feature_flags.cpp b/wifi/aidl/default/wifi_feature_flags.cpp
index 3c9f042..35b4b4a 100644
--- a/wifi/aidl/default/wifi_feature_flags.cpp
+++ b/wifi/aidl/default/wifi_feature_flags.cpp
@@ -122,6 +122,7 @@
 #define AP IfaceConcurrencyType::AP
 #define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED
 #define P2P IfaceConcurrencyType::P2P
+#undef NAN  // undefine NAN from math.h
 #define NAN IfaceConcurrencyType::NAN_IFACE
 static const std::vector<IWifiChip::ChipMode> kChipModesPrimary{
         {kMainModeId, legacyToChipConcurrencyComboList({WIFI_HAL_INTERFACE_COMBINATIONS})},
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
index ca3c4b7..986e3a8 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -197,9 +197,26 @@
 
 bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
                                            IfaceConcurrencyType type, int* configured_mode_id) {
+    if (!wifi_chip.get()) {
+        return false;
+    }
     return configureChipToSupportConcurrencyTypeInternal(wifi_chip, type, configured_mode_id);
 }
 
+bool doesChipSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
+                                    IfaceConcurrencyType type) {
+    if (!wifi_chip.get()) {
+        return false;
+    }
+    std::vector<IWifiChip::ChipMode> chip_modes;
+    auto status = wifi_chip->getAvailableModes(&chip_modes);
+    if (!status.isOk()) {
+        return false;
+    }
+    int mode_id;
+    return findAnyModeSupportingConcurrencyType(type, chip_modes, &mode_id);
+}
+
 void stopWifiService(const char* instance_name) {
     std::shared_ptr<IWifi> wifi = getWifi(instance_name);
     if (wifi != nullptr) {
@@ -208,6 +225,9 @@
 }
 
 int32_t getChipFeatureSet(const std::shared_ptr<IWifiChip>& wifi_chip) {
+    if (!wifi_chip.get()) {
+        return 0;
+    }
     int32_t features = 0;
     if (wifi_chip->getFeatureSet(&features).isOk()) {
         return features;
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
index 0d70c3b..921d689 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -42,6 +42,9 @@
 // Configure the chip in a mode to support the creation of the provided iface type.
 bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
                                            IfaceConcurrencyType type, int* configured_mode_id);
+// Check whether the chip supports the creation of the provided iface type.
+bool doesChipSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
+                                    IfaceConcurrencyType type);
 // Used to trigger IWifi.stop() at the end of every test.
 void stopWifiService(const char* instance_name);
 int32_t getChipFeatureSet(const std::shared_ptr<IWifiChip>& wifi_chip);
diff --git a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
index bbd27f9..740f833 100644
--- a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
@@ -63,6 +63,10 @@
         return mode_id;
     }
 
+    bool isConcurrencyTypeSupported(IfaceConcurrencyType type) {
+        return doesChipSupportConcurrencyType(wifi_chip_, type);
+    }
+
     std::shared_ptr<IWifiStaIface> configureChipForStaAndGetIface() {
         std::shared_ptr<IWifiStaIface> iface;
         configureChipForConcurrencyType(IfaceConcurrencyType::STA);
@@ -532,6 +536,9 @@
  * CreateApIface
  */
 TEST_P(WifiChipAidlTest, CreateApIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+        GTEST_SKIP() << "AP is not supported";
+    }
     configureChipForApAndGetIface();
 }
 
@@ -549,6 +556,9 @@
  * CreateP2pIface
  */
 TEST_P(WifiChipAidlTest, CreateP2pIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::P2P)) {
+        GTEST_SKIP() << "P2P is not supported";
+    }
     configureChipForP2pAndGetIface();
 }
 
@@ -583,6 +593,9 @@
  * GetP2pIfaceNames
  */
 TEST_P(WifiChipAidlTest, GetP2pIfaceNames) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::P2P)) {
+        GTEST_SKIP() << "P2P is not supported";
+    }
     configureChipForConcurrencyType(IfaceConcurrencyType::P2P);
 
     std::vector<std::string> iface_names;
@@ -607,6 +620,9 @@
  * GetApIfaceNames
  */
 TEST_P(WifiChipAidlTest, GetApIfaceNames) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+        GTEST_SKIP() << "AP is not supported";
+    }
     configureChipForConcurrencyType(IfaceConcurrencyType::AP);
 
     std::vector<std::string> iface_names;
@@ -679,6 +695,9 @@
  * GetP2pIface
  */
 TEST_P(WifiChipAidlTest, GetP2pIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::P2P)) {
+        GTEST_SKIP() << "P2P is not supported";
+    }
     std::shared_ptr<IWifiP2pIface> iface = configureChipForP2pAndGetIface();
     std::string iface_name = getP2pIfaceName(iface);
 
@@ -697,6 +716,9 @@
  * GetApIface
  */
 TEST_P(WifiChipAidlTest, GetApIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+        GTEST_SKIP() << "AP is not supported";
+    }
     std::shared_ptr<IWifiApIface> iface = configureChipForApAndGetIface();
     std::string iface_name = getApIfaceName(iface);
 
@@ -755,6 +777,9 @@
  * RemoveP2pIface
  */
 TEST_P(WifiChipAidlTest, RemoveP2pIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::P2P)) {
+        GTEST_SKIP() << "P2P is not supported";
+    }
     std::shared_ptr<IWifiP2pIface> iface = configureChipForP2pAndGetIface();
     std::string iface_name = getP2pIfaceName(iface);
 
@@ -771,6 +796,9 @@
  * RemoveApIface
  */
 TEST_P(WifiChipAidlTest, RemoveApIface) {
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+        GTEST_SKIP() << "AP is not supported";
+    }
     std::shared_ptr<IWifiApIface> iface = configureChipForApAndGetIface();
     std::string iface_name = getApIfaceName(iface);