Merge "Switch hostapd VTS tests to NDK backend."
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index d2ba339..8c92cbd 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -102,6 +102,9 @@
             if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
             auto [flags, isOffload] = generateOutFlags(mixPort);
             for (const auto& profile : mixPort.getProfile()) {
+                if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+                    !profile.hasChannelMasks())
+                    continue;
                 auto configs = combineAudioConfig(profile.getChannelMasks(),
                                                   profile.getSamplingRates(), profile.getFormat());
                 for (auto& config : configs) {
@@ -231,6 +234,9 @@
                                std::back_inserter(flags), [](auto flag) { return toString(flag); });
             }
             for (const auto& profile : mixPort.getProfile()) {
+                if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+                    !profile.hasChannelMasks())
+                    continue;
                 auto configs = combineAudioConfig(profile.getChannelMasks(),
                                                   profile.getSamplingRates(), profile.getFormat());
                 for (const auto& config : configs) {
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index e446a7f..c576060 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -239,6 +239,7 @@
     data: [
         "tests/apm_config_no_vx_7_0.xml",
         "tests/apm_config_with_vx_7_0.xml",
+        "tests/apm_config_b_204314749_7_0.xml",
     ],
     test_config: "tests/HalAudioV7_0GeneratorTest.xml",
 }
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
index 2e79455..3dc5b33 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
@@ -24,6 +24,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="apm_config_no_vx_7_0.xml->/data/local/tmp/apm_config_no_vx.xml" />
         <option name="push" value="apm_config_with_vx_7_0.xml->/data/local/tmp/apm_config_with_vx.xml" />
+        <option name="push" value="apm_config_b_204314749_7_0.xml->/data/local/tmp/apm_config_b_204314749_7_0.xml" />
         <option name="push" value="HalAudioV7_0GeneratorTest->/data/local/tmp/HalAudioV7_0GeneratorTest" />
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
new file mode 100644
index 0000000..5bdca9a
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="false"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="3.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+                <item>Echo Reference</item>
+                <item>Tuner</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="tunnel pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="direct pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="tunnel direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000"
+                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="primary input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="tunnel a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="direct a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="echo reference" role="sink">
+                    <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="built-in mic" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="16000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="ble_in" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER">
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-10000"
+                              maxValueMB="0"
+                              defaultValueMB="-6000"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+                </devicePort>
+                <devicePort tagName="Tuner" role="source" type="AUDIO_DEVICE_IN_TV_TUNER">
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-10000"
+                              maxValueMB="0"
+                              defaultValueMB="-6000"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source" address="top">
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Echo Reference" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
+                    <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BLE-In" type="AUDIO_DEVICE_IN_BLUETOOTH_BLE" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="HDMI Out"
+                       sources="primary output,tunnel pcm,direct output,Tuner,mmap_no_irq_out,tunnel direct output"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,tunnel pcm,direct pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT SCO"
+                       sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT SCO Headset"
+                       sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,Tuner"/>
+                <route type="mix" sink="BT A2DP Out"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT A2DP Headphones"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT A2DP Speaker"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="echo reference"
+                       sources="Echo Reference"/>
+                <route type="mix" sink="built-in mic"
+                       sources="Built-In Mic"/>
+                <route type="mix" sink="ble_in"
+                       sources="BLE-In"/>
+            </routes>
+
+        </module>
+
+        <!-- A2dp Audio HAL -->
+        <!-- <xi:include href="a2dp_audio_policy_configuration.xml"/> -->
+
+        <!-- Usb Audio HAL -->
+        <!-- <xi:include href="usb_audio_policy_configuration.xml"/> -->
+
+        <!-- Remote Submix Audio HAL -->
+        <!-- <xi:include href="r_submix_audio_policy_configuration.xml"/> -->
+
+        <!-- Hearing aid Audio HAL -->
+        <!-- <xi:include href="hearing_aid_audio_policy_configuration.xml"/> -->
+
+        <!-- MSD Audio HAL (optional) -->
+        <!-- <xi:include href="msd_audio_policy_configuration.xml"/> -->
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section -->
+
+    <!-- <xi:include href="audio_policy_volumes.xml"/> -->
+    <!-- <xi:include href="default_volume_tables.xml"/> -->
+
+    <!-- End of Volume section -->
+
+    <!-- Surround Sound configuration -->
+
+    <surroundSound>
+    <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+        There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+        and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+        need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
+        <formats>
+            <format name="AUDIO_FORMAT_AC3" />
+            <format name="AUDIO_FORMAT_E_AC3" />
+            <format name="AUDIO_FORMAT_E_AC3_JOC" />
+            <format name="AUDIO_FORMAT_DTS" />
+        </formats>
+    </surroundSound>
+
+    <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 583ff01..7caa712 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -128,5 +128,11 @@
 }
 
 // Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs
+// clang-format off
 INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest,
-                         ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"));
+                         ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"
+#if MAJOR_VERSION == 7
+                                         , "apm_config_b_204314749_7_0.xml"
+#endif
+                                           ));
+// clang-format on
diff --git a/cas/1.0/vts/functional/OWNERS b/cas/1.0/vts/functional/OWNERS
index aec93b0..7d8c2ee 100644
--- a/cas/1.0/vts/functional/OWNERS
+++ b/cas/1.0/vts/functional/OWNERS
@@ -1,2 +1,2 @@
 # Bug component: 1344
-quxiangfang@google.com
+include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.1/vts/functional/OWNERS b/cas/1.1/vts/functional/OWNERS
index 29246ed..7d8c2ee 100644
--- a/cas/1.1/vts/functional/OWNERS
+++ b/cas/1.1/vts/functional/OWNERS
@@ -1,3 +1,2 @@
-nchalko@google.com
-chz@google.com
-quxiangfang@google.com
+# Bug component: 1344
+include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.2/vts/functional/OWNERS b/cas/1.2/vts/functional/OWNERS
index 29246ed..4c55752 100644
--- a/cas/1.2/vts/functional/OWNERS
+++ b/cas/1.2/vts/functional/OWNERS
@@ -1,3 +1,3 @@
-nchalko@google.com
-chz@google.com
+# Bug component: 1344
 quxiangfang@google.com
+hgchen@google.com
diff --git a/health/aidl/README.md b/health/aidl/README.md
new file mode 100644
index 0000000..53a4f91
--- /dev/null
+++ b/health/aidl/README.md
@@ -0,0 +1,293 @@
+# Health AIDL HAL
+
+## Determine whether the example service implementation is sufficient {#determine}
+
+You need a custom implementation if any of the following is true:
+
+* You are migrating from a custom
+  [health 2.1 HIDL HAL implementation](../2.1/README.md).
+* System properties `ro.charger.enable_suspend` and/or `ro.charger.no_ui`
+  are set to a `true` value. See [below](#charger-sysprops).
+* The device supports offline charging mode, and the `service`
+  declaration with `class charger` in `init.rc` is different from the one
+  provided by the example implementation. See [below](#charger-init-rc).
+
+If the example HAL service is sufficient, [install it](#use-example). Otherwise,
+[implement a custom HAL service](#use-custom).
+
+### System properties for charger {#charger-sysprops}
+
+The health AIDL HAL service also provides functionalities of `charger`. As a
+result, the system charger at `/system/bin/charger` is deprecated.
+
+However, the health AIDL HAL service is not allowed to read `ro.charger.*`
+system properties. These properties include:
+* `ro.charger.enable_suspend`. If set, you need a custom health AIDL HAL
+  service. See [below](#charger-enable-suspend).
+* `ro.charger.no_ui`. If set, you need a custom health AIDL HAL service.
+  See [below](#charger-no-ui).
+* `ro.charger.draw_split_screen`. The system property is deprecated.
+* `ro.charger.draw_split_offset`. The system property is deprecated.
+* `ro.charger.disable_init_blank`. The system property is deprecated.
+
+If you need to set any of the deprecated system properties, contact
+[OWNERS](OWNERS).
+
+### Default `service` declaration for charger in `init.rc` {#charger-init-rc}
+
+See
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc).
+
+Check the `service` declaration in your device-specific `init.rc` file that
+has `class charger`. Most likely, the declaration looks something like this
+(Below is an excerpt from Pixel 3):
+
+```text
+service vendor.charger /system/bin/charger
+    class charger
+    seclabel u:r:charger:s0
+    user system
+    group system wakelock input
+    capabilities SYS_BOOT
+    file /dev/kmsg w
+    file /sys/fs/pstore/console-ramoops-0 r
+    file /sys/fs/pstore/console-ramoops r
+    file /proc/last_kmsg r
+```
+
+Compare each line against the one provided by the example health AIDL HAL
+service in
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc).
+Specifically:
+
+* You may ignore the `service` line. The name of the service does not matter.
+* If your service belongs to additional classes beside `charger`, you need a
+  custom health AIDL service.
+* You may ignore the `seclabel` line. When the health AIDL service runs in
+  charger mode, its original SELinux domain is kept.
+* If your service has a different `user` (not `system`), you need a custom
+  health AIDL service.
+* If your service belongs to additional `group`s beside
+  `system wakelock input`, you need a custom health AIDL service.
+* If your service requires additional capabilities beside `SYS_BOOT`,
+  you need a custom health AIDL service.
+* If your service requires additional `file`s to be opened prior to execution,
+  you need a custom health AIDL service.
+
+## Using the example health AIDL HAL service {#use-example}
+
+If you [determined](#determine) that the example health AIDL HAL service works
+for your device, install it with
+
+```mk
+PRODUCT_PACKAGES += android.hardware.health-service.example
+```
+
+Then, delete any existing `service` with `class charger` in your device-specific
+`init.rc` files, because
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc)
+already contains an entry for charger.
+
+If your device supports charger mode and it has custom charger resources,
+[move charger resources to `/vendor`](#charger-res)
+
+## Implementing a custom health AIDL HAL service {#use-custom}
+
+### Override the `Health` class {#health-impl}
+
+See [`Health.h`](default/include/health-impl/Health.h) for its class
+declaration. Inherit the class to customize for your device.
+
+```c++
+namespace aidl::android::hardware::health {
+class HealthImpl : public Health {
+    // ...
+};
+} // namespace aidl::android::hardware::health
+int main(int, char**) {
+    // ...
+    auto binder = ndk::SharedRefBase::make<aidl::android::hardware::health::HealthImpl>(
+            "default", std::move(config));
+    // ...
+}
+```
+
+* The logic to modify `healthd_config`, traditionally in `healthd_board_init()`
+  should be called before passing the `healthd_config` struct to your
+  `HealthImpl` class in [`main()`](#main).
+
+* The following functions are similar to the ones in the health 2.1 HIDL HAL:
+
+| AIDL implementation                 | HIDL implementation         |
+|-------------------------------------|-----------------------------|
+| `Health::getChargeCounterUah`       | `Health::getChargeCounter`  |
+| `Health::getCurrentNowMicroamps`    | `Health::getCurrentNow`     |
+| `Health::getCurrentAverageMicroamps`| `Health::getCurrentAverage` |
+| `Health::getCapacity`               | `Health::getCapacity`       |
+| `Health::getChargeStatus`           | `Health::getChargeStatus`   |
+| `Health::getEnergyCounterNwh`       | `Health::getEnergyCounter`  |
+| `Health::getDiskStats`              | `Health::getDiskStats`      |
+| `Health::getStorageInfo`            | `Health::getStorageInfo`    |
+| `Health::BinderEvent`               | `BinderHealth::BinderEvent` |
+| `Health::dump`                      | `Health::debug`             |
+| `Health::ShouldKeepScreenOn`        | `Health::shouldKeepScreenOn`|
+| `Health::UpdateHealthInfo`          | `Health::UpdateHealthInfo`  |
+
+### Implement `main()` {#main}
+
+See the [`main.cpp`](default/main.cpp) for the example health AIDL service for
+an example.
+
+If you need to modify `healthd_config`, do it before passing it to the
+constructor of `HealthImpl` (or `Health` if you did not implement a subclass
+of it).
+
+```c++
+int main(int argc, char** argv) {
+    auto config = std::make_unique<healthd_config>();
+    ::android::hardware::health::InitHealthdConfig(config.get());
+    healthd_board_init(config.get());
+    auto binder = ndk::SharedRefBase::make<Health>("default", std::move(config));
+    // ...
+}
+```
+
+If your device does not support off-line charging mode, or does not have a UI
+for charger (`ro.charger.no_ui=true`), skip the invocation of
+`ChargerModeMain()` in `main()`.
+
+### SELinux rules
+
+Add device specific permissions to the domain where the health HAL
+process is executed, especially if a device-specific `libhealthd` is used
+and/or device-specific storage related APIs are implemented.
+
+If you did not define a separate domain, the domain is likely
+`hal_health_default`. The device-specific rules for it is likely at
+`device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te`.
+
+### Implementing charger {#charger}
+
+#### Move charger resources to `/vendor`
+
+Ensure that charger resources are installed to `/vendor`, not `/product`.
+
+`animation.txt` must be moved to the following location:
+
+```text
+/vendor/etc/res/values/charger/animation.txt
+```
+
+Charger resources in `/system` is not read by the health HAL service in
+`/vendor`. Specifically, resources should be installed to the following
+location:
+
+```
+/vendor/etc/res/images/charger/*.png
+```
+
+If resources are not found in these locations, the health HAL service falls
+back to the following locations:
+
+```
+/vendor/etc/res/images/charger/default/*.png
+```
+
+You can use the default resources by installing the default module:
+
+```makefile
+PRODUCT_PACKAGES += charger_res_images_vendor
+```
+
+#### Modify `init.rc` for charger
+
+It is recommended that you move the existing `service` entry with
+`class charger` to the `init.rc` file in your custom health service.
+
+Modify the entry to invoke the health service binary with `--charger` argument.
+See
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc)
+for an example:
+
+```text
+service vendor.charger-tuna /vendor/bin/hw/android.hardware.health-service-tuna --charger
+    # ...
+```
+
+#### No charger mode {#no-charger}
+
+If your device does not support off-line charging mode, skip the invocation of
+`ChargerModeMain()` in `main()`.
+
+```c++
+int main(int, char**) {
+    // ...
+    // Skip checking if arguments contain "--charger"
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
+    return hal_health_loop->StartLoop();
+}
+```
+
+You may optionally delete the `service` entry with `class charger` in the
+`init.rc` file.
+
+#### No charger UI {#charger-no-ui}
+
+If your device does not have a UI for charger (`ro.charger.no_ui=true`), skip
+the invocation of `ChargerModeMain()` in `main()`.
+
+You may want to keep the `KernelLogger` so that charger still logs battery
+information to the kernel logs.
+
+```c++
+int main(int argc, char** argv) {
+    // ...
+    if (argc >= 2 && argv[1] == "--charger"sv) {
+        android::base::InitLogging(argv, &android::base::KernelLogger);
+        // fallthrough to HalHealthLoop::StartLoop()
+    }
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
+    return hal_health_loop->StartLoop();
+}
+```
+
+#### Enable suspend {#charger-enable-suspend}
+
+If your device has `ro.charger.enable_suspend=true`, implement a new class,
+`ChargerCallbackImpl`, that inherits from
+[`ChargerCallback`](default/include/health-impl/ChargerUtils.h). Then
+override the `ChargerEnableSuspend` function to return `true`. Then pass an
+instance of `ChargerCallbackImpl` to `ChargerModeMain()` instead.
+
+```c++
+namespace aidl::android::hardware::health {
+class ChargerCallbackImpl : public ChargerCallback {
+    bool ChargerEnableSuspend() override { return true; }
+};
+} // namespace aidl::android::hardware::health
+int main(int argc, char** argv) {
+    // ...
+    if (argc >= 2 && argv[1] == "--charger"sv) {
+        android::base::InitLogging(argv, &android::base::KernelLogger);
+#if !CHARGER_FORCE_NO_UI
+        return ChargerModeMain(binder,
+                std::make_shared<aidl::android::hardware::health::ChargerCallbackImpl>(binder));
+#endif
+    }
+    // ...
+}
+```
+
+#### SELinux rules for charger
+
+If your health AIDL service runs in a domain other than `hal_health_default`,
+add `charger_type` to it so the health HAL service can have charger-specific
+permissions. Example (assuming that your health AIDL service runs in domain
+`hal_health_tuna`:
+
+```text
+type hal_health_tuna, charger_type, domain;
+hal_server_domain(hal_health_default, hal_health)
+```
+
+[comment: TODO(b/170338625): explain recovery]: #
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index 7e635d4..a13c677 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -45,6 +45,52 @@
     ],
 }
 
+// Dependency to libhealthd_charger_ui. No UI in recovery.
+cc_defaults {
+    name: "libhealth_aidl_charger_defaults",
+    shared_libs: [
+        // common
+        "android.hardware.health-V1-ndk",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+
+        // charger UI only
+        "libpng",
+    ],
+
+    static_libs: [
+        // common
+        "libbatterymonitor",
+        "libhealthloop",
+
+        // charger UI only
+        "libhealthd_draw",
+        "libhealthd_charger_ui",
+        "libminui",
+        "libsuspend",
+    ],
+
+    target: {
+        recovery: {
+            // No UI and libsuspend for recovery charger.
+            cflags: [
+                "-DCHARGER_FORCE_NO_UI=1",
+            ],
+            exclude_shared_libs: [
+                "libpng",
+            ],
+            exclude_static_libs: [
+                "libhealthd_draw",
+                "libhealthd_charger_ui",
+                "libminui",
+                "libsuspend",
+            ],
+        },
+    },
+}
+
 // AIDL version of libhealth2impl.
 // A helper library for health HAL implementation.
 // HAL implementations can link to this library and extend the Health class.
@@ -52,21 +98,26 @@
     name: "libhealth_aidl_impl",
     defaults: [
         "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
     ],
     export_include_dirs: ["include"],
     export_static_lib_headers: [
         "libbatterymonitor",
     ],
     srcs: [
+        "ChargerUtils.cpp",
         "health-convert.cpp",
         "HalHealthLoop.cpp",
         "Health.cpp",
         "LinkedCallback.cpp",
     ],
-    visibility: [
-        ":__subpackages__",
-        "//hardware/interfaces/tests/extension/health:__subpackages__",
-    ],
+    target: {
+        recovery: {
+            exclude_srcs: [
+                "ChargerUtils.cpp",
+            ],
+        },
+    },
 }
 
 // AIDL version of android.hardware.health@2.1-service.
@@ -78,9 +129,13 @@
     vintf_fragments: ["android.hardware.health-service.example.xml"],
     defaults: [
         "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
     ],
     static_libs: [
         "libhealth_aidl_impl",
     ],
     srcs: ["main.cpp"],
+    overrides: [
+        "charger",
+    ],
 }
diff --git a/health/aidl/default/ChargerUtils.cpp b/health/aidl/default/ChargerUtils.cpp
new file mode 100644
index 0000000..f8e208b
--- /dev/null
+++ b/health/aidl/default/ChargerUtils.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <health-impl/ChargerUtils.h>
+
+namespace aidl::android::hardware::health::charger {
+
+std::optional<bool> ChargerCallback::ChargerShouldKeepScreenOn() {
+    return service_->ShouldKeepScreenOn();
+}
+
+bool ChargerCallback::ChargerIsOnline() {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        // Assume no charger
+        return false;
+    }
+    return hal_health_loop_sp->charger_online();
+}
+
+void ChargerCallback::ChargerInitConfig(healthd_config* config) {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        return;
+    }
+    return service_->OnInit(hal_health_loop_sp.get(), config);
+}
+
+int ChargerCallback::ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        return -1;
+    }
+    return hal_health_loop_sp->RegisterEvent(fd, func, wakeup);
+}
+
+void ChargerCallback::set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop) {
+    hal_health_loop_ = std::move(hal_health_loop);
+}
+
+// Implements HalHealthLoopCallback for AIDL charger
+// Adapter of (Charger, Health) ->  HalHealthLoopCallback
+class LoopCallback : public HalHealthLoopCallback {
+  public:
+    LoopCallback(const std::shared_ptr<Health>& service, ChargerCallback* charger_callback)
+        : service_(service), charger_(std::make_unique<::android::Charger>(charger_callback)) {}
+
+    void OnHeartbeat() override {
+        service_->OnHeartbeat();
+        charger_->OnHeartbeat();
+    }
+    // Return the minimum timeout. Negative values are treated as no values.
+    int OnPrepareToWait() override {
+        int timeout1 = service_->OnPrepareToWait();
+        int timeout2 = charger_->OnPrepareToWait();
+
+        if (timeout1 < 0) return timeout2;
+        if (timeout2 < 0) return timeout1;
+        return std::min(timeout1, timeout2);
+    }
+
+    void OnInit(HalHealthLoop*, struct healthd_config* config) override {
+        // Charger::OnInit calls ChargerInitConfig, which calls into the real Health::OnInit.
+        charger_->OnInit(config);
+    }
+
+    void OnHealthInfoChanged(const HealthInfo& health_info) override {
+        charger_->OnHealthInfoChanged(::android::ChargerHealthInfo{
+                .battery_level = health_info.batteryLevel,
+                .battery_status = health_info.batteryStatus,
+        });
+        service_->OnHealthInfoChanged(health_info);
+    }
+
+  private:
+    std::shared_ptr<Health> service_;
+    std::unique_ptr<::android::Charger> charger_;
+};
+
+int ChargerModeMain(const std::shared_ptr<Health>& binder,
+                    const std::shared_ptr<ChargerCallback>& charger_callback) {
+    LOG(INFO) << "Starting charger mode.";
+    //   parent stack ==========================================
+    //   current stack                                         ||
+    //    ||                                                   ||
+    //    V                                                    V
+    // hal_health_loop => loop_callback => charger --(raw)--> charger_callback
+    //    ^----------------(weak)---------------------------------'
+    auto loop_callback = std::make_shared<LoopCallback>(binder, charger_callback.get());
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, std::move(loop_callback));
+    charger_callback->set_hal_health_loop(hal_health_loop);
+    return hal_health_loop->StartLoop();
+}
+
+}  // namespace aidl::android::hardware::health::charger
diff --git a/health/aidl/default/android.hardware.health-service.example.rc b/health/aidl/default/android.hardware.health-service.example.rc
index b393c58..dee3d11 100644
--- a/health/aidl/default/android.hardware.health-service.example.rc
+++ b/health/aidl/default/android.hardware.health-service.example.rc
@@ -4,3 +4,13 @@
     group system
     capabilities WAKE_ALARM BLOCK_SUSPEND
     file /dev/kmsg w
+
+service vendor.charger-default /vendor/bin/hw/android.hardware.health-service.example --charger
+    class charger
+    user system
+    group system wakelock input
+    capabilities SYS_BOOT
+    file /dev/kmsg w
+    file /sys/fs/pstore/console-ramoops-0 r
+    file /sys/fs/pstore/console-ramoops r
+    file /proc/last_kmsg r
diff --git a/health/aidl/default/include/health-impl/ChargerUtils.h b/health/aidl/default/include/health-impl/ChargerUtils.h
new file mode 100644
index 0000000..8f94181
--- /dev/null
+++ b/health/aidl/default/include/health-impl/ChargerUtils.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include <optional>
+#include <type_traits>
+
+#include <android/binder_auto_utils.h>
+#include <charger/healthd_mode_charger.h>
+#include <health-impl/Health.h>
+
+#pragma once
+
+namespace aidl::android::hardware::health::charger {
+
+// Implements ChargerHalHealthLoopInterface for AIDL charger
+// Adapter of (Health, HalHealthLoop) -> ChargerHalHealthLoopInterface
+class ChargerCallback : public ::android::ChargerConfigurationInterface {
+  public:
+    ChargerCallback(const std::shared_ptr<Health>& service) : service_(service) {}
+    std::optional<bool> ChargerShouldKeepScreenOn() override;
+    bool ChargerIsOnline() override;
+    void ChargerInitConfig(healthd_config* config) override;
+    int ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) override;
+
+    // Override to return true to replace `ro.charger.enable_suspend=true`
+    bool ChargerEnableSuspend() override { return false; }
+
+    void set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop);
+
+  private:
+    std::shared_ptr<Health> service_;
+    std::weak_ptr<HalHealthLoop> hal_health_loop_;
+};
+
+int ChargerModeMain(const std::shared_ptr<Health>& binder,
+                    const std::shared_ptr<ChargerCallback>& charger_callback);
+
+}  // namespace aidl::android::hardware::health::charger
diff --git a/health/aidl/default/main.cpp b/health/aidl/default/main.cpp
index 014ae34..76c6ba0 100644
--- a/health/aidl/default/main.cpp
+++ b/health/aidl/default/main.cpp
@@ -19,17 +19,46 @@
 #include <health-impl/Health.h>
 #include <health/utils.h>
 
+#ifndef CHARGER_FORCE_NO_UI
+#define CHARGER_FORCE_NO_UI 0
+#endif
+
+#if !CHARGER_FORCE_NO_UI
+#include <health-impl/ChargerUtils.h>
+#endif
+
 using aidl::android::hardware::health::HalHealthLoop;
 using aidl::android::hardware::health::Health;
 
-static constexpr const char* gInstanceName = "default";
+#if !CHARGER_FORCE_NO_UI
+using aidl::android::hardware::health::charger::ChargerCallback;
+using aidl::android::hardware::health::charger::ChargerModeMain;
+#endif
 
-int main() {
-    // TODO(b/203246116): handle charger
+static constexpr const char* gInstanceName = "default";
+static constexpr std::string_view gChargerArg{"--charger"};
+
+int main(int argc, char** argv) {
     // make a default health service
     auto config = std::make_unique<healthd_config>();
     ::android::hardware::health::InitHealthdConfig(config.get());
     auto binder = ndk::SharedRefBase::make<Health>(gInstanceName, std::move(config));
+
+    if (argc >= 2 && argv[1] == gChargerArg) {
+        android::base::InitLogging(argv, &android::base::KernelLogger);
+
+#if !CHARGER_FORCE_NO_UI
+        // If charger shouldn't have UI for your device, simply drop the line below
+        // for your service implementation. This corresponds to
+        // ro.charger.no_ui=true
+        return ChargerModeMain(binder, std::make_shared<ChargerCallback>(binder));
+#endif
+
+        LOG(INFO) << "Starting charger mode without UI.";
+    } else {
+        LOG(INFO) << "Starting health HAL.";
+    }
+
     auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
     return hal_health_loop->StartLoop();
 }
diff --git a/health/utils/libhealthtest/Android.bp b/health/utils/libhealthtest/Android.bp
index dbe02d6..0993cb6 100644
--- a/health/utils/libhealthtest/Android.bp
+++ b/health/utils/libhealthtest/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Utils library for VTS tests.
+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"],
+}
+
 cc_library_headers {
     name: "libhealthtest_headers",
     static_libs: [
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 4e35a26..31cdded 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -55,7 +55,7 @@
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "libgmock",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index ae9ff0a..29b31d2 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -50,7 +50,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
     ],
     header_libs: [
         "libneuralnetworks_headers",
@@ -81,7 +81,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
index 478a742..737ff58 100644
--- a/neuralnetworks/1.1/utils/Android.bp
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -52,7 +52,7 @@
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "libgmock",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 4c57788..e9d4b76 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -48,7 +48,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 2a86a00..4eefb0f 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -71,7 +71,7 @@
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "libgmock",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 15a5d2f..52d51e2 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -71,7 +71,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index 8ae509f..7acb4fc 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -69,7 +69,7 @@
         "android.hardware.neuralnetworks@1.2",
         "android.hardware.neuralnetworks@1.3",
         "libgmock",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index ca59cc2..8951760 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -75,7 +75,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "libsync",
     ],
     whole_static_libs: [
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h
new file mode 100644
index 0000000..18d01e2
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h
@@ -0,0 +1,119 @@
+/*
+ * 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_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
+
+#include <android-base/macros.h>
+#include <android-base/thread_annotations.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <stack>
+#include <utility>
+#include <vector>
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+#include "nnapi/hal/aidl/ValidateHal.h"
+
+namespace android::nn {
+
+// This class manages a CPU buffer allocated on heap and provides validation methods.
+class AidlManagedBuffer {
+  public:
+    static std::shared_ptr<AidlManagedBuffer> create(uint32_t size,
+                                                     std::set<AidlHalPreparedModelRole> roles,
+                                                     const Operand& operand);
+
+    // Prefer AidlManagedBuffer::create.
+    AidlManagedBuffer(std::unique_ptr<uint8_t[]> buffer, uint32_t size,
+                      std::set<AidlHalPreparedModelRole> roles, const Operand& operand);
+
+    uint8_t* getPointer() const { return kBuffer.get(); }
+    uint32_t getSize() const { return kSize; }
+
+    // "poolIndex" is the index of this buffer in the request.pools.
+    ErrorStatus validateRequest(uint32_t poolIndex, const Request& request,
+                                const aidl_hal::IPreparedModel* preparedModel) const;
+
+    // "size" is the byte size of the Memory provided to the copyFrom or copyTo method.
+    ErrorStatus validateCopyFrom(const std::vector<uint32_t>& dimensions, uint32_t size) const;
+    ErrorStatus validateCopyTo(uint32_t size) const;
+
+    bool updateDimensions(const std::vector<uint32_t>& dimensions);
+    void setInitialized(bool initialized);
+
+  private:
+    mutable std::mutex mMutex;
+    const std::unique_ptr<uint8_t[]> kBuffer;
+    const uint32_t kSize;
+    const std::set<AidlHalPreparedModelRole> kRoles;
+    const OperandType kOperandType;
+    const std::vector<uint32_t> kInitialDimensions;
+    std::vector<uint32_t> mUpdatedDimensions GUARDED_BY(mMutex);
+    bool mInitialized GUARDED_BY(mMutex) = false;
+};
+
+// Keep track of all AidlManagedBuffers and assign each with a unique token.
+class AidlBufferTracker : public std::enable_shared_from_this<AidlBufferTracker> {
+    DISALLOW_COPY_AND_ASSIGN(AidlBufferTracker);
+
+  public:
+    // A RAII class to help manage the lifetime of the token.
+    // It is only supposed to be constructed in AidlBufferTracker::add.
+    class Token {
+        DISALLOW_COPY_AND_ASSIGN(Token);
+
+      public:
+        Token(uint32_t token, std::shared_ptr<AidlBufferTracker> tracker)
+            : kToken(token), kBufferTracker(std::move(tracker)) {}
+        ~Token() { kBufferTracker->free(kToken); }
+        uint32_t get() const { return kToken; }
+
+      private:
+        const uint32_t kToken;
+        const std::shared_ptr<AidlBufferTracker> kBufferTracker;
+    };
+
+    // The factory of AidlBufferTracker. This ensures that the AidlBufferTracker is always managed
+    // by a shared_ptr.
+    static std::shared_ptr<AidlBufferTracker> create() {
+        return std::make_shared<AidlBufferTracker>();
+    }
+
+    // Prefer AidlBufferTracker::create.
+    AidlBufferTracker() : mTokenToBuffers(1) {}
+
+    std::unique_ptr<Token> add(std::shared_ptr<AidlManagedBuffer> buffer);
+    std::shared_ptr<AidlManagedBuffer> get(uint32_t token) const;
+
+  private:
+    void free(uint32_t token);
+
+    mutable std::mutex mMutex;
+    std::stack<uint32_t, std::vector<uint32_t>> mFreeTokens GUARDED_BY(mMutex);
+
+    // Since the tokens are allocated in a non-sparse way, we use a vector to represent the mapping.
+    // The index of the vector is the token. When the token gets freed, the corresponding entry is
+    // set to nullptr. mTokenToBuffers[0] is always set to nullptr because 0 is an invalid token.
+    std::vector<std::shared_ptr<AidlManagedBuffer>> mTokenToBuffers GUARDED_BY(mMutex);
+};
+
+}  // namespace android::nn
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
new file mode 100644
index 0000000..3fb443c
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
@@ -0,0 +1,72 @@
+/*
+ * 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_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnBurst.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/Capabilities.h>
+#include <aidl/android/hardware/neuralnetworks/DataLocation.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.h>
+#include <aidl/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.h>
+#include <aidl/android/hardware/neuralnetworks/FusedActivationFunc.h>
+#include <aidl/android/hardware/neuralnetworks/IBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
+#include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/Operand.h>
+#include <aidl/android/hardware/neuralnetworks/OperandExtraParams.h>
+#include <aidl/android/hardware/neuralnetworks/OperandLifeTime.h>
+#include <aidl/android/hardware/neuralnetworks/OperandPerformance.h>
+#include <aidl/android/hardware/neuralnetworks/OperandType.h>
+#include <aidl/android/hardware/neuralnetworks/Operation.h>
+#include <aidl/android/hardware/neuralnetworks/OperationType.h>
+#include <aidl/android/hardware/neuralnetworks/OutputShape.h>
+#include <aidl/android/hardware/neuralnetworks/PerformanceInfo.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <aidl/android/hardware/neuralnetworks/RequestArgument.h>
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
+#include <aidl/android/hardware/neuralnetworks/Subgraph.h>
+#include <aidl/android/hardware/neuralnetworks/SymmPerChannelQuantParams.h>
+#include <aidl/android/hardware/neuralnetworks/Timing.h>
+
+namespace android::nn {
+
+namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
+
+inline constexpr aidl_hal::Priority kDefaultPriorityAidl = aidl_hal::Priority::MEDIUM;
+
+}  // namespace android::nn
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h
new file mode 100644
index 0000000..89552bc
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h
@@ -0,0 +1,52 @@
+/*
+ * 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_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
+
+#include <vector>
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+
+namespace android {
+namespace nn {
+
+// Return a vector with one entry for each non-extension OperandType except
+// SUBGRAPH, set to the specified PerformanceInfo value.  The vector will be
+// sorted by OperandType.
+//
+// Control flow (OperandType::SUBGRAPH) operation performance is specified
+// separately using Capabilities::ifPerformance and
+// Capabilities::whilePerformance.
+std::vector<aidl_hal::OperandPerformance> nonExtensionOperandPerformance(
+        aidl_hal::PerformanceInfo perf);
+
+// Update the vector entry corresponding to the specified OperandType with the
+// specified PerformanceInfo value.  The vector must already have an entry for
+// that OperandType, and must be sorted by OperandType.
+void update(std::vector<aidl_hal::OperandPerformance>* operandPerformance,
+            aidl_hal::OperandType type, aidl_hal::PerformanceInfo perf);
+
+// Returns true if an operand type is an extension type.
+bool isExtensionOperandType(aidl_hal::OperandType type);
+
+// Returns true if an operand type is a scalar type.
+bool isNonExtensionScalar(aidl_hal::OperandType type);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h
new file mode 100644
index 0000000..62aba31
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h
@@ -0,0 +1,47 @@
+/*
+ * 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_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+
+#include <memory>
+#include <set>
+#include <tuple>
+#include <vector>
+
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Validation.h>
+
+namespace android {
+namespace nn {
+
+using AidlHalPreparedModelRole = std::tuple<const aidl_hal::IPreparedModel*, IOType, uint32_t>;
+
+bool validateMemoryDesc(
+        const aidl_hal::BufferDesc& desc,
+        const std::vector<std::shared_ptr<aidl_hal::IPreparedModel>>& preparedModels,
+        const std::vector<aidl_hal::BufferRole>& inputRoles,
+        const std::vector<aidl_hal::BufferRole>& outputRoles,
+        std::function<const aidl_hal::Model*(const std::shared_ptr<aidl_hal::IPreparedModel>&)>
+                getModel,
+        std::set<AidlHalPreparedModelRole>* preparedModelRoles, aidl_hal::Operand* combinedOperand);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
diff --git a/neuralnetworks/aidl/utils/src/Buffer.cpp b/neuralnetworks/aidl/utils/src/Buffer.cpp
index c729a68..9af3c9e 100644
--- a/neuralnetworks/aidl/utils/src/Buffer.cpp
+++ b/neuralnetworks/aidl/utils/src/Buffer.cpp
@@ -22,7 +22,6 @@
 
 #include "Conversions.h"
 #include "Utils.h"
-#include "nnapi/hal/aidl/Conversions.h"
 
 #include <memory>
 #include <utility>
diff --git a/neuralnetworks/aidl/utils/src/BufferTracker.cpp b/neuralnetworks/aidl/utils/src/BufferTracker.cpp
new file mode 100644
index 0000000..94dc891
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/BufferTracker.cpp
@@ -0,0 +1,227 @@
+/*
+ * 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 "BufferTracker.h"
+
+#include "HalInterfaces.h"
+
+#include <android-base/macros.h>
+#include <nnapi/TypeUtils.h>
+
+#include <memory>
+#include <mutex>
+#include <set>
+#include <stack>
+#include <utility>
+#include <vector>
+
+namespace android::nn {
+
+std::shared_ptr<AidlManagedBuffer> AidlManagedBuffer::create(
+        uint32_t size, std::set<AidlHalPreparedModelRole> roles, const Operand& operand) {
+    std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
+    if (buffer == nullptr) {
+        return nullptr;
+    }
+    if (isExtension(operand.type)) {
+        LOG(ERROR) << "AidlManagedBuffer cannot handle extension operands.";
+        return nullptr;
+    }
+    return std::make_shared<AidlManagedBuffer>(std::move(buffer), size, std::move(roles), operand);
+}
+
+AidlManagedBuffer::AidlManagedBuffer(std::unique_ptr<uint8_t[]> buffer, uint32_t size,
+                                     std::set<AidlHalPreparedModelRole> roles,
+                                     const Operand& operand)
+    : kBuffer(std::move(buffer)),
+      kSize(size),
+      kRoles(std::move(roles)),
+      kOperandType(operand.type),
+      kInitialDimensions(operand.dimensions),
+      mUpdatedDimensions(operand.dimensions) {
+    CHECK(!isExtension(kOperandType));
+}
+
+ErrorStatus AidlManagedBuffer::validateRequest(
+        uint32_t poolIndex, const Request& request,
+        const aidl_hal::IPreparedModel* preparedModel) const {
+    CHECK_LT(poolIndex, request.pools.size());
+    CHECK(std::holds_alternative<Request::MemoryDomainToken>(request.pools[poolIndex]));
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    bool usedAsInput = false, usedAsOutput = false;
+    for (uint32_t i = 0; i < request.inputs.size(); i++) {
+        if (request.inputs[i].lifetime != Request::Argument::LifeTime::POOL) continue;
+        if (request.inputs[i].location.poolIndex != poolIndex) continue;
+        // Validate if the input role is specified during allocation.
+        if (kRoles.count({preparedModel, IOType::INPUT, i}) == 0) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- invalid buffer role.";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        if (!mInitialized) {
+            LOG(ERROR)
+                    << "AidlManagedBuffer::validateRequest -- using uninitialized buffer as input "
+                       "request.";
+            return ErrorStatus::GENERAL_FAILURE;
+        }
+        auto combined = combineDimensions(mUpdatedDimensions, request.inputs[i].dimensions);
+        if (!combined.has_value()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- incompatible dimensions ("
+                       << toString(mUpdatedDimensions) << " vs "
+                       << toString(request.inputs[i].dimensions) << ")";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        usedAsInput = true;
+    }
+    for (uint32_t i = 0; i < request.outputs.size(); i++) {
+        if (request.outputs[i].lifetime != Request::Argument::LifeTime::POOL) continue;
+        if (request.outputs[i].location.poolIndex != poolIndex) continue;
+        if (usedAsInput || usedAsOutput) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- using the same device memory for "
+                          "input/output or multiple outputs";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        // Validate if the output role is specified during allocation.
+        if (kRoles.count({preparedModel, IOType::OUTPUT, i}) == 0) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- invalid buffer role.";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        auto combined = combineDimensions(kInitialDimensions, request.outputs[i].dimensions);
+        if (!combined.has_value()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- incompatible dimensions ("
+                       << toString(kInitialDimensions) << " vs "
+                       << toString(request.outputs[i].dimensions) << ")";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        usedAsOutput = true;
+    }
+    return ErrorStatus::NONE;
+}
+
+ErrorStatus AidlManagedBuffer::validateCopyFrom(const std::vector<uint32_t>& dimensions,
+                                                uint32_t size) const {
+    if (size != kSize) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- invalid memory size: " << kSize
+                   << " vs " << size;
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+
+    if (isNonExtensionScalar(kOperandType)) {
+        if (!dimensions.empty()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- invalid dimensions for scalar "
+                          "operand: "
+                       << toString(dimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        return ErrorStatus::NONE;
+    }
+
+    if (dimensions.empty()) {
+        if (tensorHasUnspecifiedDimensions(kOperandType, kInitialDimensions)) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- the initial dimensions are not "
+                          "fully "
+                          "specified and no dimension update is provided: "
+                       << toString(kInitialDimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+    } else {
+        if (tensorHasUnspecifiedDimensions(kOperandType, dimensions)) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- the updated dimensions are not "
+                          "fully "
+                          "specified: "
+                       << toString(dimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+    }
+
+    const auto combined = combineDimensions(kInitialDimensions, dimensions);
+    if (!combined.has_value()) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- incompatible dimensions ("
+                   << toString(kInitialDimensions) << " vs " << toString(dimensions) << ")";
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+    return ErrorStatus::NONE;
+}
+
+ErrorStatus AidlManagedBuffer::validateCopyTo(uint32_t size) const {
+    if (size != kSize) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyTo -- invalid memory size: " << kSize
+                   << " vs " << size;
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    if (!mInitialized) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyTo -- using uninitialized buffer as source.";
+        return ErrorStatus::GENERAL_FAILURE;
+    }
+    return ErrorStatus::NONE;
+}
+
+bool AidlManagedBuffer::updateDimensions(const std::vector<uint32_t>& dimensions) {
+    auto combined = combineDimensions(kInitialDimensions, dimensions);
+    if (!combined.has_value()) {
+        LOG(ERROR) << "AidlManagedBuffer::updateDimensions -- incompatible dimensions ("
+                   << toString(kInitialDimensions) << " vs " << toString(dimensions) << ")";
+        return false;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    mUpdatedDimensions = std::move(combined).value();
+    return true;
+}
+
+void AidlManagedBuffer::setInitialized(bool initialized) {
+    std::lock_guard<std::mutex> guard(mMutex);
+    mInitialized = initialized;
+}
+
+std::unique_ptr<AidlBufferTracker::Token> AidlBufferTracker::add(
+        std::shared_ptr<AidlManagedBuffer> buffer) {
+    if (buffer == nullptr) {
+        return nullptr;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    uint32_t token = 0;
+    if (mFreeTokens.empty()) {
+        token = mTokenToBuffers.size();
+        mTokenToBuffers.push_back(std::move(buffer));
+    } else {
+        token = mFreeTokens.top();
+        mFreeTokens.pop();
+        mTokenToBuffers[token] = std::move(buffer);
+    }
+    VLOG(MEMORY) << "AidlBufferTracker::add -- new token = " << token;
+    return std::make_unique<Token>(token, shared_from_this());
+}
+
+std::shared_ptr<AidlManagedBuffer> AidlBufferTracker::get(uint32_t token) const {
+    std::lock_guard<std::mutex> guard(mMutex);
+    if (mTokenToBuffers.size() <= token || mTokenToBuffers[token] == nullptr) {
+        LOG(ERROR) << "AidlBufferTracker::get -- unknown token " << token;
+        return nullptr;
+    }
+    return mTokenToBuffers[token];
+}
+
+void AidlBufferTracker::free(uint32_t token) {
+    std::lock_guard<std::mutex> guard(mMutex);
+    CHECK_LT(token, mTokenToBuffers.size());
+    CHECK(mTokenToBuffers[token] != nullptr);
+    VLOG(MEMORY) << "AidlBufferTracker::free -- release token = " << token;
+    mTokenToBuffers[token] = nullptr;
+    mFreeTokens.push(token);
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/aidl/utils/src/HalUtils.cpp b/neuralnetworks/aidl/utils/src/HalUtils.cpp
new file mode 100644
index 0000000..64b6259
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/HalUtils.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+// This file contains pre-canonical-types utility code and includes HAL
+// utilities. LegacyUtils.h is the subset of these utilities that do not touch
+// HAL.
+
+#include "HalUtils.h"
+
+#include "HalInterfaces.h"
+
+#include <android-base/logging.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <algorithm>
+#include <iterator>
+#include <type_traits>
+#include <vector>
+
+namespace android::nn {
+
+std::vector<aidl_hal::OperandPerformance> nonExtensionOperandPerformance(
+        aidl_hal::PerformanceInfo perf) {
+    static constexpr ndk::enum_range<aidl_hal::OperandType> kOperandTypeRange;
+    std::vector<aidl_hal::OperandPerformance> ret;
+    ret.reserve(std::distance(kOperandTypeRange.begin(), kOperandTypeRange.end()));
+    for (aidl_hal::OperandType type : kOperandTypeRange) {
+        if (type != aidl_hal::OperandType::SUBGRAPH) {
+            ret.push_back(aidl_hal::OperandPerformance{type, perf});
+        }
+    }
+    std::sort(ret.begin(), ret.end(),
+              [](const aidl_hal::OperandPerformance& a, const aidl_hal::OperandPerformance& b) {
+                  return a.type < b.type;
+              });
+
+    return ret;
+}
+
+void update(std::vector<aidl_hal::OperandPerformance>* operandPerformance,
+            aidl_hal::OperandType type, aidl_hal::PerformanceInfo perf) {
+    CHECK(operandPerformance != nullptr);
+    const auto it = std::lower_bound(operandPerformance->begin(), operandPerformance->end(), type,
+                                     [](const aidl_hal::OperandPerformance& perf,
+                                        aidl_hal::OperandType type) { return perf.type < type; });
+    CHECK(it != operandPerformance->end())
+            << toString(type) << " not in operand performance vector";
+    it->info = perf;
+}
+
+bool isExtensionOperandType(aidl_hal::OperandType type) {
+    return isExtension(convert(type).value());
+}
+
+bool isNonExtensionScalar(aidl_hal::OperandType type) {
+    return isNonExtensionScalar(convert(type).value());
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/aidl/utils/src/ValidateHal.cpp b/neuralnetworks/aidl/utils/src/ValidateHal.cpp
new file mode 100644
index 0000000..a56de21
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/ValidateHal.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ValidateHal"
+
+#include "ValidateHal.h"
+
+#include "HalUtils.h"
+
+#include <android-base/logging.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <algorithm>
+#include <memory>
+#include <set>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace nn {
+
+bool validateMemoryDesc(
+        const aidl_hal::BufferDesc& desc,
+        const std::vector<std::shared_ptr<aidl_hal::IPreparedModel>>& preparedModels,
+        const std::vector<aidl_hal::BufferRole>& inputRoles,
+        const std::vector<aidl_hal::BufferRole>& outputRoles,
+        std::function<const aidl_hal::Model*(const std::shared_ptr<aidl_hal::IPreparedModel>&)>
+                getModel,
+        std::set<AidlHalPreparedModelRole>* preparedModelRoles,
+        aidl_hal::Operand* combinedOperand) {
+    NN_RET_CHECK(!preparedModels.empty());
+    NN_RET_CHECK(!inputRoles.empty() || !outputRoles.empty());
+
+    std::set<AidlHalPreparedModelRole> roles;
+    std::vector<aidl_hal::Operand> operands;
+    operands.reserve(inputRoles.size() + outputRoles.size());
+    for (const auto& role : inputRoles) {
+        NN_RET_CHECK_GE(role.modelIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.modelIndex), preparedModels.size());
+        const auto& preparedModel = preparedModels[role.modelIndex];
+        NN_RET_CHECK(preparedModel != nullptr);
+        const auto* model = getModel(preparedModel);
+        NN_RET_CHECK(model != nullptr);
+        const auto& inputIndexes = model->main.inputIndexes;
+        NN_RET_CHECK_GE(role.ioIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.ioIndex), inputIndexes.size());
+        NN_RET_CHECK_GT(role.probability, 0.0f);
+        NN_RET_CHECK_LE(role.probability, 1.0f);
+        const auto [it, success] = roles.emplace(preparedModel.get(), IOType::INPUT, role.ioIndex);
+        NN_RET_CHECK(success);
+        operands.push_back(model->main.operands[inputIndexes[role.ioIndex]]);
+    }
+    for (const auto& role : outputRoles) {
+        NN_RET_CHECK_GE(role.modelIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.modelIndex), preparedModels.size());
+        const auto& preparedModel = preparedModels[role.modelIndex];
+        NN_RET_CHECK(preparedModel != nullptr);
+        const auto* model = getModel(preparedModel);
+        NN_RET_CHECK(model != nullptr);
+        const auto& outputIndexes = model->main.outputIndexes;
+        NN_RET_CHECK_GE(role.ioIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.ioIndex), outputIndexes.size());
+        NN_RET_CHECK_GT(role.probability, 0.0f);
+        NN_RET_CHECK_LE(role.probability, 1.0f);
+        const auto [it, success] = roles.emplace(preparedModel.get(), IOType::OUTPUT, role.ioIndex);
+        NN_RET_CHECK(success);
+        operands.push_back(model->main.operands[outputIndexes[role.ioIndex]]);
+    }
+
+    CHECK(!operands.empty());
+    const auto opType = operands[0].type;
+    const auto canonicalOperandType = convert(opType);
+    NN_RET_CHECK(canonicalOperandType.has_value()) << canonicalOperandType.error().message;
+    const bool isExtensionOperand = isExtension(canonicalOperandType.value());
+
+    auto maybeDimensions = toUnsigned(desc.dimensions);
+    NN_RET_CHECK(maybeDimensions.has_value()) << maybeDimensions.error().message;
+    std::vector<uint32_t> dimensions = std::move(maybeDimensions).value();
+
+    for (const auto& operand : operands) {
+        NN_RET_CHECK(operand.type == operands[0].type)
+                << toString(operand.type) << " vs " << toString(operands[0].type);
+        NN_RET_CHECK_EQ(operand.scale, operands[0].scale);
+        NN_RET_CHECK_EQ(operand.zeroPoint, operands[0].zeroPoint);
+        // NOTE: validateMemoryDesc cannot validate extra parameters for extension operand type.
+        if (!isExtensionOperand) {
+            const auto& lhsExtraParams = operand.extraParams;
+            const auto& rhsExtraParams = operands[0].extraParams;
+            NN_RET_CHECK(lhsExtraParams == rhsExtraParams)
+                    << (lhsExtraParams.has_value() ? lhsExtraParams.value().toString()
+                                                   : "std::nullopt")
+                    << " vs "
+                    << (rhsExtraParams.has_value() ? rhsExtraParams.value().toString()
+                                                   : "std::nullopt");
+        }
+        const auto maybeRhsDimensions = toUnsigned(operand.dimensions);
+        NN_RET_CHECK(maybeRhsDimensions.has_value()) << maybeRhsDimensions.error().message;
+        const auto combined = combineDimensions(dimensions, maybeRhsDimensions.value());
+        NN_RET_CHECK(combined.has_value());
+        dimensions = combined.value();
+    }
+
+    // NOTE: validateMemoryDesc cannot validate scalar dimensions with extension operand type.
+    if (!isExtensionOperand) {
+        NN_RET_CHECK(!isNonExtensionScalar(opType) || dimensions.empty())
+                << "invalid dimensions with scalar operand type.";
+    }
+
+    if (preparedModelRoles != nullptr) {
+        *preparedModelRoles = std::move(roles);
+    }
+    if (combinedOperand != nullptr) {
+        *combinedOperand = operands[0];
+        // No need to check that values fit int32_t here, since the original values are obtained
+        // from int32_t.
+        combinedOperand->dimensions = aidl_hal::utils::toSigned(dimensions).value();
+    }
+    return true;
+}
+
+}  // namespace nn
+}  // namespace android
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 1819699..cd5475c 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -28,9 +28,9 @@
 #include <Utils.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/HalInterfaces.h>
 #include <nnapi/hal/aidl/Utils.h>
 
-#include "AidlHalInterfaces.h"
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
 #include "MemoryUtils.h"
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index c01460e..39927a3 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -39,7 +39,7 @@
     srcs: ["test/*.cpp"],
     static_libs: [
         "libgmock",
-        "libneuralnetworks_common_hidl",
+        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
     ],
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index e10d329..9acb9e0 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -24,8 +24,8 @@
 cc_binary {
     name: "android.hardware.power-service.example",
     relative_install_path: "hw",
-    init_rc: ["power-default.rc"],
-    vintf_fragments: ["power-default.xml"],
+    init_rc: [":android.hardware.power.rc"],
+    vintf_fragments: [":android.hardware.power.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
@@ -37,3 +37,13 @@
         "Power.cpp",
     ],
 }
+
+filegroup {
+    name: "android.hardware.power.xml",
+    srcs: ["power-default.xml"],
+}
+
+filegroup {
+    name: "android.hardware.power.rc",
+    srcs: ["power-default.rc"],
+}
diff --git a/power/aidl/default/apex/Android.bp b/power/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..eb04087
--- /dev/null
+++ b/power/aidl/default/apex/Android.bp
@@ -0,0 +1,72 @@
+// 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+    name: "com.android.hardware.power.key",
+    public_key: "com.android.hardware.power.avbpubkey",
+    private_key: "com.android.hardware.power.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.power.certificate",
+    certificate: "com.android.hardware.power",
+}
+
+genrule {
+    name: "com.android.hardware.power.rc-srcs",
+    srcs: [
+        ":android.hardware.power.rc",
+        ":android.hardware.power.stats.rc",
+    ],
+    out: ["com.android.hardware.power.rc"],
+    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.power/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.power.rc",
+    src: ":com.android.hardware.power.rc-srcs",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.power",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.power.key",
+    certificate: ":com.android.hardware.power.certificate",
+    file_contexts: "file_contexts",
+    use_vndk_as_stable: true,
+    updatable: false,
+    // Install the apex in /vendor/apex
+    soc_specific: true,
+    // Bundle the Power and PowerStats HALs into this one APEX.
+    binaries: [
+        "android.hardware.power-service.example",
+        "android.hardware.power.stats-service.example",
+    ],
+    prebuilts: [
+        "com.android.hardware.power.rc",
+    ],
+    vintf_fragments: [
+        ":android.hardware.power.xml",
+        ":android.hardware.power.stats.xml",
+    ],
+    overrides: [
+        // Shared lib installed by default but unused by the AIDL implementation.
+        "power.default",
+    ],
+}
diff --git a/power/aidl/default/apex/apex_manifest.json b/power/aidl/default/apex/apex_manifest.json
new file mode 100644
index 0000000..faa937d
--- /dev/null
+++ b/power/aidl/default/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.power",
+  "version": 1
+}
diff --git a/power/aidl/default/apex/com.android.hardware.power.avbpubkey b/power/aidl/default/apex/com.android.hardware.power.avbpubkey
new file mode 100644
index 0000000..3b6411d
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.avbpubkey
Binary files differ
diff --git a/power/aidl/default/apex/com.android.hardware.power.pem b/power/aidl/default/apex/com.android.hardware.power.pem
new file mode 100644
index 0000000..d18ae98
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAsUdFjtLq05tWKdQd4aj8V7tmV4KXw41pKGT5Q1CPzrdHF3yJ
+B/8VWdMpjZ+eQO1q8SijPgfvWExeWQVMfxKmwTmj26xWXhIOgo5G02Zva7zOptig
+KGnl/RdFlOiIGC36XeWDhzdIOhlGv+er9Sykf6Ot84OvktTBUTZNJrXQsyYTBRUX
+6B+wloPdBVxVf1HgzjeHUyCy5dTz0xZSWWELoW24tHIvV5FtJVKSY8ZDfuXWLLfT
+he7E93TepjT027U/J/iW4ITJzw4Qq87ick1D/jZDUbTrkqUMFEgPdgCouZ9zt5xG
+pcHAZ/Fcz9DZfEdX9Xy0R5/XbfrJdvDPguJlwK1pZnr/Pe13xxmE+TEohMmaQDqX
+jQNX3UlcfOYUAjnFMGucHDM10KjTMbP8ytCys88aNLiv7FOgVGrQ/djZN8rkMyVP
+ccoksUBMQmjYaQQZ2yZuJMiLD3P6aYkgU5tMEMoMTrBzfcx05GfElal+ZqOFKAzj
+eUxoZTR27wJb684FRbeE45D+y4jpFfrTEXry+aI7GrfDsVDnUqmyObCUttRtaT04
+6kuUmC44wFEg1EBfcWZc1szI192GBjMuZjFcYvJ4vMdCuennqvLNPBDY1PtqzCOf
+D8vpOE3T9rjS23xxFmmSmorwKKQOGChKqO/SaY0axkXgt+FbSsvTBQtZTSsCAwEA
+AQKCAgEArEu3t+MYJcdwS8EDtcF2V5IkGmMrOvziOkdA14Kh8efBKXt49xOc3atU
+VHfQ6AuXh4DWf0BZB7lZbS2wNkSbW2q47ZSmcFEeVxcOkQGawtxDAHfD2ONrirqm
+ft4s/0sYbU/WsIEzKnxMfdEdGHFmA0PCmczfxFYQ+OxMuZW1m5ginirtDEZYa0EH
+e+FMmyypz+K6HDnIhYWd4Aduy718/0zTWlUr2/DUYpTJAD2+dcPNj7Kt2xq/xj2I
+84K+hBa4phF+GgIU3a8u1ryA61RbA+QbM3siBWlxvvh2RlrHoXjuj4JMS2dup9c2
+PCggaCAyxb2IvaAFUbePPJE5LVz6RFT4HnLEydd5Yt+CEAm+iZKfCzyUgFRtb5y0
+HHTME1eVAt/rf/yIXUYA7q8nQ/PtSzIol5KLX4FUjX1MVKNmIWMa+836kxbuYDFB
+K1M1IKc1k0t9Q9F3TRCMhP/6qH/vJfubCGQhSRUMq7JyjivK9GjYST8R07Dpgu9Z
+4i9TRI8d+UVERsg8niCXONVkmNa3U49u2duUvqV3KmKgQ/Hgyy3keDjz6x56ie5w
+e0EusHAsot60W1BvHrdwlmGZjW3JmZEyazUPh9nBUAaQve1rIOpn80kGXx4EAE2o
+HcrcInJx/zVBk1Wk3UQDwmhUNpa64q9+nd9VMaR9SQNK3ah4NDECggEBAOeput2F
+CgRrvzka69i7FbgY4VmpNMIICPIB6gxvwpir/g4/GgYknuBB6ep1ksf/IZfsMp5A
+JTH1KdXqqQm8nV9v+ETYQAO+VnmWKSBKHsNJqONxsKkQ+xIJcusmKBTYLfL88XQg
+YWH3VMXgqPP8DnJYCeVRIKj1WqfEFFHiaLJJB8FgKhtZBwBnibkVG1K0XCkTdUfY
+mME2GRKW/C7DMvuFOpcFVj7Obwn68R2k3zsOhWA5NQGZF5mqhg5KYLVDg3IbMJQQ
+D+DymQxnc2s2ar0q24isy1Y/FOXrA057j1vAN951+pk6F/PCJM/mtAiRjhP0Aru1
+P6bbR11p+wnpU7MCggEBAMPm8Jmwu3F0xsyFC+1sWPAzPiwaMa7/30wANNKKqHVO
+7lUv1WYFbFMyAOzYPp3Y5HxdxNa43reULGk0R20kSu6W6FkApSvAws0rLKRlS5UI
+oZqhLGHUH2M7q07m2RgQY2TJkU2Zq6AH1kjcbSr127ISXKanKpqonwSHy38BTcGt
+Dl2fVioPzK/vwmiNo2njhh95TV4kqlbUfl7xtDt56tbg8oFBwOsK7UGajXYOxTGB
+o1DtO5E+oiOmlclXuo3m4qpSSMv+wM91aRFhHZVIx0vmO8y5lrfU2kM/5DDhJBxV
+FM4TaA+c5tFOTuCLejHc7nM99wVx7O4QZ0wBwETUxKkCggEAH0tBT+1J1iEL+tXV
+KDjVjUHnJyqBUvis5Kw3hqiOO/t33UrO5CeMQrUEuURaqKOhURl6GQCHRcFdfmUt
+ooAVLjA89GfV9et/WPtc4NzCXRUVOGxCNgRyNhSKrpM/9NjjFCDxKQO6w/YaQITB
+rfvNo8qaw5x68ff64BDPweP4yqSs5IVuCrWzCW3zH8pnH3v3uyDCxgrPT8JUDrvQ
+oyyBNZLgwEfbR66xN0Lr0VpVQXALulzf+TBKDNsJMuL/P104Y3Ci1k15J6T94bwT
+zlbSgm1IrKTS7vqkgw6FKtPsILPNmEKNsKc1VxtRx7fdeA7Zh3595Adu6sZSVJ8d
+Z1BamwKCAQAnbu0vgqu4gtEhigaEnDKq5yW0qvElUMwZ+FCpsM+IDYNcEmzaRG0x
+sfcNtdmk3GvhvN5KepwaR/FInAVkqtGKhUXv5Hla/Uo5El/CF8HHFh2xio/sgU5w
+IyqwjzdT6LiZKRnejPhHFkzEDdrLswGuLpQH185zo02fE9aakiCcw8EIh3JItTV2
+lMSFVz11qx7sZvZz5N2E7PEjG3Q0JK5o4o7uBdZXebOYaQvgn8iB1p6RQ6+h5QGu
+O3IbPVWICtnFfxq4NWeKWw/zN6FE04mKdaXD5/e2uVnV/55nWGp0aYvuj2l6+xJb
+P3ARMwI910MIX4jBx9TxdsvUOOYC9PFBAoIBAQDWswLnaNth4pgutngVWbMenSpv
+eK1RA1ldw2NoTZrGlqPB+LvjEMSH/7ioby8YtOyJRIWs3si8HpVF12qneu8qi7b7
+QlUtqyJOTnGalvhrlq5zPhdW+kk2DXvtTylUnz3vSxxi2I7cLhQRryLC/1kAwy67
+wEr0+u59bOvaqe8L1zgtYJpLQZeskUMzdSMIRVDdFShEFrMJU7adUvGpA7OZ6Ogf
+ux2jWr2vv/eKq6fU6kDPi/66MQjPbZPf2Uq6+XedkNkAeELpN4o3hw0/l/rfiK/r
+YUMJBwtjQw/hehtvC4GlgsH1tMZWzCZULo0tcW4qbzyi9PBrWFPteb33OjBc
+-----END RSA PRIVATE KEY-----
diff --git a/power/aidl/default/apex/com.android.hardware.power.pk8 b/power/aidl/default/apex/com.android.hardware.power.pk8
new file mode 100644
index 0000000..e45435d
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.pk8
Binary files differ
diff --git a/power/aidl/default/apex/com.android.hardware.power.x509.pem b/power/aidl/default/apex/com.android.hardware.power.x509.pem
new file mode 100644
index 0000000..9f0c5f0
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8ECFDFsXbm5CdS/UtQZgTiF8Umr8LrLMA0GCSqGSIb3DQEBCwUAMIGn
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEjMCEGA1UEAwwaY29t
+LmFuZHJvaWQuaGFyZHdhcmUucG93ZXIwIBcNMjExMDIwMTcwNTA0WhgPNDc1OTA5
+MTYxNzA1MDRaMIGnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
+MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
+CwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEj
+MCEGA1UEAwwaY29tLmFuZHJvaWQuaGFyZHdhcmUucG93ZXIwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQC/37fhOkOfgM2e+M7bMJ1baLFif8dKGwRa6mkJ
+9HWmuOgRcTKllzuEHtrJ0jzur3cDy6/0oZSfA/E1ck3DdRHMQadW26JSNSg6fCU9
+h1kDzkakZgyr3DsJnKGoSHCJ2V2kVbCnd6GuOaOU1ZZISw1I+BWJDc3t1mZPs80D
+ar7/hoIZnsWRoE/eWgJDcWWscRsquSi+q6hyqlCbRvwRznPaDGwmb4geHNugCXkz
+EtCswfc5jiT8DjMDkgVsGO/WcYj2GWT0K0H+Zf1CmEO9fAoXTLfVBjdumtGILgii
+d/TJe2tOBSWyZz6sVzfac2PvUH5Lm8TNUXuLV5IEdcpySge0vqYQwAyd2EgsTH1e
+mRNSk9NerpmfCFEySRRP3BWMGRhbST1d8M3v9Bq0QFhrxoAF12r6GXBUpp9XcOL5
+pBTcAkA9XI++mfz4pDzyGRGOy4WX+8XtsaVZ/14JklupSLr0Tt7oaNocUhoXB03g
+4B0jUTX0hNnVzCxzJypw6YJ60Zc8z+z8pEF34FWarHec1QbkFuyWxbaTPQ4d2NLH
+8zDxQpMILErWdAgKsRL0d8RFG5fBcleEoBM2kKHMAgnP+1qyDqBgt8zloWbmmblw
+JXMuoePFOgeVcgPrZ3EGJSx+s4+dQGQc6r/GwKLKSWpUvHxTIGug76IX9xmptB+I
+F3xb2QIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQANISf3Vi2eueOlzzfnEGGa+CXz
+nvlgUXKv8Gv0/Pbg5uC1BaHTAUgRu5rvrfP9p3Mdj86I/HbE/F4Vkuzqb8/JTWGA
+mG636zAsJRJr0fnkbPma9wVEPSK8MF1QqM6PmKXboixX82TqV1R1sRYG+9hh9W3u
+isDzYDb2ODE0X9M8/3hLS28zdCdtl4zCRK6KB86aGxvkVEj4qDA5l+AbVYevS/SU
+hz1+K/aM0Fi6MZovo5kd/Mof5l05e1TEgCoL1FtFX79r+PYGHJ8/LjtEMkFgwqvG
+CLx2sOV09EHZU27EbVvSs1JYMMXgeAvKaHsVZ51QlSzW4esg/E6z4pw654p8qyK/
+WLXIZ7BMILl1sHYmGqXitnu19puvNks2/+hyqVr0seM5GyQDuwBE8nx6xZzTRxdj
+4TZyN9LuMc9/cKJFvOPqD152bkA2frCLEzYCQreDWwxsWcUHzYrQT+v2SqzP6Ue2
+Xn06HDLx9wBL7Dz6no05SlNS0u1KdvKas6FKZHO+QaKKsBlDmXbMrBTcuUI6OXv2
+6NpVbeyDd0+A23hDiNSgI6zTY6jMidesNExB7rW/bCE4ltPyxFAB+sffyXounODc
+groB5CaS2bv+H1IXJzMMe4LkgQPl1C7G+I3KvJmnrYwmIhLIDuxP82arClIDzccS
+ExRR7ugEg91XCc87Zg==
+-----END CERTIFICATE-----
diff --git a/power/aidl/default/apex/file_contexts b/power/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..3433851
--- /dev/null
+++ b/power/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/bin/hw/android\.hardware\.power-service\.example           u:object_r:hal_power_default_exec:s0
+/bin/hw/android\.hardware\.power\.stats-service\.example    u:object_r:hal_power_stats_default_exec:s0
diff --git a/power/stats/aidl/default/Android.bp b/power/stats/aidl/default/Android.bp
index 7c0caf3..66be5f9 100644
--- a/power/stats/aidl/default/Android.bp
+++ b/power/stats/aidl/default/Android.bp
@@ -24,8 +24,8 @@
 cc_binary {
     name: "android.hardware.power.stats-service.example",
     relative_install_path: "hw",
-    init_rc: ["power.stats-default.rc"],
-    vintf_fragments: ["power.stats-default.xml"],
+    init_rc: [":android.hardware.power.stats.rc"],
+    vintf_fragments: [":android.hardware.power.stats.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
@@ -37,3 +37,13 @@
         "PowerStats.cpp",
     ],
 }
+
+filegroup {
+    name: "android.hardware.power.stats.xml",
+    srcs: ["power.stats-default.xml"],
+}
+
+filegroup {
+    name: "android.hardware.power.stats.rc",
+    srcs: ["power.stats-default.rc"],
+}
diff --git a/security/keymint/aidl/OWNERS b/security/OWNERS
similarity index 100%
rename from security/keymint/aidl/OWNERS
rename to security/OWNERS
diff --git a/security/keymint/support/OWNERS b/security/keymint/support/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/keymint/support/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/secureclock/aidl/OWNERS b/security/secureclock/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/secureclock/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/sharedsecret/aidl/OWNERS b/security/sharedsecret/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/sharedsecret/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/sensors/1.0/vts/functional/OWNERS b/sensors/1.0/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/1.0/vts/functional/OWNERS
+++ b/sensors/1.0/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS
diff --git a/sensors/2.0/vts/functional/OWNERS b/sensors/2.0/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/2.0/vts/functional/OWNERS
+++ b/sensors/2.0/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS
diff --git a/sensors/2.1/vts/functional/OWNERS b/sensors/2.1/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/2.1/vts/functional/OWNERS
+++ b/sensors/2.1/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS