Merge "Add test mapping for Tuner HAL"
diff --git a/automotive/audiocontrol/2.0/Android.bp b/automotive/audiocontrol/2.0/Android.bp
new file mode 100644
index 0000000..2a9f849
--- /dev/null
+++ b/automotive/audiocontrol/2.0/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.automotive.audiocontrol@2.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IAudioControl.hal",
+        "ICloseHandle.hal",
+        "IFocusListener.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+        "android.hardware.audio.common@6.0",
+    ],
+    gen_java: true,
+}
diff --git a/automotive/audiocontrol/2.0/IAudioControl.hal b/automotive/audiocontrol/2.0/IAudioControl.hal
new file mode 100644
index 0000000..1073498
--- /dev/null
+++ b/automotive/audiocontrol/2.0/IAudioControl.hal
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@2.0;
+
+import ICloseHandle;
+import IFocusListener;
+import android.hardware.audio.common@6.0::AudioUsage;
+
+/**
+ * Interacts with the car's audio subsystem to manage audio sources and volumes
+ */
+interface IAudioControl {
+    /**
+     * Registers focus listener to be used by HAL for requesting and abandoning audio focus.
+     *
+     * It is expected that there will only ever be a single focus listener registered. If the
+     * observer dies, the HAL implementation must unregister observer automatically. If called when
+     * a listener is already registered, the existing one should be unregistered and replaced with
+     * the new listener.
+     *
+     * @param listener the listener interface
+     * @return closeHandle A handle to unregister observer.
+     */
+    registerFocusListener(IFocusListener listener) generates (ICloseHandle closeHandle);
+
+    /**
+     * Notifies HAL of changes in audio focus status for focuses requested or abandoned by the HAL.
+     *
+     * This will be called in response to IFocusListener's requestAudioFocus and
+     * abandonAudioFocus, as well as part of any change in focus being held by the HAL due focus
+     * request from other activities or services.
+     *
+     * The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
+     * is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
+     *
+     * @param usage The audio usage associated with the focus change {@code AttributeUsage}
+     * @param zoneId The identifier for the audio zone that the HAL is playing the stream in
+     * @param focusChange the AudioFocusChange that has occurred
+     */
+    oneway onAudioFocusChange(bitfield<AudioUsage> usage, int32_t zoneId,
+        bitfield<AudioFocusChange> focusChange);
+
+    /**
+     * Control the right/left balance setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the right (+) or left (-) side of
+     * the car. 0.0 means "centered". +1.0 means fully right. -1.0 means fully left.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setBalanceTowardRight(float value);
+
+    /**
+     * Control the fore/aft fade setting of the car speakers.
+     *
+     * This is intended to shift the speaker volume toward the front (+) or back (-) of the car.
+     * 0.0 means "centered". +1.0 means fully forward. -1.0 means fully rearward.
+     *
+     * A value outside the range -1 to 1 must be clamped by the implementation to the -1 to 1
+     * range.
+     */
+    oneway setFadeTowardFront(float value);
+};
diff --git a/automotive/audiocontrol/2.0/ICloseHandle.hal b/automotive/audiocontrol/2.0/ICloseHandle.hal
new file mode 100644
index 0000000..537af6d
--- /dev/null
+++ b/automotive/audiocontrol/2.0/ICloseHandle.hal
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@2.0;
+
+/**
+ * Represents a generic close handle to remove a callback that doesn't need
+ * active interface.
+ *
+ * When close() is called OR when the interface is released, the underlying
+ * resources must be freed.
+ */
+interface ICloseHandle {
+    /**
+     * Closes the handle.
+     *
+     * The call must not fail and must be issued by the client at most once.
+     * Otherwise, the server must ignore subsequent calls.
+     */
+    close();
+};
diff --git a/automotive/audiocontrol/2.0/IFocusListener.hal b/automotive/audiocontrol/2.0/IFocusListener.hal
new file mode 100644
index 0000000..4fd5ef0
--- /dev/null
+++ b/automotive/audiocontrol/2.0/IFocusListener.hal
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@2.0;
+
+import android.hardware.audio.common@6.0::AudioUsage;
+
+/**
+ * Callback interface for audio focus listener.
+ *
+ * For typical configuration, the listener the car audio service.
+ */
+interface IFocusListener {
+    /**
+     * Called whenever HAL is requesting focus as it is starting to play audio of a given usage in a
+     * specified zone.
+     *
+     * In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This
+     * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
+     * before playing audio.
+     *
+     * @param usage The audio usage associated with the focus request {@code AttributeUsage}
+     * @param zoneId The identifier for the audio zone where the HAL is requesting focus
+     * @param focusGain The AudioFocusChange associated with this request. Should be one of the
+     * following: GAIN, GAIN_TRANSIENT, GAIN_TRANSIENT_MAY_DUCK, GAIN_TRANSIENT_EXCLUSIVE.
+     */
+    oneway requestAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId,
+        bitfield<AudioFocusChange> focusGain);
+
+    /**
+     * Called whenever HAL is abandoning focus as it is finished playing audio of a given usage in a
+     * specific zone.
+     *
+     * In response, IAudioControl#onAudioFocusChange will be called with focusChange status. This
+     * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
+     * before stopping audio playback.
+     *
+     * @param usage The audio usage for which the HAL is abandoning focus {@code AttributeUsage}
+     * @param zoneId The identifier for the audio zone that the HAL abandoning focus
+     */
+    oneway abandonAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId);
+};
diff --git a/automotive/audiocontrol/2.0/default/Android.bp b/automotive/audiocontrol/2.0/default/Android.bp
new file mode 100644
index 0000000..44ad028
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+    name: "android.hardware.automotive.audiocontrol@2.0-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "AudioControl.cpp",
+        "service.cpp",
+        "CloseHandle.cpp",
+    ],
+    init_rc: ["android.hardware.automotive.audiocontrol@2.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.automotive.audiocontrol@2.0",
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+    vintf_fragments: ["audiocontrol2_manifest.xml"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/automotive/audiocontrol/2.0/default/AudioControl.cpp b/automotive/audiocontrol/2.0/default/AudioControl.cpp
new file mode 100644
index 0000000..6505e34
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/AudioControl.cpp
@@ -0,0 +1,60 @@
+#include "AudioControl.h"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "CloseHandle.h"
+
+namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
+
+AudioControl::AudioControl() {}
+
+Return<sp<ICloseHandle>> AudioControl::registerFocusListener(const sp<IFocusListener>& listener) {
+    LOG(DEBUG) << "registering focus listener";
+    sp<ICloseHandle> closeHandle(nullptr);
+
+    if (listener) {
+        mFocusListener = listener;
+
+        closeHandle = new CloseHandle([this, listener]() {
+            if (mFocusListener == listener) {
+                mFocusListener = nullptr;
+            }
+        });
+    } else {
+        LOG(ERROR) << "Unexpected nullptr for listener resulting in no-op.";
+    }
+
+    return closeHandle;
+}
+
+Return<void> AudioControl::setBalanceTowardRight(float value) {
+    // For completeness, lets bounds check the input...
+    if (isValidValue(value)) {
+        LOG(ERROR) << "Balance value out of range -1 to 1 at " << value;
+    } else {
+        // Just log in this default mock implementation
+        LOG(INFO) << "Balance set to " << value;
+    }
+    return Void();
+}
+
+Return<void> AudioControl::setFadeTowardFront(float value) {
+    // For completeness, lets bounds check the input...
+    if (isValidValue(value)) {
+        LOG(ERROR) << "Fader value out of range -1 to 1 at " << value;
+    } else {
+        // Just log in this default mock implementation
+        LOG(INFO) << "Fader set to " << value;
+    }
+    return Void();
+}
+
+Return<void> AudioControl::onAudioFocusChange(hidl_bitfield<AudioUsage> usage, int zoneId,
+                                              hidl_bitfield<AudioFocusChange> focusChange) {
+    LOG(INFO) << "Focus changed: " << static_cast<int>(focusChange) << " for usage "
+              << static_cast<int>(usage) << " in zone " << zoneId;
+    return Void();
+}
+
+}  // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
diff --git a/automotive/audiocontrol/2.0/default/AudioControl.h b/automotive/audiocontrol/2.0/default/AudioControl.h
new file mode 100644
index 0000000..475a693
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/AudioControl.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H
+#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H
+
+#include <android/hardware/audio/common/6.0/types.h>
+#include <android/hardware/automotive/audiocontrol/2.0/IAudioControl.h>
+#include <android/hardware/automotive/audiocontrol/2.0/ICloseHandle.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+using android::hardware::audio::common::V6_0::AudioUsage;
+
+namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
+
+class AudioControl : public IAudioControl {
+  public:
+    // Methods from ::android::hardware::automotive::audiocontrol::V2_0::IAudioControl follow.
+    Return<sp<ICloseHandle>> registerFocusListener(const sp<IFocusListener>& listener);
+    Return<void> onAudioFocusChange(hidl_bitfield<AudioUsage> usage, int zoneId,
+                                    hidl_bitfield<AudioFocusChange> focusChange);
+    Return<void> setBalanceTowardRight(float value) override;
+    Return<void> setFadeTowardFront(float value) override;
+
+    // Implementation details
+    AudioControl();
+
+  private:
+    sp<IFocusListener> mFocusListener;
+    static bool isValidValue(float value) { return (value > 1.0f) || (value < -1.0f); }
+};
+
+}  // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
+
+#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V2_0_AUDIOCONTROL_H
diff --git a/automotive/audiocontrol/2.0/default/CloseHandle.cpp b/automotive/audiocontrol/2.0/default/CloseHandle.cpp
new file mode 100644
index 0000000..bc47931
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/CloseHandle.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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 "CloseHandle.h"
+
+namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
+
+CloseHandle::CloseHandle(Callback callback) : mCallback(callback) {}
+
+CloseHandle::~CloseHandle() {
+    close();
+}
+
+Return<void> CloseHandle::close() {
+    const auto wasClosed = mIsClosed.exchange(true);
+    if (wasClosed) return {};
+
+    if (mCallback) mCallback();
+    return {};
+}
+
+}  // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
diff --git a/automotive/audiocontrol/2.0/default/CloseHandle.h b/automotive/audiocontrol/2.0/default/CloseHandle.h
new file mode 100644
index 0000000..6caf0bf
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/CloseHandle.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/hardware/automotive/audiocontrol/2.0/ICloseHandle.h>
+
+namespace android::hardware::automotive::audiocontrol::V2_0::implementation {
+
+/** Generic ICloseHandle implementation ignoring double-close events. */
+class CloseHandle : public ICloseHandle {
+  public:
+    using Callback = std::function<void()>;
+
+    /**
+     * Create a handle with a callback.
+     *
+     * The callback is guaranteed to be called exactly once.
+     *
+     * \param callback Called on the first close() call, or on destruction of the handle
+     */
+    CloseHandle(Callback callback = nullptr);
+    virtual ~CloseHandle();
+
+    Return<void> close() override;
+
+  private:
+    const Callback mCallback;
+    std::atomic<bool> mIsClosed = false;
+
+    DISALLOW_COPY_AND_ASSIGN(CloseHandle);
+};
+
+}  // namespace android::hardware::automotive::audiocontrol::V2_0::implementation
diff --git a/automotive/audiocontrol/2.0/default/android.hardware.automotive.audiocontrol@2.0-service.rc b/automotive/audiocontrol/2.0/default/android.hardware.automotive.audiocontrol@2.0-service.rc
new file mode 100644
index 0000000..81c9be4
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/android.hardware.automotive.audiocontrol@2.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.audiocontrol-hal-2.0 /vendor/bin/hw/android.hardware.automotive.audiocontrol@2.0-service
+    class hal
+    user audioserver
+    group system
diff --git a/automotive/audiocontrol/2.0/default/audiocontrol2_manifest.xml b/automotive/audiocontrol/2.0/default/audiocontrol2_manifest.xml
new file mode 100644
index 0000000..42d23ed
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/audiocontrol2_manifest.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/automotive/audiocontrol/2.0/default/service.cpp b/automotive/audiocontrol/2.0/default/service.cpp
new file mode 100644
index 0000000..dcc46c3
--- /dev/null
+++ b/automotive/audiocontrol/2.0/default/service.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 <unistd.h>
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "AudioControl.h"
+
+// libhidl:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::automotive::audiocontrol::V2_0::IAudioControl;
+
+// The namespace in which all our implementation code lives
+using namespace android::hardware::automotive::audiocontrol::V2_0::implementation;
+using namespace android;
+
+// Main service entry point
+int main() {
+    // Create an instance of our service class
+    android::sp<IAudioControl> service = new AudioControl();
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+    if (service->registerAsService() != OK) {
+        LOG(ERROR) << "registerAsService failed";
+        return 1;
+    }
+
+    // Join (forever) the thread pool we created for the service above
+    joinRpcThreadpool();
+
+    // We don't ever actually expect to return, so return an error if we do get here
+    return 2;
+}
\ No newline at end of file
diff --git a/automotive/audiocontrol/2.0/types.hal b/automotive/audiocontrol/2.0/types.hal
new file mode 100644
index 0000000..65b0988
--- /dev/null
+++ b/automotive/audiocontrol/2.0/types.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.audiocontrol@2.0;
+
+/**
+ * Changes in audio focus that can be experienced
+ */
+enum AudioFocusChange : uint32_t {
+    NONE = 0,
+    GAIN = 1,
+    GAIN_TRANSIENT = 2,
+    GAIN_TRANSIENT_MAY_DUCK = 3,
+    GAIN_TRANSIENT_EXCLUSIVE = 4,
+    LOSS = -1 * GAIN,
+    LOSS_TRANSIENT = -1 * GAIN_TRANSIENT,
+    LOSS_TRANSIENT_CAN_DUCK = -1 * GAIN_TRANSIENT_MAY_DUCK,
+};
diff --git a/automotive/audiocontrol/2.0/vts/functional/Android.bp b/automotive/audiocontrol/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..520b042
--- /dev/null
+++ b/automotive/audiocontrol/2.0/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "VtsHalAudioControlV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalAudioControlV2_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.automotive.audiocontrol@2.0",
+        "libgmock",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp b/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp
new file mode 100644
index 0000000..0c10664
--- /dev/null
+++ b/automotive/audiocontrol/2.0/vts/functional/VtsHalAudioControlV2_0TargetTest.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalAudioControlTest"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/ProcessState.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include <android/hardware/audio/common/6.0/types.h>
+#include <android/hardware/automotive/audiocontrol/2.0/IAudioControl.h>
+#include <android/hardware/automotive/audiocontrol/2.0/types.h>
+#include <android/log.h>
+
+using namespace ::android::hardware::automotive::audiocontrol::V2_0;
+using ::android::sp;
+using ::android::hardware::hidl_bitfield;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V6_0::AudioUsage;
+
+// The main test class for the automotive AudioControl HAL
+class CarAudioControlHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        // Make sure we can connect to the driver
+        pAudioControl = IAudioControl::getService(GetParam());
+        ASSERT_NE(pAudioControl.get(), nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+  protected:
+    sp<IAudioControl> pAudioControl;  // Every test needs access to the service
+};
+
+//
+// Tests start here...
+//
+
+/*
+ * Fader exercise test.  Note that only a subjective observer could determine if the
+ * fader actually works.  The only thing we can do is exercise the HAL and if the HAL crashes,
+ * we _might_ get a test failure if that breaks the connection to the driver.
+ */
+TEST_P(CarAudioControlHidlTest, FaderExercise) {
+    ALOGI("Fader exercise test (silent)");
+
+    // Set the fader all the way to the back
+    pAudioControl->setFadeTowardFront(-1.0f);
+
+    // Set the fader all the way to the front
+    pAudioControl->setFadeTowardFront(1.0f);
+
+    // Set the fader part way toward the back
+    pAudioControl->setFadeTowardFront(-0.333f);
+
+    // Set the fader to a out of bounds value (driver should clamp)
+    pAudioControl->setFadeTowardFront(99999.9f);
+
+    // Set the fader back to the middle
+    pAudioControl->setFadeTowardFront(0.0f);
+}
+
+/*
+ * Balance exercise test.
+ */
+TEST_P(CarAudioControlHidlTest, BalanceExercise) {
+    ALOGI("Balance exercise test (silent)");
+
+    // Set the balance all the way to the left
+    pAudioControl->setBalanceTowardRight(-1.0f);
+
+    // Set the balance all the way to the right
+    pAudioControl->setBalanceTowardRight(1.0f);
+
+    // Set the balance part way toward the left
+    pAudioControl->setBalanceTowardRight(-0.333f);
+
+    // Set the balance to a out of bounds value (driver should clamp)
+    pAudioControl->setBalanceTowardRight(99999.9f);
+
+    // Set the balance back to the middle
+    pAudioControl->setBalanceTowardRight(0.0f);
+}
+
+struct FocusListenerMock : public IFocusListener {
+    MOCK_METHOD(Return<void>, requestAudioFocus,
+                (hidl_bitfield<AudioUsage> usage, int zoneId,
+                 hidl_bitfield<AudioFocusChange> focusGain));
+    MOCK_METHOD(Return<void>, abandonAudioFocus, (hidl_bitfield<AudioUsage> usage, int zoneId));
+};
+
+/*
+ * Test focus listener registration.
+ *
+ * Verifies that:
+ * - registerFocusListener succeeds;
+ * - registering a second listener succeeds in replacing the first;
+ * - closing handle does not crash;
+ */
+TEST_P(CarAudioControlHidlTest, FocusListenerRegistration) {
+    ALOGI("Focus listener test");
+
+    sp<FocusListenerMock> listener = new FocusListenerMock();
+
+    auto hidlResult = pAudioControl->registerFocusListener(listener);
+    ASSERT_TRUE(hidlResult.isOk());
+
+    sp<FocusListenerMock> listener2 = new FocusListenerMock();
+
+    auto hidlResult2 = pAudioControl->registerFocusListener(listener2);
+    ASSERT_TRUE(hidlResult2.isOk());
+
+    const sp<ICloseHandle>& closeHandle = hidlResult2;
+    closeHandle->close();
+};
+
+TEST_P(CarAudioControlHidlTest, FocusChangeExercise) {
+    ALOGI("Focus Change test");
+
+    pAudioControl->onAudioFocusChange(AudioUsage::MEDIA | 0, 0,
+                                      AudioFocusChange::GAIN_TRANSIENT | 0);
+};
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, CarAudioControlHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IAudioControl::descriptor)),
+        android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/biometrics/face/1.1/Android.bp b/biometrics/face/1.1/Android.bp
new file mode 100644
index 0000000..2206597
--- /dev/null
+++ b/biometrics/face/1.1/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.biometrics.face@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IBiometricsFace.hal",
+    ],
+    interfaces: [
+        "android.hardware.biometrics.face@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/biometrics/face/1.1/IBiometricsFace.hal b/biometrics/face/1.1/IBiometricsFace.hal
new file mode 100644
index 0000000..975001f
--- /dev/null
+++ b/biometrics/face/1.1/IBiometricsFace.hal
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.face@1.1;
+import @1.0::IBiometricsFace;
+import @1.0::Status;
+import @1.0::Feature;
+
+/**
+ * The HAL interface for biometric face authentication.
+ */
+interface IBiometricsFace extends @1.0::IBiometricsFace {
+    /**
+     * Enrolls a user's face for a remote client, for example Android Auto.
+     *
+     * The HAL implementation is responsible for creating a secure communication
+     * channel and receiving the enrollment images from a mobile device with
+     * face authentication hardware.
+     *
+     * Note that the Hardware Authentication Token must be valid for the
+     * duration of enrollment and thus should be explicitly invalidated by a
+     * call to revokeChallenge() when enrollment is complete, to reduce the
+     * window of opportunity to re-use the challenge and HAT. For example,
+     * Settings calls generateChallenge() once to allow the user to enroll one
+     * or more faces or toggle secure settings without having to re-enter the
+     * PIN/pattern/password. Once the user completes the operation, Settings
+     * invokes revokeChallenge() to close the transaction. If the HAT is expired,
+     * the implementation must invoke onError with UNABLE_TO_PROCESS.
+     *
+     * Requirements for using this API:
+     * - Mobile devices MUST NOT delegate enrollment to another device by calling
+     * this API. This feature is intended only to allow enrollment on devices
+     * where it is impossible to enroll locally on the device.
+     * - The path MUST be protected by a secret key with rollback protection.
+     * - Synchronizing between devices MUST be accomplished by having both
+     * devices agree on a secret PIN entered by the user (similar to BT
+     * pairing procedure) and use a salted version of that PIN plus other secret
+     * to encrypt traffic.
+     * - All communication to/from the remote device MUST be encrypted and signed
+     * to prevent image injection and other man-in-the-middle type attacks.
+     * - generateChallenge() and revokeChallenge() MUST be implemented on both
+     * remote and local host (e.g. hash the result of the remote host with a
+     * local secret before responding to the API call) and any transmission of
+     * the challenge between hosts MUST be signed to prevent man-in-the-middle
+     * attacks.
+     * - In the event of a lost connection, the result of the last
+     * generateChallenge() MUST be invalidated and the process started over.
+     * - Both the remote and local host MUST honor the timeout and invalidate the
+     * challenge.
+     *
+     * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
+     * method.
+     *
+     * @param hat A valid Hardware Authentication Token, generated as a result
+     *     of a generateChallenge() challenge being wrapped by the gatekeeper
+     *     after a successful strong authentication request.
+     * @param timeoutSec A timeout in seconds, after which this enroll
+     *     attempt is cancelled. Note that the framework can continue
+     *     enrollment by calling this again with a valid HAT. This timeout is
+     *     expected to be used to limit power usage if the device becomes idle
+     *     during enrollment. The implementation is expected to send
+     *     ERROR_TIMEOUT if this happens.
+     * @param disabledFeatures A list of features to be disabled during
+     *     enrollment. Note that all features are enabled by default.
+     * @return status The status of this method call.
+     */
+    enrollRemotely(vec<uint8_t> hat, uint32_t timeoutSec,
+        vec<Feature> disabledFeatures) generates (Status status);
+};
diff --git a/biometrics/face/1.1/vts/functional/Android.bp b/biometrics/face/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..ccbb399
--- /dev/null
+++ b/biometrics/face/1.1/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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.
+ */
+
+cc_test {
+    name: "VtsHalBiometricsFaceV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBiometricsFaceV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.biometrics.face@1.0",
+        "android.hardware.biometrics.face@1.1",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp b/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
new file mode 100644
index 0000000..c2431c6
--- /dev/null
+++ b/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "biometrics_face_hidl_hal_test"
+
+#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
+#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <chrono>
+#include <cstdint>
+#include <random>
+
+using android::sp;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
+using android::hardware::biometrics::face::V1_0::FaceError;
+using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
+using android::hardware::biometrics::face::V1_0::OptionalUint64;
+using android::hardware::biometrics::face::V1_0::Status;
+using android::hardware::biometrics::face::V1_1::IBiometricsFace;
+
+namespace {
+
+// Arbitrary, nonexistent userId
+constexpr uint32_t kUserId = 9;
+constexpr uint32_t kTimeoutSec = 3;
+constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
+constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
+constexpr char kCallbackNameOnError[] = "onError";
+
+// Callback arguments that need to be captured for the tests.
+struct FaceCallbackArgs {
+    // The error passed to the last onError() callback.
+    FaceError error;
+
+    // The userId passed to the last callback.
+    int32_t userId;
+};
+
+// Test callback class for the BiometricsFace HAL.
+// The HAL will call these callback methods to notify about completed operations
+// or encountered errors.
+class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
+                     public IBiometricsFaceClientCallback {
+  public:
+    Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override { return Void(); }
+
+    Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
+        return Void();
+    }
+
+    Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
+        return Void();
+    }
+
+    Return<void> onError(uint64_t, int32_t userId, FaceError error, int32_t) override {
+        FaceCallbackArgs args = {};
+        args.error = error;
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnError, args);
+        return Void();
+    }
+
+    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override { return Void(); }
+
+    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
+        return Void();
+    }
+
+    Return<void> onLockoutChanged(uint64_t) override { return Void(); }
+};
+
+// Test class for the BiometricsFace HAL.
+class FaceHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        mService = IBiometricsFace::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        mCallback = new FaceCallback();
+        mCallback->SetWaitTimeoutDefault(kTimeout);
+        Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
+            ASSERT_EQ(Status::OK, res.status);
+            // Makes sure the "deviceId" represented by "res.value" is not 0.
+            // 0 would mean the HIDL is not available.
+            ASSERT_NE(0UL, res.value);
+        });
+        ASSERT_TRUE(ret1.isOk());
+        Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
+        ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
+    }
+
+    void TearDown() override {}
+
+    sp<IBiometricsFace> mService;
+    sp<FaceCallback> mCallback;
+};
+
+// enroll with an invalid (all zeroes) HAT should fail.
+TEST_P(FaceHidlTest, EnrollRemotelyZeroHatTest) {
+    // Filling HAT with zeros
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; i++) {
+        token[i] = 0;
+    }
+
+    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+// enroll with an invalid HAT should fail.
+TEST_P(FaceHidlTest, EnrollRemotelyGarbageHatTest) {
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; ++i) {
+        token[i] = dist(gen);
+    }
+
+    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+}  // anonymous namespace
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, FaceHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/biometrics/fingerprint/2.2/Android.bp b/biometrics/fingerprint/2.2/Android.bp
new file mode 100644
index 0000000..6c769ac
--- /dev/null
+++ b/biometrics/fingerprint/2.2/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.biometrics.fingerprint@2.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBiometricsFingerprint.hal",
+        "IBiometricsFingerprintClientCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.biometrics.fingerprint@2.1",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal b/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal
new file mode 100644
index 0000000..0651034
--- /dev/null
+++ b/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.biometrics.fingerprint@2.2;
+
+import @2.1::IBiometricsFingerprint;
+import @2.1::RequestStatus;
+
+interface IBiometricsFingerprint extends @2.1::IBiometricsFingerprint {
+    /**
+     * Fingerprint enroll request:
+     * Switches the HAL state machine to collect and store a new fingerprint
+     * template. Switches back as soon as enroll is complete, signalled by
+     * (fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENROLLING &&
+     *  fingerprintMsg.data.enroll.samplesRemaining == 0)
+     * or after timeoutSec seconds.
+     * The fingerprint template must be assigned to the group gid.
+     *
+     * @param hat a valid Hardware Authentication Token (HAT), generated
+     * as a result of a preEnroll() call.
+     * @param gid a framework defined fingerprint set (group) id.
+     * @param timeoutSec a timeout in seconds.
+     * @param windowId optional ID of an illumination window for optical under
+     * display fingerprint sensors. Must contain a null pointer if not used.
+     *
+     * @return debugErrno is a value the framework logs in case it is not 0.
+     *
+     * A notify() function may be called with a more detailed error structure.
+     */
+    enroll_2_2(vec<uint8_t> hat, uint32_t gid, uint32_t timeoutSec, handle windowId)
+        generates (RequestStatus debugErrno);
+
+    /**
+     * Authenticates an operation identified by operationId
+     *
+     * @param operationId operation id.
+     * @param gid fingerprint group id.
+     * @param windowId optional ID of an illumination window for optical under
+     * display fingerprint sensors. Must contain a null pointer if not used.
+     *
+     * @return debugErrno is a value the framework logs in case it is not 0.
+     */
+    authenticate_2_2(uint64_t operationId, uint32_t gid, handle windowId)
+        generates (RequestStatus debugErrno);
+};
diff --git a/biometrics/fingerprint/2.2/IBiometricsFingerprintClientCallback.hal b/biometrics/fingerprint/2.2/IBiometricsFingerprintClientCallback.hal
new file mode 100644
index 0000000..14c2b12
--- /dev/null
+++ b/biometrics/fingerprint/2.2/IBiometricsFingerprintClientCallback.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.biometrics.fingerprint@2.2;
+
+import @2.1::IBiometricsFingerprintClientCallback;
+
+/*
+ * This HAL interface communicates asynchronous results from the
+ * fingerprint driver in response to user actions on the fingerprint sensor
+ */
+interface IBiometricsFingerprintClientCallback extends @2.1::IBiometricsFingerprintClientCallback {
+    /**
+     * Sent when a fingerprint image is acquired by the sensor
+     * @param deviceId the instance of this fingerprint device
+     * @param acquiredInfo a message about the quality of the acquired image
+     * @param vendorCode a vendor-specific message about the quality of the image. Only
+     *        valid when acquiredInfo == ACQUIRED_VENDOR
+     */
+    oneway onAcquired_2_2(uint64_t deviceId, FingerprintAcquiredInfo acquiredInfo,
+        int32_t vendorCode);
+};
diff --git a/biometrics/fingerprint/2.2/types.hal b/biometrics/fingerprint/2.2/types.hal
new file mode 100644
index 0000000..2c1d3f3
--- /dev/null
+++ b/biometrics/fingerprint/2.2/types.hal
@@ -0,0 +1,42 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.biometrics.fingerprint@2.2;
+
+import @2.1::FingerprintAcquiredInfo;
+
+/**
+ * Fingerprint acquisition info is meant as feedback for the current operation.
+ * Anything but START and ACQUIRED_GOOD must be shown to the user as feedback on
+ * how to take action on the current operation. For example,
+ * ACQUIRED_IMAGER_DIRTY may be used to tell the user to clean the sensor if it
+ * is detected to be dirty.
+ * If this causes the current operation to fail, an additional ERROR_CANCELED
+ * must be sent to stop the operation in progress (e.g. enrollment).
+ * In general, these messages will result in a "Try again" message.
+ */
+enum FingerprintAcquiredInfo : @2.1::FingerprintAcquiredInfo {
+    /**
+     * This message represents the earliest message sent at the beginning of the
+     * authentication pipeline. It is expected to be used to measure latency. For
+     * example, in a camera-based authentication system it's expected to be sent
+     * prior to camera initialization. Note this should be sent whenever
+     * authentication is restarted (see IBiometricsFace#userActivity).
+     * The framework will measure latency based on the time between the last START
+     * message and the onAuthenticated callback.
+     */
+    START = 7,
+};
diff --git a/biometrics/fingerprint/2.2/vts/functional/Android.bp b/biometrics/fingerprint/2.2/vts/functional/Android.bp
new file mode 100644
index 0000000..496570c
--- /dev/null
+++ b/biometrics/fingerprint/2.2/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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.
+ */
+
+cc_test {
+    name: "VtsHalBiometricsFingerprintV2_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBiometricsFingerprintV2_2TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.biometrics.fingerprint@2.1",
+        "android.hardware.biometrics.fingerprint@2.2",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp
new file mode 100644
index 0000000..50bd4ab
--- /dev/null
+++ b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "fingerprint_hidl_hal_test"
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/properties.h>
+#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
+#include <android/hardware/biometrics/fingerprint/2.2/IBiometricsFingerprint.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/ServiceManagement.h>
+
+#include <cinttypes>
+#include <random>
+
+using android::sp;
+using android::base::GetUintProperty;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::biometrics::fingerprint::V2_1::FingerprintAcquiredInfo;
+using android::hardware::biometrics::fingerprint::V2_1::FingerprintError;
+using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
+using android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
+using android::hardware::biometrics::fingerprint::V2_2::IBiometricsFingerprint;
+
+namespace {
+
+constexpr uint32_t kTimeoutSec = 3;
+constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
+constexpr uint32_t kGroupId = 99;
+constexpr char kCallbackNameOnError[] = "onError";
+
+// Callback arguments that need to be captured for the tests.
+struct FingerprintCallbackArgs {
+    // The error passed to the last onError() callback.
+    FingerprintError error;
+
+    // The deviceId passed to the last callback.
+    uint64_t deviceId;
+};
+
+// Test callback class for the BiometricsFingerprint HAL.
+// The HAL will call these callback methods to notify about completed operations
+// or encountered errors.
+class FingerprintCallback : public ::testing::VtsHalHidlTargetCallbackBase<FingerprintCallbackArgs>,
+                            public IBiometricsFingerprintClientCallback {
+  public:
+    Return<void> onEnrollResult(uint64_t, uint32_t, uint32_t, uint32_t) override { return Void(); }
+
+    Return<void> onAcquired(uint64_t, FingerprintAcquiredInfo, int32_t) override { return Void(); }
+
+    Return<void> onAuthenticated(uint64_t, uint32_t, uint32_t, const hidl_vec<uint8_t>&) override {
+        return Void();
+    }
+
+    Return<void> onError(uint64_t deviceId, FingerprintError error, int32_t) override {
+        FingerprintCallbackArgs args = {};
+        args.error = error;
+        args.deviceId = deviceId;
+        NotifyFromCallback(kCallbackNameOnError, args);
+        return Void();
+    }
+
+    Return<void> onRemoved(uint64_t, uint32_t, uint32_t, uint32_t) override { return Void(); }
+
+    Return<void> onEnumerate(uint64_t, uint32_t, uint32_t, uint32_t) override { return Void(); }
+};
+
+class FingerprintHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        mService = IBiometricsFingerprint::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        mCallback = new FingerprintCallback();
+        mCallback->SetWaitTimeoutDefault(kTimeout);
+        Return<uint64_t> ret1 = mService->setNotify(mCallback);
+        ASSERT_NE(0UL, static_cast<uint64_t>(ret1));
+
+        /*
+         * Devices shipped from now on will instead store
+         * fingerprint data under /data/vendor_de/<user-id>/fpdata.
+         * Support for /data/vendor_de and /data/vendor_ce has been added to vold.
+         */
+
+        auto api_level = GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
+        if (api_level == 0) {
+            api_level = GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+        }
+        ASSERT_NE(api_level, 0);
+
+        // 27 is the API number for O-MR1
+        string tmpDir;
+        if (api_level <= 27) {
+            tmpDir = "/data/system/users/0/fpdata/";
+        } else {
+            tmpDir = "/data/vendor_de/0/fpdata/";
+        }
+
+        Return<RequestStatus> res = mService->setActiveGroup(kGroupId, tmpDir);
+        ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
+    }
+
+    sp<IBiometricsFingerprint> mService;
+    sp<FingerprintCallback> mCallback;
+};
+
+// Enroll with an invalid (all zeroes) HAT should fail.
+TEST_P(FingerprintHidlTest, EnrollZeroHatTest) {
+    // Filling HAT with zeros
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; i++) {
+        token[i] = 0;
+    }
+
+    hidl_handle windowId = nullptr;
+    Return<RequestStatus> ret = mService->enroll_2_2(token, kGroupId, kTimeoutSec, windowId);
+    ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(ret));
+
+    // At least one call to onError should occur
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    ASSERT_NE(FingerprintError::ERROR_NO_ERROR, res.args->error);
+}
+
+// Enroll with an invalid (null) HAT should fail.
+TEST_P(FingerprintHidlTest, EnrollGarbageHatTest) {
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; ++i) {
+        token[i] = dist(gen);
+    }
+
+    hidl_handle windowId = nullptr;
+    Return<RequestStatus> ret = mService->enroll_2_2(token, kGroupId, kTimeoutSec, windowId);
+    ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(ret));
+
+    // At least one call to onError should occur
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    ASSERT_NE(FingerprintError::ERROR_NO_ERROR, res.args->error);
+}
+
+}  // anonymous namespace
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 IBiometricsFingerprint::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 24f114b..da10ef8 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -174,7 +174,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.dumpstate</name>
-        <version>1.0</version>
+        <version>1.1</version>
         <interface>
             <name>IDumpstateDevice</name>
             <instance>default</instance>
@@ -289,6 +289,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.light</name>
+        <interface>
+            <name>ILights</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.media.c2</name>
         <version>1.0-1</version>
diff --git a/current.txt b/current.txt
index 3af2d95..290dc1c 100644
--- a/current.txt
+++ b/current.txt
@@ -633,6 +633,8 @@
 4d85e814f94949dae4dc6cb82bbd7d6bb24ffafda6ddb2eac928d2a4fc2e21ce android.hardware.cas@1.2::types
 66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
 994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
+881aa8720fb1d69aa9843bfab69d810ab7654a61d2f5ab5e2626cbf240f24eaf android.hardware.dumpstate@1.1::types
+13b33f623521ded51a6c0f7ea5b77e97066d0aa1e38a83c2873f08ad67294f89 android.hardware.dumpstate@1.1::IDumpstateDevice
 3dacec7801968e1e4479724dc0180442d9e915466bff051f80996266b1a51c2c android.hardware.gnss@2.1::IGnss
 ba62e1e8993bfb9f27fa04816fa0f2241ae2d01edfa3d0c04182e2e5de80045c android.hardware.gnss@2.1::IGnssCallback
 ccdf3c0fb2c02a6d4dc57afb276c3497ae8172b80b00ebc0bf8a0238dd38b01d android.hardware.gnss@2.1::IGnssConfiguration
@@ -653,7 +655,8 @@
 65c16331e57f6dd68b3971f06f78fe9e3209afb60630c31705aa355f9a52bf0d android.hardware.neuralnetworks@1.3::IBuffer
 d1f382d14e1384b907d5bb5780df7f01934650d556fedbed2f15a90773c657d6 android.hardware.neuralnetworks@1.3::IDevice
 4167dc3ad35e9cd0d2057d4868c7675ae2c3c9d05bbd614c1f5dccfa5fd68797 android.hardware.neuralnetworks@1.3::IExecutionCallback
-7d23020248194abbee8091cc624f39a5a6d7ccba338b172d5d2d3df0cceffbee android.hardware.neuralnetworks@1.3::IPreparedModel
+29e26e83399b69c7998b787bd30426dd5baa2da350effca76bbee1ba877355c9 android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
+384fd9fd6e4d43ea11d407e52ea81da5242c3c5f4b458b8707d8feb652a13e36 android.hardware.neuralnetworks@1.3::IPreparedModel
 0439a1fbbec7f16e5e4c653d85ac685d51bfafbae15b8f8cca530acdd7d6a8ce android.hardware.neuralnetworks@1.3::IPreparedModelCallback
 5f1a4e0c29fc686ed476f9f04eed35e4405d21288cb2746b978d6891de5cc37d android.hardware.neuralnetworks@1.3::types
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
@@ -667,7 +670,7 @@
 ##
 # BEGIN Radio HAL Merge Conflict Avoidance Buffer - STOPSHIP if present
 ##
-616456d7ce4435d88995f9fe0025a76bca14bd70799e4ca3ff4bae74d54d1166 android.hardware.radio@1.5::types
+430f8449ddb24c02284da561bfd24bb5a2a226d9ed2aec38e876e323e2b7eeee android.hardware.radio@1.5::types
 c68f5bd87f747f8e7968ff66ecc548b2d26f8e186b7bb805c11d6c883a838fc6 android.hardware.radio@1.5::IRadio
 e96ae1c3a9c0689002ec2318e9c587f4f607c16a75a3cd38788b77eb91072021 android.hardware.radio@1.5::IRadioIndication
 9e962eff568dc8c712d83846f8c27460de5005ed9b836d3e08390e8aa56b5a46 android.hardware.radio@1.5::IRadioResponse
diff --git a/drm/1.2/vts/functional/drm_hal_common.cpp b/drm/1.2/vts/functional/drm_hal_common.cpp
index 02aa3a9..b169268 100644
--- a/drm/1.2/vts/functional/drm_hal_common.cpp
+++ b/drm/1.2/vts/functional/drm_hal_common.cpp
@@ -87,7 +87,7 @@
         return new DrmHalVTSClearkeyModule();
     }
 
-    return static_cast<DrmHalVTSVendorModule_V1*>(DrmHalTest::gVendorModules->getModule(instance));
+    return static_cast<DrmHalVTSVendorModule_V1*>(DrmHalTest::gVendorModules->getModuleByName(instance));
 }
 
 /**
@@ -120,21 +120,12 @@
         GTEST_SKIP() << "No vendor module installed";
     }
 
-    if (instance == "clearkey") {
-        // TODO(b/147449315)
-        // Only the clearkey plugged into the "default" instance supports
-        // this test. Currently the "clearkey" instance fails some tests
-        // here.
-        GTEST_SKIP() << "Clearkey tests don't work with 'clearkey' instance yet.";
-    }
-
     ASSERT_EQ(instance, vendorModule->getServiceName());
     contentConfigurations = vendorModule->getContentConfigurations();
 
     // If drm scheme not installed skip subsequent tests
-    if (drmFactory.get() == nullptr || !drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
-        vendorModule->setInstalled(false);
-        return;
+    if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
+        GTEST_SKIP() << "vendor module drm scheme not supported";
     }
 
     ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find " << vendorModule->getServiceName() <<  " drm@1.2 plugin";
diff --git a/drm/1.2/vts/functional/drm_hal_common.h b/drm/1.2/vts/functional/drm_hal_common.h
index b2d654c..03b1b87 100644
--- a/drm/1.2/vts/functional/drm_hal_common.h
+++ b/drm/1.2/vts/functional/drm_hal_common.h
@@ -62,14 +62,6 @@
 
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
 
-#define RETURN_IF_SKIPPED                                                                \
-    if (!vendorModule->isInstalled()) {                                                  \
-        GTEST_SKIP() << "This drm scheme not supported."                                 \
-                     << " library:" << GetParam()                                        \
-                     << " service-name:" << vendorModule->getServiceName() << std::endl; \
-        return;                                                                          \
-    }
-
 namespace android {
 namespace hardware {
 namespace drm {
@@ -131,9 +123,11 @@
    public:
      virtual void SetUp() override {
          DrmHalTest::SetUp();
-
-         if (vendorModule == nullptr) {
-             GTEST_SKIP() << "Instance not supported";
+         const uint8_t kClearKeyUUID[16] = {
+             0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+             0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+         if (!drmFactory->isCryptoSchemeSupported(kClearKeyUUID)) {
+             GTEST_SKIP() << "ClearKey not supported by " << GetParam();
          }
      }
     virtual void TearDown() override {}
diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp
index 54c5751..48becc1 100644
--- a/drm/1.2/vts/functional/drm_hal_test.cpp
+++ b/drm/1.2/vts/functional/drm_hal_test.cpp
@@ -53,7 +53,6 @@
  * Ensure drm factory supports module UUID Scheme
  */
 TEST_P(DrmHalTest, VendorUuidSupported) {
-    RETURN_IF_SKIPPED;
     auto res = drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kSwSecureCrypto);
     ALOGI("kVideoMp4 = %s res %d", kVideoMp4, (bool)res);
     EXPECT_TRUE(res);
@@ -63,7 +62,6 @@
  * Ensure drm factory doesn't support an invalid scheme UUID
  */
 TEST_P(DrmHalTest, InvalidPluginNotSupported) {
-    RETURN_IF_SKIPPED;
     const uint8_t kInvalidUUID[16] = {
         0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
         0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
@@ -74,7 +72,6 @@
  * Ensure drm factory doesn't support an empty UUID
  */
 TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) {
-    RETURN_IF_SKIPPED;
     hidl_array<uint8_t, 16> emptyUUID;
     memset(emptyUUID.data(), 0, 16);
     EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(emptyUUID, kVideoMp4, kSwSecureCrypto));
@@ -84,7 +81,6 @@
  * Ensure drm factory doesn't support an invalid mime type
  */
 TEST_P(DrmHalTest, BadMimeNotSupported) {
-    RETURN_IF_SKIPPED;
     EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kBadMime, kSwSecureCrypto));
 }
 
@@ -101,7 +97,6 @@
  * that is delivered back to the HAL.
  */
 TEST_P(DrmHalTest, DoProvisioning) {
-    RETURN_IF_SKIPPED;
     hidl_string certificateType;
     hidl_string certificateAuthority;
     hidl_vec<uint8_t> provisionRequest;
@@ -138,7 +133,6 @@
  * A get key request should fail if no sessionId is provided
  */
 TEST_P(DrmHalTest, GetKeyRequestNoSession) {
-    RETURN_IF_SKIPPED;
     SessionId invalidSessionId;
     hidl_vec<uint8_t> initData;
     KeyedVector optionalParameters;
@@ -156,7 +150,6 @@
  * invalid mime type
  */
 TEST_P(DrmHalTest, GetKeyRequestBadMime) {
-    RETURN_IF_SKIPPED;
     auto sessionId = openSession();
     hidl_vec<uint8_t> initData;
     KeyedVector optionalParameters;
@@ -193,7 +186,6 @@
  * Test drm plugin offline key support
  */
 TEST_P(DrmHalTest, OfflineLicenseTest) {
-    RETURN_IF_SKIPPED;
     auto sessionId = openSession();
     hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
 
@@ -233,7 +225,6 @@
  * Test drm plugin offline key state
  */
 TEST_P(DrmHalTest, OfflineLicenseStateTest) {
-    RETURN_IF_SKIPPED;
     auto sessionId = openSession();
     DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE);
     hidl_vec<uint8_t> keySetId = loadKeys(sessionId, content, KeyType::OFFLINE);
@@ -258,7 +249,6 @@
  * Negative offline license test. Remove empty keySetId
  */
 TEST_P(DrmHalTest, RemoveEmptyKeySetId) {
-    RETURN_IF_SKIPPED;
     KeySetId emptyKeySetId;
     Status err = drmPlugin->removeOfflineLicense(emptyKeySetId);
     EXPECT_EQ(Status::BAD_VALUE, err);
@@ -268,7 +258,6 @@
  * Negative offline license test. Get empty keySetId state
  */
 TEST_P(DrmHalTest, GetEmptyKeySetIdState) {
-    RETURN_IF_SKIPPED;
     KeySetId emptyKeySetId;
     auto res = drmPlugin->getOfflineLicenseState(emptyKeySetId, checkKeySetIdState<Status::BAD_VALUE, OfflineLicenseState::UNKNOWN>);
     EXPECT_OK(res);
@@ -278,7 +267,6 @@
  * Test that the plugin returns valid connected and max HDCP levels
  */
 TEST_P(DrmHalTest, GetHdcpLevels) {
-    RETURN_IF_SKIPPED;
     auto res = drmPlugin->getHdcpLevels_1_2(
             [&](StatusV1_2 status, const HdcpLevel &connectedLevel,
                 const HdcpLevel &maxLevel) {
@@ -294,7 +282,6 @@
  * the listener gets them.
  */
 TEST_P(DrmHalTest, ListenerKeysChange) {
-    RETURN_IF_SKIPPED;
     sp<DrmHalPluginListener> listener = new DrmHalPluginListener();
     auto res = drmPlugin->setListener(listener);
     EXPECT_OK(res);
@@ -326,7 +313,6 @@
  * Positive decrypt test.  "Decrypt" a single clear segment
  */
 TEST_P(DrmHalTest, ClearSegmentTest) {
-    RETURN_IF_SKIPPED;
     for (const auto& config : contentConfigurations) {
         for (const auto& key : config.keys) {
             const size_t kSegmentSize = 1024;
@@ -354,7 +340,6 @@
  * Verify data matches.
  */
 TEST_P(DrmHalTest, EncryptedAesCtrSegmentTest) {
-    RETURN_IF_SKIPPED;
     for (const auto& config : contentConfigurations) {
         for (const auto& key : config.keys) {
             const size_t kSegmentSize = 1024;
@@ -381,7 +366,6 @@
  * Negative decrypt test.  Decrypted frame too large to fit in output buffer
  */
 TEST_P(DrmHalTest, ErrorFrameTooLarge) {
-    RETURN_IF_SKIPPED;
     for (const auto& config : contentConfigurations) {
         for (const auto& key : config.keys) {
             const size_t kSegmentSize = 1024;
@@ -407,7 +391,6 @@
  * Negative decrypt test. Decrypt without loading keys.
  */
 TEST_P(DrmHalTest, EncryptedAesCtrSegmentTestNoKeys) {
-    RETURN_IF_SKIPPED;
     for (const auto& config : contentConfigurations) {
         for (const auto& key : config.keys) {
             vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
@@ -433,7 +416,6 @@
  * Ensure clearkey drm factory doesn't support security level higher than supported
  */
 TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) {
-    RETURN_IF_SKIPPED;
     const SecurityLevel kHwSecureAll = SecurityLevel::HW_SECURE_ALL;
     EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kHwSecureAll));
 }
@@ -442,7 +424,6 @@
  * Test resource contention during attempt to generate key request
  */
 TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) {
-    RETURN_IF_SKIPPED;
     Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorResourceContention);
     EXPECT_EQ(Status::OK, status);
     auto sessionId = openSession();
@@ -464,7 +445,6 @@
  * Test clearkey plugin offline key with mock error
  */
 TEST_P(DrmHalClearkeyTest, OfflineLicenseInvalidState) {
-    RETURN_IF_SKIPPED;
     auto sessionId = openSession();
     hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
     Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState);
@@ -486,7 +466,6 @@
  * Test SessionLostState is triggered on error
  */
 TEST_P(DrmHalClearkeyTest, SessionLostState) {
-    RETURN_IF_SKIPPED;
     sp<DrmHalPluginListener> listener = new DrmHalPluginListener();
     auto res = drmPlugin->setListener(listener);
     EXPECT_OK(res);
@@ -507,7 +486,6 @@
  * Negative decrypt test. Decrypt with invalid key.
  */
 TEST_P(DrmHalClearkeyTest, DecryptWithEmptyKey) {
-    RETURN_IF_SKIPPED;
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
     const uint32_t kClearBytes = 512;
@@ -545,7 +523,6 @@
  * Negative decrypt test. Decrypt with a key exceeds AES_BLOCK_SIZE.
  */
 TEST_P(DrmHalClearkeyTest, DecryptWithKeyTooLong) {
-    RETURN_IF_SKIPPED;
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
     const uint32_t kClearBytes = 512;
diff --git a/drm/1.2/vts/functional/vendor_modules.cpp b/drm/1.2/vts/functional/vendor_modules.cpp
index efcb90a..08131cf 100644
--- a/drm/1.2/vts/functional/vendor_modules.cpp
+++ b/drm/1.2/vts/functional/vendor_modules.cpp
@@ -23,6 +23,7 @@
 #include <utils/String8.h>
 #include <SharedLibrary.h>
 
+#include "drm_hal_vendor_module_api.h"
 #include "vendor_modules.h"
 
 using std::string;
@@ -69,4 +70,14 @@
     ModuleFactory moduleFactory = reinterpret_cast<ModuleFactory>(symbol);
     return (*moduleFactory)();
 }
+
+DrmHalVTSVendorModule* VendorModules::getModuleByName(const string& name) {
+    for (const auto &path : mPathList) {
+        auto module = getModule(path);
+        if (module->getServiceName() == name) {
+            return module;
+        }
+    }
+    return NULL;
+}
 };
diff --git a/drm/1.2/vts/functional/vendor_modules.h b/drm/1.2/vts/functional/vendor_modules.h
index 9b730ad..eacd2d1 100644
--- a/drm/1.2/vts/functional/vendor_modules.h
+++ b/drm/1.2/vts/functional/vendor_modules.h
@@ -47,6 +47,11 @@
     DrmHalVTSVendorModule* getModule(const std::string& path);
 
     /**
+     * Retrieve a DrmHalVTSVendorModule given a service name.
+     */
+    DrmHalVTSVendorModule* getModuleByName(const std::string& name);
+
+    /**
      * Return the list of paths to available vendor modules.
      */
     std::vector<std::string> getPathList() const {return mPathList;}
diff --git a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
index 96b13c5..343d4c9 100644
--- a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
+++ b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
@@ -78,6 +78,7 @@
     ASSERT_EQ(1, read(fds[0], &buff, 1)) << "dumped nothing";
 
     native_handle_close(handle);
+    native_handle_delete(handle);
 }
 
 // Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
@@ -96,6 +97,7 @@
     ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
 
     native_handle_close(handle);
+    native_handle_delete(handle);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/dumpstate/1.1/Android.bp b/dumpstate/1.1/Android.bp
new file mode 100644
index 0000000..2aa8c82
--- /dev/null
+++ b/dumpstate/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.dumpstate@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IDumpstateDevice.hal",
+    ],
+    interfaces: [
+        "android.hardware.dumpstate@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/dumpstate/1.1/IDumpstateDevice.hal b/dumpstate/1.1/IDumpstateDevice.hal
new file mode 100644
index 0000000..24831b3
--- /dev/null
+++ b/dumpstate/1.1/IDumpstateDevice.hal
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package android.hardware.dumpstate@1.1;
+
+import @1.0::IDumpstateDevice;
+
+interface IDumpstateDevice extends @1.0::IDumpstateDevice {
+    /**
+     * Extension of dumpstateBoard which also accepts a mode parameter to limit dumped data.
+     *
+     * For an example of when this is relevant, consider a bug report being generated with
+     * DumpstateMode::CONNECTIVITY - there is no reason to include camera or USB logs in this type
+     * of report.
+     *
+     * The 1.0 version of #dumpstateBoard(handle) should just delegate to this new method and pass
+     * DumpstateMode::DEFAULT and a timeout of 30,000ms (30 seconds).
+     *
+     * @param h A native handle with one or two valid file descriptors. The first FD is for text
+     *     output, the second (if present) is for binary output.
+     * @param mode A mode value to restrict dumped content.
+     * @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
+     *     If execution runs longer than this, the IDumpstateDevice service may be killed and only
+     *     partial information will be included in the report.
+     */
+    dumpstateBoard_1_1(handle h, DumpstateMode mode, uint64_t timeoutMillis);
+
+    /**
+     * Turns device vendor logging on or off.
+     *
+     * The setting should be persistent across reboots. Underlying implementations may need to start
+     * vendor logging daemons, set system properties, or change logging masks, for example. Given
+     * that many vendor logs contain significant amounts of private information and may come with
+     * memory/storage/battery impacts, calling this method on a user build should only be done after
+     * user consent has been obtained, e.g. from a toggle in developer settings.
+     *
+     * @param enable Whether to enable or disable device vendor logging.
+     * @return success Whether or not the change took effect.
+     */
+    setDeviceLoggingEnabled(bool enable) generates (bool success);
+};
diff --git a/dumpstate/1.1/types.hal b/dumpstate/1.1/types.hal
new file mode 100644
index 0000000..a6f391a
--- /dev/null
+++ b/dumpstate/1.1/types.hal
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package android.hardware.dumpstate@1.1;
+
+/**
+ * Constants that define the type of bug report being taken to restrict content appropriately.
+ */
+enum DumpstateMode : uint32_t {
+    /**
+     * Takes a bug report without user interference.
+     */
+    FULL = 0,
+
+    /**
+     * Interactive bug report, i.e. triggered by the user.
+     */
+    INTERACTIVE = 1,
+
+    /**
+     * Remote bug report triggered by DevicePolicyManager, for example.
+     */
+    REMOTE = 2,
+
+    /**
+     * Bug report triggered on a wear device.
+     */
+    WEAR = 3,
+
+    /**
+     * Bug report limited to only connectivity info (cellular, wifi, and networking). Sometimes
+     * called "telephony" in legacy contexts.
+     *
+     * All reported information MUST directly relate to connectivity debugging or customer support
+     * and MUST NOT contain unrelated private information. This information MUST NOT identify
+     * user-installed packages (UIDs are OK, package names are not), and MUST NOT contain logs of
+     * user application traffic.
+     */
+    CONNECTIVITY = 4,
+
+    /**
+     * Bug report limited to only wifi info.
+     */
+    WIFI = 5,
+
+    /**
+     * Default mode.
+     */
+    DEFAULT = 6
+};
diff --git a/dumpstate/1.1/vts/functional/Android.bp b/dumpstate/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..5267706
--- /dev/null
+++ b/dumpstate/1.1/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "VtsHalDumpstateV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalDumpstateV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.dumpstate@1.0",
+        "android.hardware.dumpstate@1.1",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
new file mode 100644
index 0000000..3b6051c
--- /dev/null
+++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "dumpstate_1_1_hidl_hal_test"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <vector>
+
+#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
+#include <android/hardware/dumpstate/1.1/types.h>
+#include <cutils/native_handle.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <log/log.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::dumpstate::V1_1::DumpstateMode;
+using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
+
+class DumpstateHidl1_1Test : public ::testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        dumpstate = IDumpstateDevice::getService(GetParam());
+        ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance";
+    }
+
+    sp<IDumpstateDevice> dumpstate;
+};
+
+#define TEST_FOR_DUMPSTATE_MODE(name, body, mode) \
+    TEST_P(DumpstateHidl1_1Test, name##_##mode) { body(DumpstateMode::mode); }
+
+#define TEST_FOR_ALL_DUMPSTATE_MODES(name, body)       \
+    TEST_FOR_DUMPSTATE_MODE(name, body, FULL);         \
+    TEST_FOR_DUMPSTATE_MODE(name, body, INTERACTIVE);  \
+    TEST_FOR_DUMPSTATE_MODE(name, body, REMOTE);       \
+    TEST_FOR_DUMPSTATE_MODE(name, body, WEAR);         \
+    TEST_FOR_DUMPSTATE_MODE(name, body, CONNECTIVITY); \
+    TEST_FOR_DUMPSTATE_MODE(name, body, WIFI);         \
+    TEST_FOR_DUMPSTATE_MODE(name, body, DEFAULT);
+
+const uint64_t kDefaultTimeoutMillis = 30 * 1000;  // 30 seconds
+
+// Negative test: make sure dumpstateBoard() doesn't crash when passed a null pointer.
+TEST_FOR_ALL_DUMPSTATE_MODES(TestNullHandle, [this](DumpstateMode mode) {
+    Return<void> status = dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+});
+
+// Negative test: make sure dumpstateBoard() ignores a handle with no FD.
+TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithNoFd, [this](DumpstateMode mode) {
+    native_handle_t* handle = native_handle_create(0, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+
+    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+});
+
+// Positive test: make sure dumpstateBoard() writes something to the FD.
+TEST_FOR_ALL_DUMPSTATE_MODES(TestOk, [this](DumpstateMode mode) {
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+    // Check that at least one byte was written
+    char buff;
+    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "dumped nothing";
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+});
+
+// Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
+TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithTwoFds, [this](DumpstateMode mode) {
+    int fds1[2];
+    int fds2[2];
+    ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
+    ASSERT_EQ(0, pipe2(fds2, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(2, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds1[1];
+    handle->data[1] = fds2[1];
+
+    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+});
+
+// Make sure dumpstateBoard_1_1 actually validates its arguments.
+TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Negative) {
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(-100),
+                                                        kDefaultTimeoutMillis);
+    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
+                                << status.description();
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+}
+
+TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Undefined) {
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(9001),
+                                                        kDefaultTimeoutMillis);
+    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
+                                << status.description();
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+}
+
+// Make sure toggling device logging doesn't crash.
+TEST_P(DumpstateHidl1_1Test, TestEnableDeviceLogging) {
+    Return<bool> status = dumpstate->setDeviceLoggingEnabled(true);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+}
+
+TEST_P(DumpstateHidl1_1Test, TestDisableDeviceLogging) {
+    Return<bool> status = dumpstate->setDeviceLoggingEnabled(false);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, DumpstateHidl1_1Test,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index e2f2670..a23d72c 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -57,7 +57,15 @@
 void TestRenderEngine::drawLayers() {
     base::unique_fd bufferFence;
     base::unique_fd readyFence;
-    mRenderEngine->drawLayers(mDisplaySettings, mCompositionLayers,
+
+    std::vector<const renderengine::LayerSettings*> compositionLayerPointers;
+    compositionLayerPointers.reserve(mCompositionLayers.size());
+    std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
+                   std::back_insert_iterator(compositionLayerPointers),
+                   [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
+                       return &settings;
+                   });
+    mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers,
                               mGraphicBuffer->getNativeBuffer(), true, std::move(bufferFence),
                               &readyFence);
     int fd = readyFence.release();
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 7e0c33c..9e3cf0e 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -71,6 +71,51 @@
          *   setClientTargetProperty(ClientTargetProperty clientTargetProperty);
          */
          SET_CLIENT_TARGET_PROPERTY = 0x105 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+
+        /**
+         * SET_LAYER_GENERIC_METADATA has this pseudo prototype
+         *
+         *   setLayerGenericMetadata(string key, bool mandatory, vec<uint8_t> value);
+         *
+         * Sets a piece of generic metadata for the given layer. If this
+         * function is called twice with the same key but different values, the
+         * newer value must override the older one. Calling this function with a
+         * 0-length value must reset that key's metadata as if it had not been
+         * set.
+         *
+         * A given piece of metadata may either be mandatory or a hint
+         * (non-mandatory) as indicated by the second parameter. Mandatory
+         * metadata may affect the composition result, which is to say that it
+         * may cause a visible change in the final image. By contrast, hints may
+         * only affect the composition strategy, such as which layers are
+         * composited by the client, but must not cause a visible change in the
+         * final image. The value of the mandatory flag shall match the value
+         * returned from getLayerGenericMetadataKeys for the given key.
+         *
+         * Only keys which have been returned from getLayerGenericMetadataKeys()
+         * shall be accepted. Any other keys must result in an UNSUPPORTED error.
+         *
+         * The value passed into this function shall be the binary
+         * representation of a HIDL type corresponding to the given key. For
+         * example, a key of 'com.example.V1_3.Foo' shall be paired with a
+         * value of type com.example@1.3::Foo, which would be defined in a
+         * vendor HAL extension.
+         *
+         * This function will be encoded in the command buffer in this order:
+         *   1) The key length, stored as a uint32_t
+         *   2) The key itself, padded to a uint32_t boundary if necessary
+         *   3) The mandatory flag, stored as a uint32_t
+         *   4) The value length in bytes, stored as a uint32_t
+         *   5) The value itself, padded to a uint32_t boundary if necessary
+         *
+         * @param key indicates which metadata value should be set on this layer
+         * @param mandatory indicates whether this particular key represents
+         *        mandatory metadata or a hint (non-mandatory metadata), as
+         *        described above
+         * @param value is a binary representation of a HIDL struct
+         *        corresponding to the key as described above
+         */
+        SET_LAYER_GENERIC_METADATA = 0x40e << @2.1::IComposerClient.Command:OPCODE_SHIFT,
     };
 
     /**
@@ -271,4 +316,33 @@
      */
     setContentType(Display display, ContentType type)
         generates (Error error);
+
+    struct LayerGenericMetadataKey {
+        /**
+         * Key names must comply with the requirements specified for
+         * getLayerGenericMetadataKeys below
+         */
+        string name;
+
+        /**
+         * The mandatory flag is defined in the description of
+         * setLayerGenericMetadata above
+         */
+        bool mandatory;
+    };
+
+    /**
+     * Retrieves the set of keys that may be passed into setLayerGenericMetadata
+     *
+     * Key names must meet the following requirements:
+     * - Must be specified in reverse domain name notation
+     * - Must not start with 'com.android' or 'android'
+     * - Must be unique within the returned vector
+     * - Must correspond to a matching HIDL struct type, which defines the
+     *   structure of its values. For example, the key 'com.example.V1-3.Foo'
+     *   should correspond to a value of type com.example@1.3::Foo, which is
+     *   defined in a vendor HAL extension
+     */
+    getLayerGenericMetadataKeys()
+        generates(Error error, vec<LayerGenericMetadataKey> keys);
 };
diff --git a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
index e84779e..eb35e5c 100644
--- a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
+++ b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
@@ -53,6 +53,27 @@
         writeSigned(static_cast<int32_t>(clientTargetProperty.dataspace));
         endCommand();
     }
+
+    void setLayerGenericMetadata(const hidl_string& key, const bool mandatory,
+                                 const hidl_vec<uint8_t>& value) {
+        const size_t commandSize = 3 + sizeToElements(key.size()) + sizeToElements(value.size());
+        if (commandSize > std::numeric_limits<uint16_t>::max()) {
+            LOG_FATAL("Too much generic metadata (%zu elements)", commandSize);
+            return;
+        }
+
+        beginCommand(IComposerClient::Command::SET_LAYER_GENERIC_METADATA,
+                     static_cast<uint16_t>(commandSize));
+        write(key.size());
+        writeBlob(key.size(), reinterpret_cast<const unsigned char*>(key.c_str()));
+        write(mandatory);
+        write(value.size());
+        writeBlob(value.size(), value.data());
+        endCommand();
+    }
+
+  protected:
+    uint32_t sizeToElements(uint32_t size) { return (size + 3) / 4; }
 };
 
 // This class helps parse a command queue.  Note that all sizes/lengths are in
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
index c864ce6..c889069 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
@@ -164,6 +164,14 @@
         return mHal->setContentType(display, contentType);
     }
 
+    Return<void> getLayerGenericMetadataKeys(
+            IComposerClient::getLayerGenericMetadataKeys_cb hidl_cb) override {
+        std::vector<IComposerClient::LayerGenericMetadataKey> keys;
+        Error error = mHal->getLayerGenericMetadataKeys(&keys);
+        hidl_cb(error, keys);
+        return Void();
+    }
+
     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
         auto client = std::make_unique<ComposerClientImpl>(hal);
         return client->init() ? std::move(client) : nullptr;
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
index e0153ce..697d6b8 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerCommandEngine.h
@@ -74,6 +74,43 @@
 
     CommandWriterBase* getWriter() { return static_cast<CommandWriterBase*>(mWriter.get()); }
 
+    bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+        switch (static_cast<IComposerClient::Command>(command)) {
+            case IComposerClient::Command::SET_LAYER_GENERIC_METADATA:
+                return executeSetLayerGenericMetadata(length);
+            default:
+                return BaseType2_3::executeCommand(command, length);
+        }
+    }
+
+    bool executeSetLayerGenericMetadata(uint16_t length) {
+        // We expect at least two buffer lengths and a mandatory flag
+        if (length < 3) {
+            return false;
+        }
+
+        const uint32_t keySize = read();
+        std::string key;
+        key.resize(keySize);
+        readBlob(keySize, key.data());
+
+        const bool mandatory = read();
+
+        const uint32_t valueSize = read();
+        std::vector<uint8_t> value(valueSize);
+        readBlob(valueSize, value.data());
+
+        auto error = mHal->setLayerGenericMetadata(mCurrentDisplay, mCurrentLayer, key, mandatory,
+                                                   value);
+        if (error != Error::NONE) {
+            // The error cast is safe because setLayerGenericMetadata doesn't
+            // return any of the new values added in V2_4::Error
+            mWriter->setError(getCommandLoc(), static_cast<V2_1::Error>(error));
+        }
+
+        return true;
+    }
+
     ComposerHal* mHal;
 };
 
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
index 277055c..58991c1 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
@@ -79,6 +79,10 @@
             uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
             std::vector<uint32_t>* outRequestMasks,
             IComposerClient::ClientTargetProperty* outClientTargetProperty) = 0;
+    virtual Error setLayerGenericMetadata(Display display, Layer layer, const std::string& key,
+                                          bool mandatory, const std::vector<uint8_t>& value) = 0;
+    virtual Error getLayerGenericMetadataKeys(
+            std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
index 616852a..d28e006 100644
--- a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
+++ b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
@@ -245,6 +245,61 @@
         return err;
     }
 
+    Error setLayerGenericMetadata(Display display, Layer layer, const std::string& key,
+                                  bool mandatory, const std::vector<uint8_t>& value) override {
+        if (!mDispatch.setLayerGenericMetadata) {
+            return Error::UNSUPPORTED;
+        }
+
+        if (key.size() > std::numeric_limits<uint32_t>::max()) {
+            return Error::BAD_PARAMETER;
+        }
+
+        if (value.size() > std::numeric_limits<uint32_t>::max()) {
+            return Error::BAD_PARAMETER;
+        }
+
+        int32_t error = mDispatch.setLayerGenericMetadata(
+                mDevice, display, layer, static_cast<uint32_t>(key.size()), key.c_str(), mandatory,
+                static_cast<uint32_t>(value.size()), value.data());
+        return static_cast<Error>(error);
+    }
+
+    Error getLayerGenericMetadataKeys(
+            std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override {
+        if (!mDispatch.getLayerGenericMetadataKey) {
+            return Error::UNSUPPORTED;
+        }
+
+        std::vector<IComposerClient::LayerGenericMetadataKey> keys;
+
+        uint32_t index = 0;
+        uint32_t keyLength = 0;
+        while (true) {
+            mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, nullptr, nullptr);
+            if (keyLength == 0) {
+                break;
+            }
+
+            IComposerClient::LayerGenericMetadataKey key;
+            std::string keyName;
+            keyName.resize(keyLength);
+            mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, keyName.data(),
+                                                 &key.mandatory);
+            key.name = keyName;
+            keys.emplace_back(std::move(key));
+
+            // Only attempt to load the first 100 keys to avoid an infinite loop
+            // if something goes wrong
+            if (++index > 100) {
+                break;
+            }
+        }
+
+        *outKeys = std::move(keys);
+        return Error::NONE;
+    }
+
   protected:
     bool initDispatch() override {
         if (!BaseType2_3::initDispatch()) {
@@ -267,6 +322,11 @@
         this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType);
         this->initOptionalDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY,
                                    &mDispatch.getClientTargetProperty);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_GENERIC_METADATA,
+                                   &mDispatch.setLayerGenericMetadata);
+        this->initOptionalDispatch(HWC2_FUNCTION_GET_LAYER_GENERIC_METADATA_KEY,
+                                   &mDispatch.getLayerGenericMetadataKey);
+
         return true;
     }
 
@@ -319,6 +379,8 @@
         HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes;
         HWC2_PFN_SET_CONTENT_TYPE setContentType;
         HWC2_PFN_GET_CLIENT_TARGET_PROPERTY getClientTargetProperty;
+        HWC2_PFN_SET_LAYER_GENERIC_METADATA setLayerGenericMetadata;
+        HWC2_PFN_GET_LAYER_GENERIC_METADATA_KEY getLayerGenericMetadataKey;
     } mDispatch = {};
 
     hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr;
diff --git a/graphics/composer/2.4/utils/vts/ComposerVts.cpp b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
index 8a9c006..8cdc452 100644
--- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
@@ -129,6 +129,16 @@
     return mClient->setContentType(display, contentType);
 }
 
+Error ComposerClient::getLayerGenericMetadataKeys(
+        std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) {
+    Error error = Error::NONE;
+    mClient->getLayerGenericMetadataKeys([&](const auto tmpError, const auto& tmpKeys) {
+        error = tmpError;
+        *outKeys = tmpKeys;
+    });
+    return error;
+}
+
 }  // namespace vts
 }  // namespace V2_4
 }  // namespace composer
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
index df75a48..3dd8e50 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
@@ -93,6 +93,9 @@
 
     Error setContentType(Display display, IComposerClient::ContentType contentType);
 
+    Error getLayerGenericMetadataKeys(
+            std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys);
+
   private:
     const sp<IComposerClient> mClient;
 };
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 800ff08..f6b46ff 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "graphics_composer_hidl_hal_test@2.4"
 
 #include <algorithm>
+#include <regex>
 #include <thread>
 
 #include <android-base/logging.h>
@@ -625,6 +626,28 @@
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
         android::hardware::PrintInstanceNameToString);
 
+TEST_F(GraphicsComposerHidlCommandTest, getLayerGenericMetadataKeys) {
+    std::vector<IComposerClient::LayerGenericMetadataKey> keys;
+    mComposerClient->getLayerGenericMetadataKeys(&keys);
+
+    std::regex reverseDomainName("^[a-zA-Z-]{2,}(\\.[a-zA-Z0-9-]+)+$");
+    std::unordered_set<std::string> uniqueNames;
+    for (const auto& key : keys) {
+        std::string name(key.name.c_str());
+
+        // Keys must not start with 'android' or 'com.android'
+        ASSERT_FALSE(name.find("android") == 0);
+        ASSERT_FALSE(name.find("com.android") == 0);
+
+        // Keys must be in reverse domain name format
+        ASSERT_TRUE(std::regex_match(name, reverseDomainName));
+
+        // Keys must be unique within this list
+        const auto& [iter, inserted] = uniqueNames.insert(name);
+        ASSERT_TRUE(inserted);
+    }
+}
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_4
diff --git a/health/utils/libhealthloop/utils.cpp b/health/utils/libhealthloop/utils.cpp
index b0d153f..ebfd8d8 100644
--- a/health/utils/libhealthloop/utils.cpp
+++ b/health/utils/libhealthloop/utils.cpp
@@ -40,6 +40,8 @@
             .batteryChargeCounterPath = String8(String8::kEmptyString),
             .batteryFullChargePath = String8(String8::kEmptyString),
             .batteryCycleCountPath = String8(String8::kEmptyString),
+            .batteryCapacityLevelPath = String8(String8::kEmptyString),
+            .batteryChargeTimeToFullNowPath = String8(String8::kEmptyString),
             .energyCounter = NULL,
             .boot_min_cap = 0,
             .screen_on = NULL,
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
new file mode 100644
index 0000000..916a857
--- /dev/null
+++ b/light/aidl/Android.bp
@@ -0,0 +1,18 @@
+aidl_interface {
+    name: "android.hardware.light",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/light/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/light/aidl/android/hardware/light/BrightnessMode.aidl b/light/aidl/android/hardware/light/BrightnessMode.aidl
new file mode 100644
index 0000000..bc29699
--- /dev/null
+++ b/light/aidl/android/hardware/light/BrightnessMode.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package android.hardware.light;
+
+@VintfStability
+enum BrightnessMode {
+    /**
+     * Light brightness is managed by a user setting.
+     */
+    USER = 0,
+
+    /**
+     * Light brightness is managed by a light sensor. This is typically used
+     * to control the display backlight, but not limited to it. HALs and
+     * hardware implementations are free to support sensor for other lights or
+     * none whatsoever.
+     */
+    SENSOR = 1,
+
+    /**
+     * Use a low-persistence mode for display backlights, where the pixel
+     * color transition times are lowered.
+     *
+     * When set, the device driver must switch to a mode optimized for low display
+     * persistence that is intended to be used when the device is being treated as a
+     * head mounted display (HMD). The actual display brightness in this mode is
+     * implementation dependent, and any value set for color in LightState may be
+     * overridden by the HAL implementation.
+     *
+     * For an optimal HMD viewing experience, the display must meet the following
+     * criteria in this mode:
+     * - Gray-to-Gray, White-to-Black, and Black-to-White switching time must be ≤ 3 ms.
+     * - The display must support low-persistence with ≤ 3.5 ms persistence.
+     *   Persistence is defined as the amount of time for which a pixel is
+     *   emitting light for a single frame.
+     * - Any "smart panel" or other frame buffering options that increase display
+     *   latency are disabled.
+     * - Display brightness is set so that the display is still visible to the user
+     *   under normal indoor lighting.
+     * - The display must update at 60 Hz at least, but higher refresh rates are
+     *   recommended for low latency.
+     *
+     */
+    LOW_PERSISTENCE = 2,
+}
diff --git a/light/aidl/android/hardware/light/FlashMode.aidl b/light/aidl/android/hardware/light/FlashMode.aidl
new file mode 100644
index 0000000..00c6b6a
--- /dev/null
+++ b/light/aidl/android/hardware/light/FlashMode.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package android.hardware.light;
+
+@VintfStability
+enum FlashMode {
+    /**
+     * Keep the light steady on or off.
+     */
+    NONE = 0,
+    /**
+     * Flash the light at specified rate, potentially using a software-based
+     * implementation.
+     */
+    TIMED = 1,
+    /**
+     * Flash the light using hardware flashing support. This may or may not
+     * support a user-defined flashing rate or other features.
+     */
+    HARDWARE = 2,
+}
diff --git a/light/aidl/android/hardware/light/HwLight.aidl b/light/aidl/android/hardware/light/HwLight.aidl
new file mode 100644
index 0000000..43fdb4b
--- /dev/null
+++ b/light/aidl/android/hardware/light/HwLight.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.LightType;
+
+/**
+ * A description of a single light. Multiple lights can map to the same physical
+ * LED. Separate physical LEDs are always represented by separate instances.
+ */
+@VintfStability
+parcelable HwLight {
+    /**
+     * Integer ID used for controlling this light
+     */
+    int id;
+
+    /**
+     * For a group of lights of the same logical type, sorting by ordinal should
+     * be give their physical order. No other meaning is carried by it.
+     */
+    int ordinal;
+
+    /**
+     * Logical type use of this light.
+     */
+    LightType type;
+}
diff --git a/light/aidl/android/hardware/light/HwLightState.aidl b/light/aidl/android/hardware/light/HwLightState.aidl
new file mode 100644
index 0000000..24d3250
--- /dev/null
+++ b/light/aidl/android/hardware/light/HwLightState.aidl
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.BrightnessMode;
+import android.hardware.light.FlashMode;
+
+/**
+ * The parameters that can be set for a given light.
+ *
+ * Not all lights must support all parameters. If you
+ * can do something backward-compatible, do it.
+ */
+@VintfStability
+parcelable HwLightState {
+    /**
+     * The color of the LED in ARGB.
+     *
+     * The implementation of this in the HAL and hardware is a best-effort one.
+     *   - If a light can only do red or green and blue is requested, green
+     *     should be shown.
+     *   - If only a brightness ramp is supported, then this formula applies:
+     *      unsigned char brightness = ((77*((color>>16)&0x00ff))
+     *              + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+     *   - If only on and off are supported, 0 is off, anything else is on.
+     *
+     * The high byte should be ignored. Callers should set it to 0xff (which
+     * would correspond to 255 alpha).
+     */
+    int color;
+
+    /**
+     * To flash the light at a given rate, set flashMode to FLASH_TIMED.
+     */
+    FlashMode flashMode;
+
+    /**
+     * flashOnMs should be set to the number of milliseconds to turn the
+     * light on, before it's turned off.
+     */
+    int flashOnMs;
+
+    /**
+     * flashOfMs should be set to the number of milliseconds to turn the
+     * light off, before it's turned back on.
+     */
+    int flashOffMs;
+
+    BrightnessMode brightnessMode;
+}
diff --git a/light/aidl/android/hardware/light/ILights.aidl b/light/aidl/android/hardware/light/ILights.aidl
new file mode 100644
index 0000000..2253f73
--- /dev/null
+++ b/light/aidl/android/hardware/light/ILights.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.HwLightState;
+import android.hardware.light.HwLight;
+
+/**
+ * Allows controlling logical lights/indicators, mapped to LEDs in a
+ * hardware-specific manner by the HAL implementation.
+ */
+@VintfStability
+interface ILights {
+    /**
+     * Set light identified by id to the provided state.
+     *
+     * If control over an invalid light is requested, this method exists with
+     * EX_UNSUPPORTED_OPERATION. Control over supported lights is done on a
+     * device-specific best-effort basis and unsupported sub-features will not
+     * be reported.
+     *
+     * @param id ID of logical light to set as returned by getLights()
+     * @param state describes what the light should look like.
+     */
+    void setLightState(in int id, in HwLightState state);
+
+    /**
+     * Discover what lights are supported by the HAL implementation.
+     *
+     * @return List of available lights
+     */
+    HwLight[] getLights();
+}
diff --git a/light/aidl/android/hardware/light/LightType.aidl b/light/aidl/android/hardware/light/LightType.aidl
new file mode 100644
index 0000000..9a7f656
--- /dev/null
+++ b/light/aidl/android/hardware/light/LightType.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package android.hardware.light;
+
+/**
+ * These light IDs correspond to logical lights, not physical.
+ * So for example, if your INDICATOR light is in line with your
+ * BUTTONS, it might make sense to also light the INDICATOR
+ * light to a reasonable color when the BUTTONS are lit.
+ */
+@VintfStability
+enum LightType {
+    BACKLIGHT = 0,
+    KEYBOARD = 1,
+    BUTTONS = 2,
+    BATTERY = 3,
+    NOTIFICATIONS = 4,
+    ATTENTION = 5,
+    BLUETOOTH = 6,
+    WIFI = 7,
+    MICROPHONE = 8,
+}
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
new file mode 100644
index 0000000..ae3f463
--- /dev/null
+++ b/light/aidl/default/Android.bp
@@ -0,0 +1,16 @@
+cc_binary {
+    name: "android.hardware.lights-service.example",
+    relative_install_path: "hw",
+    init_rc: ["lights-default.rc"],
+    vintf_fragments: ["lights-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.light-ndk_platform",
+    ],
+    srcs: [
+        "Lights.cpp",
+        "main.cpp",
+    ],
+}
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
new file mode 100644
index 0000000..74747d5
--- /dev/null
+++ b/light/aidl/default/Lights.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Lights.h"
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace light {
+
+ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
+    LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* /*lights*/) {
+    LOG(INFO) << "Lights reporting supported lights";
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
new file mode 100644
index 0000000..8cba5a1
--- /dev/null
+++ b/light/aidl/default/Lights.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/light/BnLights.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace light {
+
+// Default implementation that reports no supported lights.
+class Lights : public BnLights {
+    ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
+    ndk::ScopedAStatus getLights(std::vector<HwLight>* types) override;
+};
+
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/light/aidl/default/lights-default.rc b/light/aidl/default/lights-default.rc
new file mode 100644
index 0000000..687ec97
--- /dev/null
+++ b/light/aidl/default/lights-default.rc
@@ -0,0 +1,5 @@
+service vendor.light-default /vendor/bin/hw/android.hardware.lights-service.example
+    class hal
+    user nobody
+    group nobody
+    shutdown critical
diff --git a/light/aidl/default/lights-default.xml b/light/aidl/default/lights-default.xml
new file mode 100644
index 0000000..db604d6
--- /dev/null
+++ b/light/aidl/default/lights-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.light</name>
+        <fqname>ILights/default</fqname>
+    </hal>
+</manifest>
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
new file mode 100644
index 0000000..a860bf4
--- /dev/null
+++ b/light/aidl/default/main.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Lights.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::light::Lights;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
+
+    const std::string instance = std::string() + Lights::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reached
+}
diff --git a/light/aidl/vts/functional/Android.bp b/light/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..3dd8cf6
--- /dev/null
+++ b/light/aidl/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "VtsHalLightTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalLightTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+    ],
+    static_libs: [
+        "android.hardware.light-cpp",
+    ],
+    test_suites: [
+        "vts-core",
+    ],
+}
diff --git a/light/aidl/vts/functional/VtsHalLightTargetTest.cpp b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
new file mode 100644
index 0000000..3c26278
--- /dev/null
+++ b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "light_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <android-base/logging.h>
+#include <android/hardware/light/ILights.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+#include <set>
+
+using android::ProcessState;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::light::BrightnessMode;
+using android::hardware::light::FlashMode;
+using android::hardware::light::HwLight;
+using android::hardware::light::HwLightState;
+using android::hardware::light::ILights;
+using android::hardware::light::LightType;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+const std::set<LightType> kAllTypes{android::enum_range<LightType>().begin(),
+                                    android::enum_range<LightType>().end()};
+
+class LightsAidl : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        lights = android::waitForDeclaredService<ILights>(String16(GetParam().c_str()));
+        ASSERT_NE(lights, nullptr);
+        ASSERT_TRUE(lights->getLights(&supportedLights).isOk());
+    }
+
+    sp<ILights> lights;
+    std::vector<HwLight> supportedLights;
+
+    virtual void TearDown() override {
+        for (const HwLight& light : supportedLights) {
+            HwLightState off;
+            off.color = 0x00000000;
+            off.flashMode = FlashMode::NONE;
+            off.brightnessMode = BrightnessMode::USER;
+            EXPECT_TRUE(lights->setLightState(light.id, off).isOk());
+        }
+
+        // must leave the device in a useable condition
+        for (const HwLight& light : supportedLights) {
+            if (light.type == LightType::BACKLIGHT) {
+                HwLightState backlightOn;
+                backlightOn.color = 0xFFFFFFFF;
+                backlightOn.flashMode = FlashMode::TIMED;
+                backlightOn.brightnessMode = BrightnessMode::USER;
+                EXPECT_TRUE(lights->setLightState(light.id, backlightOn).isOk());
+            }
+        }
+    }
+};
+
+/**
+ * Ensure all reported lights actually work.
+ */
+TEST_P(LightsAidl, TestSupported) {
+    HwLightState whiteFlashing;
+    whiteFlashing.color = 0xFFFFFFFF;
+    whiteFlashing.flashMode = FlashMode::TIMED;
+    whiteFlashing.flashOnMs = 100;
+    whiteFlashing.flashOffMs = 50;
+    whiteFlashing.brightnessMode = BrightnessMode::USER;
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(lights->setLightState(light.id, whiteFlashing).isOk());
+    }
+}
+
+/**
+ * Ensure all reported lights have one of the supported types.
+ */
+TEST_P(LightsAidl, TestSupportedLightTypes) {
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(kAllTypes.find(light.type) != kAllTypes.end());
+    }
+}
+
+/**
+ * Ensure all lights have a unique id.
+ */
+TEST_P(LightsAidl, TestUniqueIds) {
+    std::set<int> ids;
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(ids.find(light.id) == ids.end());
+        ids.insert(light.id);
+    }
+}
+
+/**
+ * Ensure all lights have a unique ordinal for a given type.
+ */
+TEST_P(LightsAidl, TestUniqueOrdinalsForType) {
+    std::map<int, std::set<int>> ordinalsByType;
+    for (const HwLight& light : supportedLights) {
+        auto& ordinals = ordinalsByType[(int)light.type];
+        EXPECT_TRUE(ordinals.find(light.ordinal) == ordinals.end());
+        ordinals.insert(light.ordinal);
+    }
+}
+
+/**
+ * Ensure EX_UNSUPPORTED_OPERATION is returned if LOW_PERSISTENCE is not supported.
+ */
+TEST_P(LightsAidl, TestLowPersistence) {
+    HwLightState lowPersistence;
+    lowPersistence.color = 0xFF123456;
+    lowPersistence.flashMode = FlashMode::TIMED;
+    lowPersistence.flashOnMs = 100;
+    lowPersistence.flashOffMs = 50;
+    lowPersistence.brightnessMode = BrightnessMode::LOW_PERSISTENCE;
+    for (const HwLight& light : supportedLights) {
+        Status status = lights->setLightState(light.id, lowPersistence);
+        EXPECT_TRUE(status.isOk() || Status::EX_UNSUPPORTED_OPERATION == status.exceptionCode());
+    }
+}
+
+/**
+ * Ensure EX_UNSUPPORTED_OPERATION is returns for an invalid light id.
+ */
+TEST_P(LightsAidl, TestInvalidLightIdUnsupported) {
+    int maxId = INT_MIN;
+    for (const HwLight& light : supportedLights) {
+        maxId = std::max(maxId, light.id);
+    }
+
+    Status status = lights->setLightState(maxId + 1, HwLightState());
+    EXPECT_TRUE(status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION);
+}
+
+INSTANTIATE_TEST_SUITE_P(Lights, LightsAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ILights::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/light/utils/Android.bp b/light/utils/Android.bp
index 4c287e4..e901129 100644
--- a/light/utils/Android.bp
+++ b/light/utils/Android.bp
@@ -23,7 +23,11 @@
     shared_libs: [
         "android.hardware.light@2.0",
         "libbase",
+        "libbinder",
         "libhidlbase",
         "libutils",
     ],
+    static_libs: [
+        "android.hardware.light-cpp",
+    ],
 }
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index b834132..b9b6489 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -19,34 +19,23 @@
 
 #include <android-base/logging.h>
 #include <android/hardware/light/2.0/ILight.h>
+#include <android/hardware/light/ILights.h>
+#include <binder/IServiceManager.h>
+
+using android::sp;
+using android::waitForVintfService;
+using android::binder::Status;
+using android::hardware::hidl_vec;
+
+namespace V2_0 = android::hardware::light::V2_0;
+namespace aidl = android::hardware::light;
 
 void error(const std::string& msg) {
     LOG(ERROR) << msg;
     std::cerr << msg << std::endl;
 }
 
-int main(int argc, char* argv[]) {
-    using ::android::hardware::hidl_vec;
-    using ::android::hardware::light::V2_0::Brightness;
-    using ::android::hardware::light::V2_0::Flash;
-    using ::android::hardware::light::V2_0::ILight;
-    using ::android::hardware::light::V2_0::LightState;
-    using ::android::hardware::light::V2_0::Status;
-    using ::android::hardware::light::V2_0::Type;
-    using ::android::sp;
-
-    sp<ILight> service = ILight::getService();
-    if (service == nullptr) {
-        error("Could not retrieve light service.");
-        return -1;
-    }
-
-    static LightState off = {
-            .color = 0u,
-            .flashMode = Flash::NONE,
-            .brightnessMode = Brightness::USER,
-    };
-
+int parseArgs(int argc, char* argv[], unsigned int* color) {
     if (argc > 2) {
         error("Usage: blank_screen [color]");
         return -1;
@@ -54,25 +43,78 @@
 
     if (argc > 1) {
         char* col_ptr;
-        unsigned int col_new;
 
-        col_new = strtoul(argv[1], &col_ptr, 0);
+        *color = strtoul(argv[1], &col_ptr, 0);
         if (*col_ptr != '\0') {
             error("Failed to convert " + std::string(argv[1]) + " to number");
             return -1;
         }
-        off.color = col_new;
+
+        return 0;
     }
 
-    service->getSupportedTypes([&](const hidl_vec<Type>& types) {
-        for (Type type : types) {
-            Status ret = service->setLight(type, off);
-            if (ret != Status::SUCCESS) {
-                error("Failed to shut off screen for type " +
+    *color = 0u;
+    return 0;
+}
+
+void setToColorAidl(sp<aidl::ILights> hal, unsigned int color) {
+    static aidl::HwLightState off;
+    off.color = color;
+    off.flashMode = aidl::FlashMode::NONE;
+    off.brightnessMode = aidl::BrightnessMode::USER;
+
+    std::vector<aidl::HwLight> lights;
+    Status status = hal->getLights(&lights);
+    if (!status.isOk()) {
+        error("Failed to list lights");
+        return;
+    }
+
+    for (auto light : lights) {
+        Status setStatus = hal->setLightState(light.id, off);
+        if (!setStatus.isOk()) {
+            error("Failed to shut off light id " + std::to_string(light.id));
+        }
+    }
+}
+
+void setToColorHidl(sp<V2_0::ILight> hal, unsigned int color) {
+    static V2_0::LightState off = {
+            .color = color,
+            .flashMode = V2_0::Flash::NONE,
+            .brightnessMode = V2_0::Brightness::USER,
+    };
+
+    hal->getSupportedTypes([&](const hidl_vec<V2_0::Type>& types) {
+        for (auto type : types) {
+            V2_0::Status ret = hal->setLight(type, off);
+            if (ret != V2_0::Status::SUCCESS) {
+                error("Failed to shut off light for type " +
                       std::to_string(static_cast<int>(type)));
             }
         }
     });
+}
 
-    return 0;
+int main(int argc, char* argv[]) {
+    unsigned int inputColor;
+    int result = parseArgs(argc, argv, &inputColor);
+    if (result != 0) {
+        return result;
+    }
+
+    auto aidlHal = waitForVintfService<aidl::ILights>();
+    if (aidlHal != nullptr) {
+        setToColorAidl(aidlHal, inputColor);
+        return 0;
+    }
+
+    sp<V2_0::ILight> hidlHal = V2_0::ILight::getService();
+    if (hidlHal != nullptr) {
+        setToColorHidl(hidlHal, inputColor);
+        return 0;
+    }
+
+    error("Could not retrieve light service.");
+    return -1;
 }
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index 56011e2..7b02cc5 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -11,6 +11,7 @@
         "IBuffer.hal",
         "IDevice.hal",
         "IExecutionCallback.hal",
+        "IFencedExecutionCallback.hal",
         "IPreparedModel.hal",
         "IPreparedModelCallback.hal",
     ],
diff --git a/neuralnetworks/1.3/IFencedExecutionCallback.hal b/neuralnetworks/1.3/IFencedExecutionCallback.hal
new file mode 100644
index 0000000..39076b9
--- /dev/null
+++ b/neuralnetworks/1.3/IFencedExecutionCallback.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package android.hardware.neuralnetworks@1.3;
+
+import @1.2::Timing;
+import ErrorStatus;
+
+/**
+ * IFencedExecutionCallback can be used to query the error status result
+ * and duration information from an IPreparedModel::executeFenced call.
+ */
+interface IFencedExecutionCallback {
+
+    /**
+     * The getExecutionInfo method is used by the clients to query error status
+     * result and duration information. The method must only be called after the actual
+     * evaluation has finished or resulted in an runtime error, as indicated by the status
+     * of the sync fence returned by the IPreparedModel::executeFenced call, otherwise
+     * GENERAL_FAILURE must be returned.
+     *
+     * @return status Error status returned from the asynchronously dispatched execution
+     *                must be:
+     *                - NONE if the asynchronous execution was successful
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                  unspecified error
+     * @return timing Duration of execution. Unless MeasureTiming::YES was passed when
+     *                launching the execution and status is NONE, all times must
+     *                be reported as UINT64_MAX. A driver may choose to report
+     *                any time as UINT64_MAX, indicating that particular measurement is
+     *                not available.
+     */
+    getExecutionInfo() generates (ErrorStatus status, Timing timing);
+};
diff --git a/neuralnetworks/1.3/IPreparedModel.hal b/neuralnetworks/1.3/IPreparedModel.hal
index bce6ee2..f84bcf4 100644
--- a/neuralnetworks/1.3/IPreparedModel.hal
+++ b/neuralnetworks/1.3/IPreparedModel.hal
@@ -24,6 +24,7 @@
 import OptionalTimePoint;
 import Request;
 import IExecutionCallback;
+import IFencedExecutionCallback;
 
 /**
  * IPreparedModel describes a model that has been prepared for execution and
@@ -91,7 +92,8 @@
      *                 execution cannot be finished by the deadline, the
      *                 execution must be aborted.
      * @param callback A callback object used to return the error status of
-     *                 the execution. The callback object's notify function must
+     *                 the execution, shape information of model output operands, and
+     *                 duration of execution. The callback object's notify function must
      *                 be called exactly once, even if the execution was
      *                 unsuccessful.
      * @return status Error status of the call, must be:
@@ -187,4 +189,57 @@
                              OptionalTimePoint deadline)
                   generates (ErrorStatus status, vec<OutputShape> outputShapes,
                              Timing timing);
+
+    /**
+     * Launch a fenced asynchronous execution on a prepared model.
+     *
+     * The execution is performed asynchronously with respect to the caller.
+     * executeFenced must fully validate the request, and only accept one that is
+     * guaranteed to be completed, unless a hardware failure or kernel panic happens on the device.
+     * If there is an error during validation, executeFenced must immediately return with
+     * the corresponding ErrorStatus. If the request is valid and there is no error launching,
+     * executeFenced must dispatch an asynchronous task to perform the execution in the
+     * background, and immediately return with ErrorStatus::NONE, a sync_fence that will be
+     * signaled once the execution is completed, and a callback that can be used by the client
+     * to query the duration and runtime error status. If the task has finished
+     * before the call returns, empty handle may be returned for the sync fence. If the
+     * asynchronous task fails to launch, executeFenced must immediately return with
+     * ErrorStatus::GENERAL_FAILURE, and empty handle for the sync fence and nullptr
+     * for callback. The execution must wait for all the sync fences (if any) in wait_for to be
+     * signaled before starting the actual execution.
+     *
+     * If any of sync fences in wait_for changes to error status after the executeFenced
+     * call succeeds, the driver must immediately set the returned sync fence to error status.
+     *
+     * When the asynchronous task has finished its execution, it must
+     * immediately signal the sync_fence created when dispatching. After
+     * the sync_fence is signaled, the task must not modify the content of
+     * any data object referenced by 'request' (described by the
+     * {@link @1.0::DataLocation} of a {@link @1.0::RequestArgument}).
+     *
+     * Any number of calls to the executeFenced, execute* and executeSynchronously*
+     * functions, in any combination, may be made concurrently, even on the same
+     * IPreparedModel object.
+     *
+     * @param request The input and output information on which the prepared
+     *                model is to be executed.
+     * @param waitFor A vector of sync fence file descriptors.
+     *                Execution must not start until all sync fences have been signaled.
+     * @param measure Specifies whether or not to measure duration of the execution.
+     *                The duration runs from the time the driver sees the call
+     *                to the executeFenced function to the time sync_fence is triggered.
+     * @return status Error status of the call, must be:
+     *                - NONE if task is successfully launched
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - INVALID_ARGUMENT if one of the input arguments is invalid, including
+     *                                   fences in error states.
+     * @return syncFence The sync fence that will be triggered when the task is completed.
+     *                   The sync fence will be set to error if a critical error,
+     *                   e.g. hardware failure or kernel panic, occurs when doing execution.
+     * @return callback The IFencedExecutionCallback can be used to query information like duration
+     *                  and error status when the execution is completed.
+     */
+    executeFenced(Request request, vec<handle> waitFor, MeasureTiming measure)
+        generates (ErrorStatus status, handle syncFence, IFencedExecutionCallback callback);
 };
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index ce2d3a9..8e7e9b9 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -65,6 +65,7 @@
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
         "libneuralnetworks_utils",
+        "libsync",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index cba1f77..b811149 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -29,11 +29,13 @@
 #include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.2/types.h>
 #include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.3/types.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
+#include <android/sync.h>
 #include <gtest/gtest.h>
 #include <hidlmemory/mapping.h>
 
@@ -70,7 +72,7 @@
 
 namespace {
 
-enum class Executor { ASYNC, SYNC, BURST };
+enum class Executor { ASYNC, SYNC, BURST, FENCED };
 
 enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
 
@@ -562,6 +564,43 @@
 
             break;
         }
+        case Executor::FENCED: {
+            SCOPED_TRACE("fenced");
+            ErrorStatus result;
+            hidl_handle sync_fence_handle;
+            sp<IFencedExecutionCallback> fenced_callback;
+            Return<void> ret = preparedModel->executeFenced(
+                    request, {}, testConfig.measureTiming,
+                    [&result, &sync_fence_handle, &fenced_callback](
+                            ErrorStatus error, const hidl_handle& handle,
+                            const sp<IFencedExecutionCallback>& callback) {
+                        result = error;
+                        sync_fence_handle = handle;
+                        fenced_callback = callback;
+                    });
+            ASSERT_TRUE(ret.isOk());
+            if (result != ErrorStatus::NONE) {
+                ASSERT_EQ(sync_fence_handle.getNativeHandle(), nullptr);
+                ASSERT_EQ(fenced_callback, nullptr);
+                executionStatus = ErrorStatus::GENERAL_FAILURE;
+            } else if (sync_fence_handle.getNativeHandle()) {
+                constexpr int kInfiniteTimeout = -1;
+                int sync_fd = sync_fence_handle.getNativeHandle()->data[0];
+                ASSERT_GT(sync_fd, 0);
+                int r = sync_wait(sync_fd, kInfiniteTimeout);
+                ASSERT_GE(r, 0);
+            }
+            if (result == ErrorStatus::NONE) {
+                ASSERT_NE(fenced_callback, nullptr);
+                Return<void> ret = fenced_callback->getExecutionInfo(
+                        [&executionStatus, &timing](ErrorStatus error, Timing t) {
+                            executionStatus = error;
+                            timing = t;
+                        });
+                ASSERT_TRUE(ret.isOk());
+            }
+            break;
+        }
     }
 
     if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
@@ -635,7 +674,7 @@
         case TestKind::GENERAL: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
-            executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+            executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, Executor::FENCED};
         } break;
         case TestKind::DYNAMIC_SHAPE: {
             outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
@@ -671,7 +710,8 @@
                                    const TestModel& coupledModel) {
     const std::vector<OutputType> outputTypesList = {OutputType::FULLY_SPECIFIED};
     const std::vector<MeasureTiming> measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
-    const std::vector<Executor> executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+    const std::vector<Executor> executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST,
+                                                Executor::FENCED};
 
     for (const OutputType outputType : outputTypesList) {
         for (const MeasureTiming measureTiming : measureTimingList) {
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index be4112a..1ddd09c 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -16,7 +16,9 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
 #include <chrono>
+
 #include "1.0/Utils.h"
 #include "1.3/Callbacks.h"
 #include "ExecutionBurstController.h"
@@ -136,6 +138,22 @@
             burst->freeMemory(keys.front());
         }
     }
+
+    // dispatch
+    {
+        SCOPED_TRACE(message + " [executeFenced]");
+        Return<void> ret = preparedModel->executeFenced(
+                request, {}, MeasureTiming::NO,
+                [](ErrorStatus error, const hidl_handle& handle,
+                   const sp<IFencedExecutionCallback>& callback) {
+                    if (error != ErrorStatus::DEVICE_UNAVAILABLE) {
+                        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                    }
+                    ASSERT_EQ(handle.getNativeHandle(), nullptr);
+                    ASSERT_EQ(callback, nullptr);
+                });
+        ASSERT_TRUE(ret.isOk());
+    }
 }
 
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 93c8f13..28cc8ff 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -133,6 +133,35 @@
 // Forward declaration from ValidateBurst.cpp
 void validateBurst(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
 
+// Validate sync_fence handles for dispatch with valid input
+void validateExecuteFenced(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    SCOPED_TRACE("Expecting request to fail [executeFenced]");
+    Return<void> ret_null =
+            preparedModel->executeFenced(request, {hidl_handle(nullptr)}, V1_2::MeasureTiming::NO,
+                                         [](ErrorStatus error, const hidl_handle& handle,
+                                            const sp<IFencedExecutionCallback>& callback) {
+                                             ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                                             ASSERT_EQ(handle.getNativeHandle(), nullptr);
+                                             ASSERT_EQ(callback, nullptr);
+                                         });
+    ASSERT_TRUE(ret_null.isOk());
+
+    native_handle_t* nativeHandle = native_handle_create(1, 0);
+    ASSERT_NE(nullptr, nativeHandle);
+    nativeHandle->data[0] = -1;
+    hidl_handle hidlHandle;
+    hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
+    Return<void> ret_invalid =
+            preparedModel->executeFenced(request, {hidlHandle}, V1_2::MeasureTiming::NO,
+                                         [](ErrorStatus error, const hidl_handle& handle,
+                                            const sp<IFencedExecutionCallback>& callback) {
+                                             ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                                             ASSERT_EQ(handle.getNativeHandle(), nullptr);
+                                             ASSERT_EQ(callback, nullptr);
+                                         });
+    ASSERT_TRUE(ret_invalid.isOk());
+}
+
 void validateEverything(const sp<IDevice>& device, const Model& model, const Request& request,
                         std::pair<bool, bool> supportsDeadlines) {
     const auto [prepareModelDeadlineSupported, executionDeadlineSupported] = supportsDeadlines;
@@ -144,6 +173,7 @@
     if (preparedModel == nullptr) return;
 
     validateRequest(preparedModel, request, executionDeadlineSupported);
+    validateExecuteFenced(preparedModel, request);
 
     // TODO(butlermichael): Check if we need to test burst in V1_3 if the interface remains V1_2.
     ASSERT_TRUE(nn::compliantWithV1_0(request));
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 5482aca..c0fa8af 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -600,6 +600,9 @@
 
     /** Information about any closed subscriber group ID for this cell */
     OptionalCsgInfo optionalCsgInfo;
+
+    /** Bands used by the cell. */
+    vec<EutranBands> bands;
 };
 
 /**
@@ -615,8 +618,8 @@
     /** Additional PLMN-IDs beyond the primary PLMN broadcast for this cell */
     vec<string> additionalPlmns;
 
-    /** Band used by the cell */
-    NgranBands band;
+    /** Bands used by the cell. */
+    vec<NgranBands> bands;
 };
 
 struct CellInfoGsm {
diff --git a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
index f69cf87..cd8cc3e 100644
--- a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
+++ b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
@@ -26,6 +26,9 @@
 using android::String16;
 using android::hardware::rebootescrow::IRebootEscrow;
 
+#define SKIP_UNSUPPORTED \
+    if (rebootescrow == nullptr) GTEST_SKIP() << "Not supported on this device"
+
 /**
  * This tests that the key can be written, read, and removed. It does not test
  * that the key survives a reboot. That needs a host-based test.
@@ -36,7 +39,6 @@
   public:
     virtual void SetUp() override {
         rebootescrow = android::waitForDeclaredService<IRebootEscrow>(String16(GetParam().c_str()));
-        ASSERT_NE(rebootescrow, nullptr);
     }
 
     sp<IRebootEscrow> rebootescrow;
@@ -59,6 +61,8 @@
 };
 
 TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_Success) {
+    SKIP_UNSUPPORTED;
+
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
 
     std::vector<uint8_t> actualKey;
@@ -67,6 +71,8 @@
 }
 
 TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_SecondRetrieveSucceeds) {
+    SKIP_UNSUPPORTED;
+
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
 
     std::vector<uint8_t> actualKey;
@@ -78,6 +84,8 @@
 }
 
 TEST_P(RebootEscrowAidlTest, StoreTwiceOverwrites_Success) {
+    SKIP_UNSUPPORTED;
+
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
     ASSERT_TRUE(rebootescrow->storeKey(KEY_2).isOk());
 
@@ -87,6 +95,8 @@
 }
 
 TEST_P(RebootEscrowAidlTest, StoreEmpty_AfterGetEmptyKey_Success) {
+    SKIP_UNSUPPORTED;
+
     rebootescrow->storeKey(KEY_1);
     rebootescrow->storeKey(EMPTY_KEY);
 
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 7d6b990..3637708 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -30,5 +30,10 @@
     shared_libs: [
         "libbinder",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+
+    require_root: true,
 }
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 4e7dcc3..820c58c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -31,8 +31,11 @@
 #include <android/hardware/tv/tuner/1.0/types.h>
 #include <binder/MemoryDealer.h>
 #include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
 #include <hidl/Status.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <utils/Condition.h>
@@ -633,23 +636,10 @@
     android::Mutex::Autolock autoLock(mRecordThreadLock);
 }
 
-// Test environment for Tuner HIDL HAL.
-class TunerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-  public:
-    // get the test environment singleton
-    static TunerHidlEnvironment* Instance() {
-        static TunerHidlEnvironment* instance = new TunerHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<ITuner>(); }
-};
-
-class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class TunerHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
-        mService = ::testing::VtsHalHidlTargetTestBase::getService<ITuner>(
-                TunerHidlEnvironment::Instance()->getServiceName<ITuner>());
+        mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
     }
 
@@ -1242,7 +1232,7 @@
 /*
  * API STATUS TESTS
  */
-TEST_F(TunerHidlTest, CreateFrontend) {
+TEST_P(TunerHidlTest, CreateFrontend) {
     Result status;
     hidl_vec<FrontendId> feIds;
 
@@ -1262,7 +1252,7 @@
     }
 }
 
-TEST_F(TunerHidlTest, TuneFrontend) {
+TEST_P(TunerHidlTest, TuneFrontend) {
     Result status;
     hidl_vec<FrontendId> feIds;
 
@@ -1282,7 +1272,7 @@
     }
 }
 
-TEST_F(TunerHidlTest, StopTuneFrontend) {
+TEST_P(TunerHidlTest, StopTuneFrontend) {
     Result status;
     hidl_vec<FrontendId> feIds;
 
@@ -1302,7 +1292,7 @@
     }
 }
 
-TEST_F(TunerHidlTest, CloseFrontend) {
+TEST_P(TunerHidlTest, CloseFrontend) {
     Result status;
     hidl_vec<FrontendId> feIds;
 
@@ -1322,7 +1312,7 @@
     }
 }
 
-TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
+TEST_P(TunerHidlTest, CreateDemuxWithFrontend) {
     Result status;
     hidl_vec<FrontendId> feIds;
 
@@ -1349,22 +1339,22 @@
     }
 }
 
-TEST_F(TunerHidlTest, CreateDemux) {
+TEST_P(TunerHidlTest, CreateDemux) {
     description("Create Demux");
     ASSERT_TRUE(createDemux());
 }
 
-TEST_F(TunerHidlTest, CloseDemux) {
+TEST_P(TunerHidlTest, CloseDemux) {
     description("Close Demux");
     ASSERT_TRUE(closeDemux());
 }
 
-TEST_F(TunerHidlTest, CreateDescrambler) {
+TEST_P(TunerHidlTest, CreateDescrambler) {
     description("Create Descrambler");
     ASSERT_TRUE(createDescrambler());
 }
 
-TEST_F(TunerHidlTest, CloseDescrambler) {
+TEST_P(TunerHidlTest, CloseDescrambler) {
     description("Close Descrambler");
     ASSERT_TRUE(closeDescrambler());
 }
@@ -1374,7 +1364,7 @@
  *
  * TODO: re-enable the tests after finalizing the testing stream.
  */
-/*TEST_F(TunerHidlTest, PlaybackDataFlowWithSectionFilterTest) {
+/*TEST_P(TunerHidlTest, PlaybackDataFlowWithSectionFilterTest) {
     description("Feed ts data from playback and configure pes filter to get output");
 
     // todo modulize the filter conf parser
@@ -1417,7 +1407,7 @@
     ASSERT_TRUE(playbackDataFlowTest(filterConf, playbackConf, goldenOutputFiles));
 }
 
-TEST_F(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
+TEST_P(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
     description("Feed ts data from frontend and test with PES filter");
 
     // todo modulize the filter conf parser
@@ -1447,7 +1437,7 @@
     ASSERT_TRUE(broadcastDataFlowTest(filterConf, goldenOutputFiles));
 }
 
-TEST_F(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
+TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
     description("Feed ts data from frontend to recording and test with ts record filter");
 
     // todo modulize the filter conf parser
@@ -1487,11 +1477,7 @@
 
 }  // namespace
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(TunerHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    TunerHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index b9a80ec..0fdfa5d 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -49,4 +49,9 @@
      * A haptic effect that simulates quick downwards movement with gravity.
      */
     QUICK_FALL,
+    /**
+     * This very short effect should produce a light crisp sensation intended
+     * to be used repetitively for dynamic feedback.
+     */
+    LIGHT_TICK,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index f553664..06a8bf5 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -158,12 +158,31 @@
     int getCompositionSizeMax();
 
     /**
+     * List of supported effect primitive.
+     *
+     * Return the effect primitives which are supported by the compose API.
+     * Implementations are expected to support all primitives of the interface
+     * version that they implement.
+     */
+    CompositePrimitive[] getSupportedPrimitives();
+
+    /**
+     * Retrieve effect primitive's duration in milliseconds.
+     *
+     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
+     *
+     * @return Best effort estimation of effect primitive's duration.
+     * @param primitive Effect primitive being queried.
+     */
+    int getPrimitiveDuration(CompositePrimitive primitive);
+
+    /**
      * Fire off a string of effect primitives, combined to perform richer effects.
      *
      * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
      *
      * Doing this operation while the vibrator is already on is undefined behavior. Clients should
-     * explicitly call off.
+     * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
      *
      * @param composite Array of composition parameters.
      */
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index cedd9cb..0d7131a 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -113,6 +113,26 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>* supported) {
+    *supported = {
+            CompositePrimitive::NOOP,       CompositePrimitive::CLICK,
+            CompositePrimitive::THUD,       CompositePrimitive::SPIN,
+            CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
+            CompositePrimitive::QUICK_FALL, CompositePrimitive::LIGHT_TICK,
+    };
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
+                                                  int32_t* durationMs) {
+    if (primitive != CompositePrimitive::NOOP) {
+        *durationMs = 100;
+    } else {
+        *durationMs = 0;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composite,
                                      const std::shared_ptr<IVibratorCallback>& callback) {
     if (composite.size() > kComposeSizeMax) {
@@ -127,7 +147,7 @@
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
         if (e.primitive < CompositePrimitive::NOOP ||
-            e.primitive > CompositePrimitive::QUICK_FALL) {
+            e.primitive > CompositePrimitive::LIGHT_TICK) {
             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
         }
     }
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 0eb957d..c3f3616 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -36,6 +36,9 @@
     ndk::ScopedAStatus setExternalControl(bool enabled) override;
     ndk::ScopedAStatus getCompositionDelayMax(int32_t* maxDelayMs);
     ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
+    ndk::ScopedAStatus getSupportedPrimitives(std::vector<CompositePrimitive>* supported) override;
+    ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive,
+                                            int32_t* durationMs) override;
     ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
                                const std::shared_ptr<IVibratorCallback>& callback) override;
     ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) override;
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index f197763..411fe7a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -261,6 +261,29 @@
     }
 }
 
+TEST_P(VibratorAidl, GetSupportedPrimitives) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        std::vector<CompositePrimitive> supported;
+
+        EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
+
+        std::sort(supported.begin(), supported.end());
+
+        EXPECT_EQ(kCompositePrimitives, supported);
+    }
+}
+
+TEST_P(VibratorAidl, GetPrimitiveDuration) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        int32_t duration;
+
+        for (auto primitive : kCompositePrimitives) {
+            EXPECT_EQ(Status::EX_NONE,
+                      vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
+        }
+    }
+}
+
 TEST_P(VibratorAidl, ComposeValidPrimitives) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         int32_t maxDelay, maxSize;
@@ -357,6 +380,30 @@
     }
 }
 
+TEST_P(VibratorAidl, ComposeCallback) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        std::promise<void> completionPromise;
+        std::future<void> completionFuture{completionPromise.get_future()};
+        sp<CompletionCallback> callback =
+                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+        CompositePrimitive primitive = CompositePrimitive::CLICK;
+        CompositeEffect effect;
+        std::vector<CompositeEffect> composite;
+        int32_t duration;
+
+        effect.delayMs = 0;
+        effect.primitive = primitive;
+        effect.scale = 1.0f;
+        composite.emplace_back(effect);
+
+        EXPECT_EQ(Status::EX_NONE,
+                  vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
+        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode());
+        EXPECT_EQ(completionFuture.wait_for(std::chrono::milliseconds(duration * 2)),
+                  std::future_status::ready);
+    }
+}
+
 TEST_P(VibratorAidl, AlwaysOn) {
     if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
         std::vector<Effect> supported;