Merge "Document unspecified dimensions." into pi-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 00d0aa5..531e44e 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -64,3 +64,5 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/android.hardware.tests*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-sp/android.hardware.graphics.allocator*)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.0.policy)
diff --git a/audio/4.0/types.hal b/audio/4.0/types.hal
index 7b2035b..6b46b10 100644
--- a/audio/4.0/types.hal
+++ b/audio/4.0/types.hal
@@ -184,9 +184,9 @@
  * Simple processing as constant gain adjustment must be DIRECT.
  */
 enum AudioMicrophoneChannelMapping : uint32_t {
-    UNUSED      = 0, /** Channel not used */
-    DIRECT      = 1, /** Channel used and signal not processed */
-    PROCESSED   = 2, /** Channel used and signal has some process */
+    UNUSED      = 0, /* Channel not used */
+    DIRECT      = 1, /* Channel used and signal not processed */
+    PROCESSED   = 2, /* Channel used and signal has some process */
 };
 
 /**
diff --git a/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
index a76770d..8217b94 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
@@ -9,3 +9,5 @@
     # and its .rc file has an "onrestart restart audio-hal" rule, thus
     # an additional auto-restart from the init process isn't needed.
     oneshot
+    interface android.hardware.audio@4.0::IDevicesFactory default
+    interface android.hardware.audio@2.0::IDevicesFactory default
diff --git a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
index 05239ac..abc2ff5 100644
--- a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
+++ b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
@@ -41,6 +41,7 @@
     inline void PrintTo(const T& val, ::std::ostream* os) { *os << toString(val); }
 
 namespace AUDIO_HAL_VERSION {
+DEFINE_GTEST_PRINT_TO(IPrimaryDevice::TtyMode)
 DEFINE_GTEST_PRINT_TO(Result)
 }  // namespace AUDIO_HAL_VERSION
 
diff --git a/audio/core/2.0/vts/functional/Android.bp b/audio/core/2.0/vts/functional/Android.bp
index f3b2ca7..d1ddaff 100644
--- a/audio/core/2.0/vts/functional/Android.bp
+++ b/audio/core/2.0/vts/functional/Android.bp
@@ -25,9 +25,8 @@
         "android.hardware.audio.common.test.utility",
         "android.hardware.audio@2.0",
         "android.hardware.audio.common@2.0",
-        "libxml2",
-    ],
-    shared_libs: [
         "libicuuc",
+        "libicuuc_stubdata",
+        "libxml2",
     ],
 }
diff --git a/audio/core/4.0/vts/functional/Android.bp b/audio/core/4.0/vts/functional/Android.bp
index dde3e7b..22c5493 100644
--- a/audio/core/4.0/vts/functional/Android.bp
+++ b/audio/core/4.0/vts/functional/Android.bp
@@ -25,10 +25,9 @@
         "android.hardware.audio.common.test.utility",
         "android.hardware.audio@4.0",
         "android.hardware.audio.common@4.0",
-        "libxml2",
-    ],
-    shared_libs: [
         "libicuuc",
+        "libicuuc_stubdata",
+        "libxml2",
     ],
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 0bf32b5..c764ea6 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -22,6 +22,7 @@
 #include <cstdio>
 #include <initializer_list>
 #include <limits>
+#include <list>
 #include <string>
 #include <vector>
 
@@ -51,6 +52,7 @@
 using std::string;
 using std::to_string;
 using std::vector;
+using std::list;
 
 using ::android::sp;
 using ::android::hardware::Return;
@@ -104,6 +106,7 @@
 static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
 static auto okOrNotSupportedOrInvalidArgs = {Result::OK, Result::NOT_SUPPORTED,
                                              Result::INVALID_ARGUMENTS};
+static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
 
 class AudioHidlTestEnvironment : public ::Environment {
    public:
@@ -212,53 +215,59 @@
 template <class Property>
 class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
    protected:
-    /** Test a property getter and setter. */
-    template <class Getter, class Setter>
-    void testAccessors(const string& propertyName, const vector<Property>& valuesToTest,
-                       Setter setter, Getter getter, const vector<Property>& invalidValues = {}) {
-        Property initialValue;  // Save initial value to restore it at the end
-                                // of the test
-        ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
-        ASSERT_OK(res);
+    enum Optionality { REQUIRED, OPTIONAL };
+    struct Initial {  // Initial property value
+        Initial(Property value, Optionality check = REQUIRED) : value(value), check(check) {}
+        Property value;
+        Optionality check;  // If this initial value should be checked
+    };
+    /** Test a property getter and setter.
+     *  The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
+     */
+    template <Optionality optionality = REQUIRED, class Getter, class Setter>
+    void testAccessors(const string& propertyName, const Initial expectedInitial,
+                       list<Property> valuesToTest, Setter setter, Getter getter,
+                       const vector<Property>& invalidValues = {}) {
+        const auto expectedResults = {Result::OK,
+                                      optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
 
+        Property initialValue = expectedInitial.value;
+        ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
+        ASSERT_RESULT(expectedResults, res);
+        if (res == Result::OK && expectedInitial.check == REQUIRED) {
+            EXPECT_EQ(expectedInitial.value, initialValue);
+        }
+
+        valuesToTest.push_front(expectedInitial.value);
+        valuesToTest.push_back(initialValue);
         for (Property setValue : valuesToTest) {
             SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
                          testing::PrintToString(setValue));
-            ASSERT_OK((device.get()->*setter)(setValue));
+            auto ret = (device.get()->*setter)(setValue);
+            ASSERT_RESULT(expectedResults, ret);
+            if (ret == Result::NOT_SUPPORTED) {
+                doc::partialTest(propertyName + " setter is not supported");
+                break;
+            }
             Property getValue;
             // Make sure the getter returns the same value just set
             ASSERT_OK((device.get()->*getter)(returnIn(res, getValue)));
-            ASSERT_OK(res);
+            ASSERT_RESULT(expectedResults, res);
+            if (res == Result::NOT_SUPPORTED) {
+                doc::partialTest(propertyName + " getter is not supported");
+                continue;
+            }
             EXPECT_EQ(setValue, getValue);
         }
 
         for (Property invalidValue : invalidValues) {
             SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
                          testing::PrintToString(invalidValue));
-            EXPECT_RESULT(Result::INVALID_ARGUMENTS, (device.get()->*setter)(invalidValue));
+            EXPECT_RESULT(invalidArgsOrNotSupported, (device.get()->*setter)(invalidValue));
         }
 
-        ASSERT_OK((device.get()->*setter)(initialValue));  // restore initial value
-    }
-
-    /** Test the getter and setter of an optional feature. */
-    template <class Getter, class Setter>
-    void testOptionalAccessors(const string& propertyName, const vector<Property>& valuesToTest,
-                               Setter setter, Getter getter,
-                               const vector<Property>& invalidValues = {}) {
-        doc::test("Test the optional " + propertyName + " getters and setter");
-        {
-            SCOPED_TRACE("Test feature support by calling the getter");
-            Property initialValue;
-            ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
-            if (res == Result::NOT_SUPPORTED) {
-                doc::partialTest(propertyName + " getter is not supported");
-                return;
-            }
-            ASSERT_OK(res);  // If it is supported it must succeed
-        }
-        // The feature is supported, test it
-        testAccessors(propertyName, valuesToTest, setter, getter, invalidValues);
+        // Restore initial value
+        EXPECT_RESULT(expectedResults, (device.get()->*setter)(initialValue));
     }
 };
 
@@ -266,24 +275,22 @@
 
 TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) {
     doc::test("Check that the mic can be muted and unmuted");
-    testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, &IDevice::getMicMute);
+    testAccessors("mic mute", Initial{false}, {true}, &IDevice::setMicMute, &IDevice::getMicMute);
     // TODO: check that the mic is really muted (all sample are 0)
 }
 
 TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
-    doc::test(
-        "If master mute is supported, try to mute and unmute the master "
-        "output");
-    testOptionalAccessors("master mute", {true, false, true}, &IDevice::setMasterMute,
-                          &IDevice::getMasterMute);
+    doc::test("If master mute is supported, try to mute and unmute the master output");
+    testAccessors<OPTIONAL>("master mute", Initial{false}, {true}, &IDevice::setMasterMute,
+                            &IDevice::getMasterMute);
     // TODO: check that the master volume is really muted
 }
 
 using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>;
 TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) {
     doc::test("Test the master volume if supported");
-    testOptionalAccessors(
-        "master volume", {0, 0.5, 1}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
+    testAccessors<OPTIONAL>(
+        "master volume", Initial{1}, {0, 0.5}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
         {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()});
     // TODO: check that the master volume is really changed
 }
@@ -957,7 +964,6 @@
 TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice", ASSERT_OK(closeStream());
                ASSERT_RESULT(Result::INVALID_STATE, closeStream()))
 
-static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
 static void testCreateTooBigMmapBuffer(IStream* stream) {
     MmapBufferInfo info;
     Result res;
@@ -1415,35 +1421,36 @@
 
 TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
     doc::test("Query and set the BT SCO NR&EC state");
-    testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
-                          &IPrimaryDevice::setBtScoNrecEnabled,
-                          &IPrimaryDevice::getBtScoNrecEnabled);
+    testAccessors<OPTIONAL>("BtScoNrecEnabled", Initial{false, OPTIONAL}, {true},
+                            &IPrimaryDevice::setBtScoNrecEnabled,
+                            &IPrimaryDevice::getBtScoNrecEnabled);
 }
 
 TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
     doc::test("Query and set the SCO whideband state");
-    testOptionalAccessors("BtScoWideband", {true, false, true},
-                          &IPrimaryDevice::setBtScoWidebandEnabled,
-                          &IPrimaryDevice::getBtScoWidebandEnabled);
+    testAccessors<OPTIONAL>("BtScoWideband", Initial{false, OPTIONAL}, {true},
+                            &IPrimaryDevice::setBtScoWidebandEnabled,
+                            &IPrimaryDevice::getBtScoWidebandEnabled);
 }
 
 TEST_F(BoolAccessorPrimaryHidlTest, setGetBtHfpEnabled) {
     doc::test("Query and set the BT HFP state");
-    testOptionalAccessors("BtHfpEnabled", {true, false, true}, &IPrimaryDevice::setBtHfpEnabled,
-                          &IPrimaryDevice::getBtHfpEnabled);
+    testAccessors<OPTIONAL>("BtHfpEnabled", Initial{false, OPTIONAL}, {true},
+                            &IPrimaryDevice::setBtHfpEnabled, &IPrimaryDevice::getBtHfpEnabled);
 }
 
 using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
 TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
     doc::test("Query and set the TTY mode state");
-    testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
-                          &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
+    testAccessors<OPTIONAL>("TTY mode", Initial{TtyMode::OFF},
+                            {TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
+                            &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
 }
 
 TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
     doc::test("Query and set the HAC state");
-    testOptionalAccessors("HAC", {true, false, true}, &IPrimaryDevice::setHacEnabled,
-                          &IPrimaryDevice::getHacEnabled);
+    testAccessors<OPTIONAL>("HAC", Initial{false}, {true}, &IPrimaryDevice::setHacEnabled,
+                            &IPrimaryDevice::getHacEnabled);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
index a27ac25..35ff110 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.h
@@ -36,6 +36,7 @@
 
 class ParametersUtil {
    public:
+    Result setParam(const char* name, const char* value);
     Result getParam(const char* name, bool* value);
     Result getParam(const char* name, int* value);
     Result getParam(const char* name, String8* value, AudioParameter context = {});
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
index afff2b6..34bc53c 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/ParametersUtil.impl.h
@@ -112,6 +112,12 @@
     return std::unique_ptr<AudioParameter>(new AudioParameter(paramsAndValues));
 }
 
+Result ParametersUtil::setParam(const char* name, const char* value) {
+    AudioParameter param;
+    param.add(String8(name), String8(value));
+    return setParams(param);
+}
+
 Result ParametersUtil::setParam(const char* name, bool value) {
     AudioParameter param;
     param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
index 61ffbe0..f269dd4 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/PrimaryDevice.impl.h
@@ -208,16 +208,56 @@
     return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, enabled);
 }
 
+static const char* convertTtyModeFromHIDL(IPrimaryDevice::TtyMode mode) {
+    switch (mode) {
+        case IPrimaryDevice::TtyMode::OFF:
+            return AUDIO_PARAMETER_VALUE_TTY_OFF;
+        case IPrimaryDevice::TtyMode::VCO:
+            return AUDIO_PARAMETER_VALUE_TTY_VCO;
+        case IPrimaryDevice::TtyMode::HCO:
+            return AUDIO_PARAMETER_VALUE_TTY_HCO;
+        case IPrimaryDevice::TtyMode::FULL:
+            return AUDIO_PARAMETER_VALUE_TTY_FULL;
+        default:
+            return nullptr;
+    }
+}
+static IPrimaryDevice::TtyMode convertTtyModeToHIDL(const char* halMode) {
+    if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
+        return IPrimaryDevice::TtyMode::OFF;
+    else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
+        return IPrimaryDevice::TtyMode::VCO;
+    else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
+        return IPrimaryDevice::TtyMode::HCO;
+    else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
+        return IPrimaryDevice::TtyMode::FULL;
+    return IPrimaryDevice::TtyMode(-1);
+}
+
 Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
-    int halMode;
+    String8 halMode;
     Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_TTY_MODE, &halMode);
-    TtyMode mode = retval == Result::OK ? TtyMode(halMode) : TtyMode::OFF;
-    _hidl_cb(retval, mode);
+    if (retval != Result::OK) {
+        _hidl_cb(retval, TtyMode::OFF);
+        return Void();
+    }
+    TtyMode mode = convertTtyModeToHIDL(halMode);
+    if (mode == TtyMode(-1)) {
+        ALOGE("HAL returned invalid TTY value: %s", halMode.c_str());
+        _hidl_cb(Result::INVALID_STATE, TtyMode::OFF);
+        return Void();
+    }
+    _hidl_cb(Result::OK, mode);
     return Void();
 }
 
 Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
-    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, static_cast<int>(mode));
+    const char* modeStr = convertTtyModeFromHIDL(mode);
+    if (modeStr == nullptr) {
+        ALOGW("Can not set an invalid TTY value: %d", mode);
+        return Result::INVALID_ARGUMENTS;
+    }
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, modeStr);
 }
 
 Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
index f5a49b3..51d2e11 100644
--- a/audio/effect/2.0/vts/functional/Android.bp
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -27,10 +27,9 @@
         "android.hardware.audio.effect@2.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
-        "libxml2",
-    ],
-    shared_libs: [
         "libeffectsconfig",
         "libicuuc",
+        "libicuuc_stubdata",
+        "libxml2",
     ],
 }
diff --git a/audio/effect/4.0/vts/functional/Android.bp b/audio/effect/4.0/vts/functional/Android.bp
index 92b5db7..96ded69 100644
--- a/audio/effect/4.0/vts/functional/Android.bp
+++ b/audio/effect/4.0/vts/functional/Android.bp
@@ -27,11 +27,10 @@
         "android.hardware.audio.effect@4.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
-        "libxml2",
-    ],
-    shared_libs: [
         "libeffectsconfig",
         "libicuuc",
+        "libicuuc_stubdata",
+        "libxml2",
     ],
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
diff --git a/automotive/README.md b/automotive/README.md
new file mode 100644
index 0000000..341a1bb
--- /dev/null
+++ b/automotive/README.md
@@ -0,0 +1,10 @@
+## Autmotive HALs ##
+---
+
+## Overview: ##
+
+The automotive HAL tree is used by Android Automotive to discover and
+operate hardware specific to a car.
+
+The HALs are not (yet) frozen, as the HAL definition is expected to evolve
+between Android releases.
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 91255d0..6af774e 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -41,6 +41,7 @@
         "VehicleAreaDoor",
         "VehicleAreaMirror",
         "VehicleAreaSeat",
+        "VehicleAreaWheel",
         "VehicleAreaWindow",
         "VehicleDisplay",
         "VehicleGear",
@@ -68,7 +69,6 @@
         "VmsOfferingMessageIntegerValuesIndex",
         "VmsPublisherInformationIntegerValuesIndex",
         "VmsSubscriptionsStateIntegerValuesIndex",
-        "Wheel",
     ],
     gen_java: true,
 }
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 774bc4f..22ab079 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -62,6 +62,8 @@
         "impl/vhal_v2_0/VehicleEmulator.cpp",
         "impl/vhal_v2_0/PipeComm.cpp",
         "impl/vhal_v2_0/SocketComm.cpp",
+        "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
+        "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
     ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["impl"],
@@ -71,6 +73,7 @@
         "libprotobuf-cpp-lite",
     ],
     static_libs: [
+        "libjsoncpp",
         "libqemu_pipe",
         "android.hardware.automotive.vehicle@2.0-libproto-native",
     ],
@@ -107,6 +110,7 @@
         "android.hardware.automotive.vehicle@2.0-manager-lib",
         "android.hardware.automotive.vehicle@2.0-default-impl-lib",
         "android.hardware.automotive.vehicle@2.0-libproto-native",
+        "libjsoncpp",
         "libqemu_pipe",
     ],
 }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 48ee1bb..eb9d660 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -32,6 +32,8 @@
 constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
 constexpr int AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ;
 constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT;
+constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT;
+constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
 constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
 constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
@@ -40,40 +42,73 @@
 constexpr int VEHICLE_MAP_SERVICE = (int)VehicleProperty::VEHICLE_MAP_SERVICE;
 constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK;
 constexpr int ALL_WHEELS =
-    (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR);
+    (int)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT |
+          VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR);
+constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT |
+                                VehicleAreaSeat::ROW_2_CENTER);
+constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT);
+constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT;
 
-/*
- * This property is used for test purpose to generate fake events.
- *
- * It has the following format:
- *
- * int32Values[0] - command (see FakeDataCommand below for possible values)
- * int32Values[1] - VehicleProperty to which command applies
+/**
+ * This property is used for test purpose to generate fake events. Here is the test package that
+ * is referencing this property definition: packages/services/Car/tests/vehiclehal_test
  */
 const int32_t kGenerateFakeDataControllingProperty =
     0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 
+/**
+ * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty.
+ * All those commands can be send independently with each other. And each will override the one sent
+ * previously.
+ *
+ * The controlling property has the following format:
+ *
+ *     int32Values[0] - command enum defined in FakeDataCommand
+ *
+ * The format of the arguments is defined for each command type as below:
+ */
 enum class FakeDataCommand : int32_t {
-    /** Stops generating of fake data that was triggered by Start command */
-    Stop = 0,
-
     /**
-     * Starts fake data generation.  Caller must provide additional data:
+     * Starts linear fake data generation. Caller must provide additional data:
+     *     int32Values[1] - VehicleProperty to which command applies
      *     int64Values[0] - periodic interval in nanoseconds
      *     floatValues[0] - initial value
-     *     floatValues[1] - dispersion defines min and max range relative to initial value
+     *     floatValues[1] - dispersion defines the min/max value relative to initial value, where
+     *                      max = initial_value + dispersion, min = initial_value - dispersion.
+     *                      Dispersion should be non-negative, otherwise the behavior is undefined.
      *     floatValues[2] - increment, with every timer tick the value will be incremented by this
-     * amount
+     *                      amount. When reaching to max value, the current value will be set to min.
+     *                      It should be non-negative, otherwise the behavior is undefined.
      */
-    Start = 1,
+    StartLinear = 0,
+
+    /** Stops generating of fake data that was triggered by Start commands.
+     *     int32Values[1] - VehicleProperty to which command applies. VHAL will stop the
+     *                      corresponding linear generation for that property.
+     */
+    StopLinear = 1,
+
+    /**
+     * Starts JSON-based fake data generation. Caller must provide a string value specifying
+     * the path to fake value JSON file:
+     *     stringValue    - path to the fake values JSON file
+     */
+    StartJson = 2,
+
+    /**
+     * Stops JSON-based fake data generation. No additional arguments needed.
+     */
+    StopJson = 3,
 
     /**
      * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every
-     * key-press). Caller must provide the following data: int32Values[2] - Android key code
+     * key-press). We set the enum with high number to leave space for future start/stop commands.
+     * Caller must provide the following data:
+     *     int32Values[2] - Android key code
      *     int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see
-     * VehicleDisplay)
+     *                      VehicleDisplay)
      */
-    KeyPress = 2,
+    KeyPress = 100,
 };
 
 const int32_t kHvacPowerProperties[] = {
@@ -245,8 +280,7 @@
     {.config = {.prop = toInt(VehicleProperty::HVAC_POWER_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}},
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}},
                 // TODO(bryaneyler): Ideally, this is generated dynamically from
                 // kHvacPowerProperties.
                 .configArray =
@@ -266,58 +300,79 @@
         .initialValue = {.int32Values = {0}}  // Will be used for all areas.
     },
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+     .initialValue = {.int32Values = {0}}},
+
     {.config = {.prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
      .initialValue = {.int32Values = {1}}},
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+     .initialValue = {.int32Values = {0}}},
+
     {.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
      .initialValue = {.int32Values = {1}}},
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_AC_ON),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+     .initialValue = {.int32Values = {0}}},
+
     {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
      .initialValue = {.int32Values = {1}}},
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_DUAL_ON),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+     .initialValue = {.int32Values = {0}}},
+
     {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT),
-                    .minInt32Value = 1,
-                    .maxInt32Value = 7}}},
+                    .areaId = HVAC_ALL, .minInt32Value = 1, .maxInt32Value = 7}}},
      .initialValue = {.int32Values = {3}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
+                .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
      .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_STEERING_WHEEL_HEAT),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{
+                    .areaId = (0), .minInt32Value = -2, .maxInt32Value = 2}}},
+     .initialValue = {.int32Values = {0}}},  // +ve values for heating and -ve for cooling
+
     {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaSeat::ROW_1_LEFT),
-                                    .minFloatValue = 16,
-                                    .maxFloatValue = 32,
+                                    .areaId = HVAC_LEFT, .minFloatValue = 16, .maxFloatValue = 32,
                                 },
                                 VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT),
-                                    .minFloatValue = 16,
-                                    .maxFloatValue = 32,
+                                    .areaId = HVAC_RIGHT, .minFloatValue = 16, .maxFloatValue = 32,
                                 }}},
-     .initialAreaValues = {{toInt(VehicleAreaSeat::ROW_1_LEFT), {.floatValues = {16}}},
-                           {toInt(VehicleAreaSeat::ROW_1_RIGHT), {.floatValues = {20}}}}},
+     .initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}},
+                           {HVAC_RIGHT, {.floatValues = {20}}}}},
 
     {.config =
          {
@@ -330,6 +385,12 @@
          },
      .initialValue = {.floatValues = {25.0f}}},
 
+    {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}},
+     .initialValue = {.int32Values = {(int)VehicleUnit::FAHRENHEIT}}},
+
     {.config =
          {
              .prop = toInt(VehicleProperty::NIGHT_MODE),
@@ -381,13 +442,13 @@
             },
     },
 
-    {.config =
-         {
-             .prop = toInt(VehicleProperty::DOOR_LOCK),
-             .access = VehiclePropertyAccess::READ,
-             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-         },
-     .initialValue = {.int32Values = {1}}},
+    {.config = {.prop = toInt(VehicleProperty::DOOR_LOCK),
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
+                                VehicleAreaConfig{.areaId = DOOR_1_RIGHT}}},
+     .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
+                           {DOOR_1_RIGHT, {.int32Values = {1}}}}},
 
     {.config =
          {
@@ -400,23 +461,15 @@
          },
      .initialValue = {.int64Values = {0, 100000, 200000, 300000, 400000}}},
 
-    {
-        .config =
-            {
-                .prop = ABS_ACTIVE,
+    {.config = {.prop = ABS_ACTIVE,
                 .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-            },
-    },
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+     .initialValue = {.int32Values = {0}}},
 
-    {
-        .config =
-            {
-                .prop = TRACTION_CONTROL_ACTIVE,
+    {.config = {.prop = TRACTION_CONTROL_ACTIVE,
                 .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-            },
-    },
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+     .initialValue = {.int32Values = {0}}},
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
                 .access = VehiclePropertyAccess::READ,
@@ -426,8 +479,7 @@
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
                 .access = VehiclePropertyAccess::WRITE,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .configArray = {3}},
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
      .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 2eb905d..07695bf 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -19,6 +19,8 @@
 #include <android-base/macros.h>
 
 #include "EmulatedVehicleHal.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
 #include "Obd2SensorStore.h"
 
 namespace android {
@@ -88,10 +90,12 @@
 EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
-      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer,
-                                  this, std::placeholders::_1)),
-      mFakeValueGenerator(std::bind(&EmulatedVehicleHal::onFakeValueGenerated,
-                                    this, std::placeholders::_1, std::placeholders::_2)) {
+      mRecurrentTimer(
+          std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
+      mLinearFakeValueGenerator(std::make_unique<LinearFakeValueGenerator>(
+          std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))),
+      mJsonFakeValueGenerator(std::make_unique<JsonFakeValueGenerator>(
+          std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))) {
     initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
@@ -135,10 +139,11 @@
             return status;
         }
     } else if (mHvacPowerProps.count(propValue.prop)) {
-        // TODO(75328113): this should be handled by property status
         auto hvacPowerOn = mPropStore->readValueOrNull(
             toInt(VehicleProperty::HVAC_POWER_ON),
-            (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT));
+            (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
+             VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
+             VehicleAreaSeat::ROW_2_RIGHT));
 
         if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
                 && hvacPowerOn->value.int32Values[0] == 0) {
@@ -328,42 +333,29 @@
 StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
     ALOGI("%s", __func__);
     const auto& v = request.value;
-    if (v.int32Values.size() < 2) {
-        ALOGE("%s: expected at least 2 elements in int32Values, got: %zu", __func__,
-                v.int32Values.size());
+    if (!v.int32Values.size()) {
+        ALOGE("%s: expected at least \"command\" field in int32Values", __func__);
         return StatusCode::INVALID_ARG;
     }
 
     FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-    int32_t propId = v.int32Values[1];
 
     switch (command) {
-        case FakeDataCommand::Start: {
-            if (!v.int64Values.size()) {
-                ALOGE("%s: interval is not provided in int64Values", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            auto interval = std::chrono::nanoseconds(v.int64Values[0]);
-
-            if (v.floatValues.size() < 3) {
-                ALOGE("%s: expected at least 3 element sin floatValues, got: %zu", __func__,
-                        v.floatValues.size());
-                return StatusCode::INVALID_ARG;
-            }
-            float initialValue = v.floatValues[0];
-            float dispersion = v.floatValues[1];
-            float increment = v.floatValues[2];
-
-            ALOGI("%s, propId: %d, initalValue: %f", __func__, propId, initialValue);
-            mFakeValueGenerator.startGeneratingHalEvents(
-                interval, propId, initialValue, dispersion, increment);
-
-            break;
+        case FakeDataCommand::StartLinear: {
+            ALOGI("%s, FakeDataCommand::StartLinear", __func__);
+            return mLinearFakeValueGenerator->start(request);
         }
-        case FakeDataCommand::Stop: {
-            ALOGI("%s, FakeDataCommand::Stop", __func__);
-            mFakeValueGenerator.stopGeneratingHalEvents(propId);
-            break;
+        case FakeDataCommand::StartJson: {
+            ALOGI("%s, FakeDataCommand::StartJson", __func__);
+            return mJsonFakeValueGenerator->start(request);
+        }
+        case FakeDataCommand::StopLinear: {
+            ALOGI("%s, FakeDataCommand::StopLinear", __func__);
+            return mLinearFakeValueGenerator->stop(request);
+        }
+        case FakeDataCommand::StopJson: {
+            ALOGI("%s, FakeDataCommand::StopJson", __func__);
+            return mJsonFakeValueGenerator->stop(request);
         }
         case FakeDataCommand::KeyPress: {
             ALOGI("%s, FakeDataCommand::KeyPress", __func__);
@@ -374,7 +366,6 @@
             doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
             break;
         }
-
         default: {
             ALOGE("%s: unexpected command: %d", __func__, command);
             return StatusCode::INVALID_ARG;
@@ -396,30 +387,16 @@
     return keyEvent;
 }
 
-void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) {
+void EmulatedVehicleHal::onFakeValueGenerated(const VehiclePropValue& value) {
+    ALOGD("%s: %s", __func__, toString(value).c_str());
     static constexpr bool shouldUpdateStatus = false;
 
-    VehiclePropValuePtr updatedPropValue {};
-    switch (getPropType(propId)) {
-        case VehiclePropertyType::FLOAT:
-            updatedPropValue = getValuePool()->obtainFloat(value);
-            break;
-        case VehiclePropertyType::INT32:
-            updatedPropValue = getValuePool()->obtainInt32(static_cast<int32_t>(value));
-            break;
-        default:
-            ALOGE("%s: data type for property: 0x%x not supported", __func__, propId);
-            return;
-
-    }
-
+    VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
     if (updatedPropValue) {
-        updatedPropValue->prop = propId;
-        updatedPropValue->areaId = 0;  // Add area support if necessary.
         updatedPropValue->timestamp = elapsedRealtimeNano();
         updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
         mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus);
-        auto changeMode = mPropStore->getConfigOrDie(propId)->changeMode;
+        auto changeMode = mPropStore->getConfigOrDie(value.prop)->changeMode;
         if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) {
             doHalEvent(move(updatedPropValue));
         }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index d291dba..c188aef 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -30,9 +30,10 @@
 #include "vhal_v2_0/VehiclePropertyStore.h"
 
 #include "DefaultConfig.h"
-#include "VehicleEmulator.h"
 #include "FakeValueGenerator.h"
 
+#include "VehicleEmulator.h"
+
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -66,7 +67,7 @@
     }
 
     StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-    void onFakeValueGenerated(int32_t propId, float value);
+    void onFakeValueGenerated(const VehiclePropValue& value);
     VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                              int32_t targetDisplay);
 
@@ -84,7 +85,8 @@
     VehiclePropertyStore* mPropStore;
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
-    FakeValueGenerator mFakeValueGenerator;
+    std::unique_ptr<FakeValueGenerator> mLinearFakeValueGenerator;
+    std::unique_ptr<FakeValueGenerator> mJsonFakeValueGenerator;
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index 7bbbb08..1eeb88d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -14,15 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_
-
-#include <chrono>
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
 
-#include <vhal_v2_0/RecurrentTimer.h>
-
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -31,89 +27,27 @@
 
 namespace impl {
 
+using OnHalEvent = std::function<void(const VehiclePropValue& event)>;
+using MuxGuard = std::lock_guard<std::mutex>;
+
 class FakeValueGenerator {
-private:
-    // In every timer tick we may want to generate new value based on initial value for debug
-    // purpose. It's better to have sequential values to see if events gets delivered in order
-    // to the client.
-
-    struct GeneratorCfg {
-        float initialValue;  //
-        float currentValue;  //  Should be in range (initialValue +/- dispersion).
-        float dispersion;    //  Defines minimum and maximum value based on initial value.
-        float increment;     //  Value that we will be added to currentValue with each timer tick.
-    };
-
 public:
-    using OnHalEvent = std::function<void(int32_t propId, float value)>;
-
-    FakeValueGenerator(const OnHalEvent& onHalEvent) :
-        mOnHalEvent(onHalEvent),
-        mRecurrentTimer(std::bind(&FakeValueGenerator::onTimer, this,
-                                  std::placeholders::_1))
-    {}
-
-    ~FakeValueGenerator() = default;
-
-
-    void startGeneratingHalEvents(std::chrono::nanoseconds interval, int propId, float initialValue,
-                                  float dispersion, float increment) {
-        MuxGuard g(mLock);
-
-        removeLocked(propId);
-
-        mGenCfg.insert({propId, GeneratorCfg {
-            .initialValue = initialValue,
-            .currentValue = initialValue,
-            .dispersion = dispersion,
-            .increment = increment,
-        }});
-
-        mRecurrentTimer.registerRecurrentEvent(interval, propId);
-    }
-
-    void stopGeneratingHalEvents(int propId) {
-        MuxGuard g(mLock);
-        if (propId == 0) {
-            // Remove all.
-            for (auto&& it : mGenCfg) {
-                removeLocked(it.first);
-            }
-        } else {
-            removeLocked(propId);
-        }
-    }
-
-private:
-    void removeLocked(int propId) {
-        if (mGenCfg.erase(propId)) {
-            mRecurrentTimer.unregisterRecurrentEvent(propId);
-        }
-    }
-
-    void onTimer(const std::vector<int32_t>& properties) {
-        MuxGuard g(mLock);
-
-        for (int32_t propId : properties) {
-            auto& cfg = mGenCfg[propId];
-            cfg.currentValue += cfg.increment;
-            if (cfg.currentValue > cfg.initialValue + cfg.dispersion) {
-                cfg.currentValue = cfg.initialValue - cfg.dispersion;
-            }
-            mOnHalEvent(propId, cfg.currentValue);
-        }
-    }
-
-private:
-    using MuxGuard = std::lock_guard<std::mutex>;
-
-    mutable std::mutex mLock;
-    OnHalEvent mOnHalEvent;
-    RecurrentTimer mRecurrentTimer;
-    std::unordered_map<int32_t, GeneratorCfg> mGenCfg;
+    virtual ~FakeValueGenerator() = default;
+    /**
+     * Starts generating VHAL events
+     *
+     * @param request in VehiclePropValue with required information to start fake data generation
+     * @return StatusCode of the start request
+     */
+    virtual StatusCode start(const VehiclePropValue& request) = 0;
+    /**
+     * Stops generating VHAL events
+     * @param request in VehiclePropValue with required information to stop fake data generation
+     * @return StatusCode of the stop request
+     */
+    virtual StatusCode stop(const VehiclePropValue& request) = 0;
 };
 
-
 }  // impl
 
 }  // namespace V2_0
@@ -122,6 +56,4 @@
 }  // namespace hardware
 }  // namespace android
 
-
-
-#endif //android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
new file mode 100644
index 0000000..88b8f86
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2018 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 "JsonFakeValueGenerator"
+
+#include <fstream>
+
+#include <log/log.h>
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "JsonFakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent)
+    : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {}
+
+JsonFakeValueGenerator::~JsonFakeValueGenerator() {
+    mStopRequested = true;
+    {
+        MuxGuard g(mLock);
+        mGenCfg.index = 0;
+        mGenCfg.events.clear();
+    }
+    mCond.notify_one();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    if (v.stringValue.empty()) {
+        ALOGE("%s: path to JSON file is missing", __func__);
+        return StatusCode::INVALID_ARG;
+    }
+    const char* file = v.stringValue.c_str();
+    std::ifstream ifs(file);
+    if (!ifs) {
+        ALOGE("%s: couldn't open %s for parsing.", __func__, file);
+        return StatusCode::INTERNAL_ERROR;
+    }
+    std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs);
+
+    {
+        MuxGuard g(mLock);
+        mGenCfg = {0, fakeVhalEvents};
+    }
+    mCond.notify_one();
+    return StatusCode::OK;
+}
+
+StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    if (!v.stringValue.empty()) {
+        ALOGI("%s: %s", __func__, v.stringValue.c_str());
+    }
+
+    {
+        MuxGuard g(mLock);
+        mGenCfg.index = 0;
+        mGenCfg.events.clear();
+    }
+    mCond.notify_one();
+    return StatusCode::OK;
+}
+
+std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) {
+    std::vector<VehiclePropValue> fakeVhalEvents;
+
+    Json::Reader reader;
+    Json::Value rawEvents;
+    if (!reader.parse(is, rawEvents)) {
+        ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__,
+              reader.getFormattedErrorMessages().c_str());
+        return fakeVhalEvents;
+    }
+
+    for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
+        Json::Value rawEvent = rawEvents[i];
+        if (!rawEvent.isObject()) {
+            ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
+                  rawEvent.toStyledString().c_str());
+            continue;
+        }
+        if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
+            rawEvent["timestamp"].empty()) {
+            ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
+                  rawEvent.toStyledString().c_str());
+            continue;
+        }
+        VehiclePropValue event = {.prop = rawEvent["prop"].asInt(),
+                                  .areaId = rawEvent["areaId"].asInt(),
+                                  .timestamp = rawEvent["timestamp"].asInt64()};
+
+        Json::Value rawEventValue = rawEvent["value"];
+        auto& value = event.value;
+        switch (getPropType(event.prop)) {
+            case VehiclePropertyType::BOOLEAN:
+            case VehiclePropertyType::INT32:
+                value.int32Values.resize(1);
+                value.int32Values[0] = rawEventValue.asInt();
+                break;
+            case VehiclePropertyType::INT64:
+                value.int64Values.resize(1);
+                value.int64Values[0] = rawEventValue.asInt64();
+                break;
+            case VehiclePropertyType::FLOAT:
+                value.floatValues.resize(1);
+                value.floatValues[0] = rawEventValue.asFloat();
+                break;
+            case VehiclePropertyType::STRING:
+                value.stringValue = rawEventValue.asString();
+                break;
+            default:
+                ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__,
+                      event.prop, rawEventValue.asString().c_str());
+                continue;
+        }
+        fakeVhalEvents.push_back(event);
+    }
+    return fakeVhalEvents;
+}
+
+void JsonFakeValueGenerator::loop() {
+    static constexpr auto kInvalidTime = TimePoint(Nanos::max());
+
+    while (!mStopRequested) {
+        auto nextEventTime = kInvalidTime;
+        {
+            MuxGuard g(mLock);
+            if (mGenCfg.index < mGenCfg.events.size()) {
+                mOnHalEvent(mGenCfg.events[mGenCfg.index]);
+            }
+            if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) {
+                Nanos intervalNano =
+                    static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp -
+                                       mGenCfg.events[mGenCfg.index].timestamp);
+                nextEventTime = Clock::now() + intervalNano;
+            }
+            mGenCfg.index++;
+        }
+
+        std::unique_lock<std::mutex> g(mLock);
+        mCond.wait_until(g, nextEventTime);
+    }
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
new file mode 100644
index 0000000..51da4c5
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <thread>
+
+#include <json/json.h>
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class JsonFakeValueGenerator : public FakeValueGenerator {
+private:
+    using Nanos = std::chrono::nanoseconds;
+    using Clock = std::chrono::steady_clock;
+    using TimePoint = std::chrono::time_point<Clock, Nanos>;
+
+    struct GeneratorCfg {
+        size_t index;
+        std::vector<VehiclePropValue> events;
+    };
+
+public:
+    JsonFakeValueGenerator(const OnHalEvent& onHalEvent);
+    ~JsonFakeValueGenerator();
+    StatusCode start(const VehiclePropValue& request) override;
+    StatusCode stop(const VehiclePropValue& request) override;
+
+private:
+    std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is);
+    void loop();
+
+private:
+    OnHalEvent mOnHalEvent;
+    std::thread mThread;
+    mutable std::mutex mLock;
+    std::condition_variable mCond;
+    GeneratorCfg mGenCfg;
+    std::atomic_bool mStopRequested{false};
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
new file mode 100644
index 0000000..8cb9322
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 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 "LinearFakeValueGenerator"
+
+#include <log/log.h>
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "LinearFakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(const OnHalEvent& onHalEvent)
+    : mOnHalEvent(onHalEvent),
+      mRecurrentTimer(std::bind(&LinearFakeValueGenerator::onTimer, this, std::placeholders::_1)) {}
+
+StatusCode LinearFakeValueGenerator::start(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    if (v.int32Values.size() < 2) {
+        ALOGE("%s: expected property ID in int32Values", __func__);
+        return StatusCode::INVALID_ARG;
+    }
+    int32_t propId = v.int32Values[1];
+
+    if (!v.int64Values.size()) {
+        ALOGE("%s: interval is not provided in int64Values", __func__);
+        return StatusCode::INVALID_ARG;
+    }
+    auto interval = std::chrono::nanoseconds(v.int64Values[0]);
+
+    if (v.floatValues.size() < 3) {
+        ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
+              v.floatValues.size());
+        return StatusCode::INVALID_ARG;
+    }
+    float initialValue = v.floatValues[0];
+    float dispersion = v.floatValues[1];
+    float increment = v.floatValues[2];
+
+    MuxGuard g(mLock);
+    removeLocked(propId);
+    mGenCfg.insert({propId, GeneratorCfg{
+                                .initialValue = initialValue,
+                                .currentValue = initialValue,
+                                .dispersion = dispersion,
+                                .increment = increment,}});
+
+    mRecurrentTimer.registerRecurrentEvent(interval, propId);
+    return StatusCode::OK;
+}
+
+StatusCode LinearFakeValueGenerator::stop(const VehiclePropValue& request) {
+    const auto& v = request.value;
+    if (v.int32Values.size() < 2) {
+        ALOGE("%s: expected property ID in int32Values", __func__);
+        return StatusCode::INVALID_ARG;
+    }
+    int32_t propId = v.int32Values[1];
+
+    MuxGuard g(mLock);
+    if (propId == 0) {
+        // Remove all.
+        for (auto&& it : mGenCfg) {
+            removeLocked(it.first);
+        }
+    } else {
+        removeLocked(propId);
+    }
+    return StatusCode::OK;
+}
+
+void LinearFakeValueGenerator::removeLocked(int propId) {
+    if (mGenCfg.erase(propId)) {
+        mRecurrentTimer.unregisterRecurrentEvent(propId);
+    }
+}
+
+void LinearFakeValueGenerator::onTimer(const std::vector<int32_t>& properties) {
+    MuxGuard g(mLock);
+
+    for (int32_t propId : properties) {
+        auto& cfg = mGenCfg[propId];
+        cfg.currentValue += cfg.increment;
+        if (cfg.currentValue > cfg.initialValue + cfg.dispersion) {
+            cfg.currentValue = cfg.initialValue - cfg.dispersion;
+        }
+        VehiclePropValue event = {.prop = propId};
+        auto& value = event.value;
+        switch (getPropType(event.prop)) {
+            case VehiclePropertyType::INT32:
+                value.int32Values.resize(1);
+                value.int32Values[0] = static_cast<int32_t>(cfg.currentValue);
+                break;
+            case VehiclePropertyType::INT64:
+                value.int64Values.resize(1);
+                value.int64Values[0] = static_cast<int64_t>(cfg.currentValue);
+                break;
+            case VehiclePropertyType::FLOAT:
+                value.floatValues.resize(1);
+                value.floatValues[0] = cfg.currentValue;
+                break;
+            default:
+                ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
+                continue;
+        }
+        mOnHalEvent(event);
+    }
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
new file mode 100644
index 0000000..fe6d097
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
+
+#include <vhal_v2_0/RecurrentTimer.h>
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class LinearFakeValueGenerator : public FakeValueGenerator {
+private:
+    // In every timer tick we may want to generate new value based on initial value for debug
+    // purpose. It's better to have sequential values to see if events gets delivered in order
+    // to the client.
+
+    struct GeneratorCfg {
+        float initialValue;  //
+        float currentValue;  //  Should be in range (initialValue +/- dispersion).
+        float dispersion;    //  Defines minimum and maximum value based on initial value.
+        float increment;     //  Value that we will be added to currentValue with each timer tick.
+    };
+
+public:
+    LinearFakeValueGenerator(const OnHalEvent& onHalEvent);
+    ~LinearFakeValueGenerator() = default;
+    StatusCode start(const VehiclePropValue& request) override;
+    StatusCode stop(const VehiclePropValue& request) override;
+
+private:
+    void removeLocked(int propId);
+    void onTimer(const std::vector<int32_t>& properties);
+
+private:
+    mutable std::mutex mLock;
+    OnHalEvent mOnHalEvent;
+    RecurrentTimer mRecurrentTimer;
+    std::unordered_map<int32_t, GeneratorCfg> mGenCfg;
+};
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index faa1adc..57179df 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -42,6 +42,9 @@
 };
 
 /**
+ * Vehicle Areas
+ * Used to construct property IDs in the VehicleProperty enum.
+ *
  * Some properties may be associated with particular vehicle areas. For
  * example, VehicleProperty:DOOR_LOCK property must be associated with
  * particular door, thus this property must be marked with
@@ -50,8 +53,34 @@
  * Other properties may not be associated with particular vehicle area,
  * these kind of properties must have VehicleArea:GLOBAL flag.
  *
- * Used to create property ID in VehicleProperty enum.
- */
+ * [Definition] Area: An area represents a unique element of an AreaType.
+ *   For instance, if AreaType is WINDOW, then an area may be FRONT_WINDSHIELD.
+ *
+ * [Definition] AreaID: An AreaID is a combination of one or more areas,
+ *   and is represented using a bitmask of Area enums. Different AreaTypes may
+ *   not be mixed in a single AreaID. For instance, a window area cannot be
+ *   combined with a seat area in an AreaID.
+ *
+ * Rules for mapping a zoned property to AreaIDs:
+ *  - A property must be mapped to an array of AreaIDs that are impacted when
+ *    the property value changes.
+ *  - Each element in the array must represent an AreaID, in which, the
+ *    property value can only be changed together in all the areas within
+ *    an AreaID and never independently. That is, when the property value
+ *    changes in one of the areas in an AreaID in the array, then it must
+ *    automatically change in all other areas in the AreaID.
+ *  - The property value must be independently controllable in any two
+ *    different AreaIDs in the array.
+ *  - An area must only appear once in the array of AreaIDs. That is, an
+ *    area must only be part of a single AreaID in the array.
+ *
+ * [Definition] Global Property: A property that applies to the entire car
+ *   and is not associated with a specific area. For example, FUEL_LEVEL,
+ *   HVAC_STEERING_WHEEL_HEAT.
+ *
+ * Rules for mapping a global property to AreaIDs:
+ *  - A global property must not be mapped to AreaIDs.
+*/
 enum VehicleArea : int32_t {
     GLOBAL      = 0x01000000,
     /** WINDOW maps to enum VehicleAreaWindow */
@@ -62,7 +91,7 @@
     SEAT        = 0x05000000,
     /** DOOR maps to enum VehicleAreaDoor */
     DOOR        = 0x06000000,
-    /** WHEEL maps to enum Wheel */
+    /** WHEEL maps to enum VehicleAreaWheel */
     WHEEL       = 0x07000000,
 
     MASK        = 0x0f000000,
@@ -331,16 +360,16 @@
     /**
      * Reports wheel ticks
      *
-     * The first four elements represent ticks for individual wheels in the
+     * The first element in the vector is a reset count.  A reset indicates
+     * previous tick counts are not comparable with this and future ones.  Some
+     * sort of discontinuity in tick counting has occurred.
+     *
+     * The next four elements represent ticks for individual wheels in the
      * following order: front left, front right, rear right, rear left.  All
      * tick counts are cumulative.  Tick counts increment when the vehicle
      * moves forward, and decrement when vehicles moves in reverse.  The ticks
      * should be reset to 0 when the vehicle is started by the user.
      *
-     * The next element in the vector is a reset count.  A reset indicates
-     * previous tick counts are not comparable with this and future ones.  Some
-     * sort of discontinuity in tick counting has occurred.
-     *
      *  int64Values[0] = reset count
      *  int64Values[1] = front left ticks
      *  int64Values[2] = front right ticks
@@ -472,7 +501,8 @@
     /**
      * Tire pressure
      *
-     * The min/max range is used to indicate the recommended tire pressure.
+     * min/max value indicates tire pressure sensor range.  Each tire will have a separate min/max
+     * value denoted by its areaConfig.areaId.
      *
      * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
@@ -481,7 +511,7 @@
     TIRE_PRESSURE = (
         0x0309
         | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:MIXED
+        | VehiclePropertyType:FLOAT
         | VehicleArea:WHEEL),
 
     /**
@@ -489,6 +519,12 @@
      *
      * This is the gear selected by the user.
      *
+     * Values in the config data must represent the list of supported gears
+     * for this vehicle.  For example, config data for an automatic transmission
+     * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_DRIVE,
+     * GEAR_1, GEAR_2,...} and for manual transmission the list must be
+     * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @data_enum VehicleGear
@@ -500,8 +536,17 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Current gear. In non-manual case, selected gear does not necessarily
-     * match the current gear.
+     * Current gear. In non-manual case, selected gear may not
+     * match the current gear. For example, if the selected gear is GEAR_DRIVE,
+     * the current gear will be one of GEAR_1, GEAR_2 etc, which reflects
+     * the actual gear the transmission is currently running in.
+     *
+     * Values in the config data must represent the list of supported gears
+     * for this vehicle.  For example, config data for an automatic transmission
+     * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...}
+     * and for manual transmission the list must be
+     * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}. This list need not be the
+     * same as that of the supported gears reported in GEAR_SELECTION.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -625,6 +670,41 @@
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
 
+    /*
+     * HVAC Properties
+     *
+     * Additional rules for mapping a zoned HVAC property to AreaIDs:
+     *  - Every seat in VehicleAreaSeat that is available in the car, must be
+     *    part of an AreaID in the AreaID array.
+     *
+     * Example 1: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three
+     *  back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). There are two
+     *  temperature control units -- driver side and passenger side.
+     *   - A valid mapping set of AreaIDs for HVAC_TEMPERATURE_SET would be a
+     *     two element array:
+     *      - ROW_1_LEFT  | ROW_2_LEFT
+     *      - ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT
+     *   - An alternative mapping for the same hardware configuration would be:
+     *      - ROW_1_LEFT  | ROW_2_CENTER | ROW_2_LEFT
+     *      - ROW_1_RIGHT | ROW_2_RIGHT
+     *  The temperature controllers are assigned to the seats which they
+     *  "most influence", but every seat must be included exactly once. The
+     *  assignment of the center rear seat to the left or right AreaID may seem
+     *  arbitrary, but the inclusion of every seat in exactly one AreaID ensures
+     *  that the seats in the car are all expressed and that a "reasonable" way
+     *  to affect each seat is available.
+     *
+     * Example 2: A car has three seat rows with two seats in the front row (ROW_1_LEFT,
+     *  ROW_1_RIGHT) and three seats in the second (ROW_2_LEFT, ROW_2_CENTER,
+     *  ROW_2_RIGHT) and third rows (ROW_3_LEFT, ROW_3_CENTER, ROW_3_RIGHT). There
+     *  are three temperature control units -- driver side, passenger side, and rear.
+     *   - A reasonable way to map HVAC_TEMPERATURE_SET to AreaIDs is a three
+     *     element array:
+     *     - ROW_1_LEFT
+     *     - ROW_1_RIGHT
+     *     - ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT | ROW_3_LEFT | ROW_3_CENTER | ROW_3_RIGHT
+     */
+
     /**
      * Fan speed setting
      *
@@ -754,22 +834,34 @@
         | VehicleArea:SEAT),
 
     /**
-     * Enable temperature coupling between zones.
+     * Enable temperature coupling between areas.
      *
-     * The areaId for this property must include the zones that are coupled
-     * together.  Typically, the front two zones (ROW_1_LEFT and ROW_1_RIGHT)
-     * are coupled together when this property is enabled.  Thus, the areaId
-     * shall be (ROW_1_LEFT | ROW_1_RIGHT).  When the property is enabled, the
-     * ECU may synchronize the temperature for the affected zones.  Any
-     * parameters modified as a side effect of turning on/off the DUAL_ON
-     * parameter shall generate onPropertyEvent() callbacks to the VHAL.  In
-     * addition, if setting a temperature (i.e. driver's temp) changes another
-     * temperature (i.e. front passenger's temp), then the appropriate
+     * The AreaIDs for HVAC_DUAL_ON property shall contain a combination of
+     * HVAC_TEMPERATURE_SET AreaIDs that can be coupled together. If
+     * HVAC_TEMPERATURE_SET is mapped to AreaIDs [a_1, a_2, ..., a_n], and if
+     * HVAC_DUAL_ON can be enabled to couple a_i and a_j, then HVAC_DUAL_ON
+     * property must be mapped to [a_i | a_j]. Further, if a_k and a_l can also
+     * be coupled together separately then HVAC_DUAL_ON must be mapped to
+     * [a_i | a_j, a_k | a_l].
+     *
+     * Example: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three
+     *  back seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). There are two
+     *  temperature control units -- driver side and passenger side -- which can
+     *  be optionally synchronized. This may be expressed in the AreaIDs this way:
+     *  - HVAC_TEMPERATURE_SET->[ROW_1_LEFT | ROW_2_LEFT, ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT]
+     *  - HVAC_DUAL_ON->[ROW_1_LEFT | ROW_2_LEFT | ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT]
+     *
+     * When the property is enabled, the ECU must synchronize the temperature
+     * for the affected areas. Any parameters modified as a side effect
+     * of turning on/off the DUAL_ON parameter shall generate
+     * onPropertyEvent() callbacks to the VHAL. In addition, if setting
+     * a temperature (i.e. driver's temperature) changes another temperature
+     * (i.e. front passenger's temperature), then the appropriate
      * onPropertyEvent() callbacks must be generated.  If a user changes a
      * temperature that breaks the coupling (e.g. setting the passenger
      * temperature independently) then the VHAL must send the appropriate
      * onPropertyEvent() callbacks (i.e. HVAC_DUAL_ON = false,
-     * HVAC_TEMPERATURE_SET[zone] = xxx, etc).
+     * HVAC_TEMPERATURE_SET[AreaID] = xxx, etc).
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -877,13 +969,41 @@
         | VehicleArea:SEAT),
 
     /**
-     * Represents global power state for HVAC.  Setting this property to false
+     * Represents global power state for HVAC. Setting this property to false
      * MAY mark some properties that control individual HVAC features/subsystems
      * to UNAVAILABLE state. Setting this property to true MAY mark some
      * properties that control individual HVAC features/subsystems to AVAILABLE
      * state (unless any/all of them are UNAVAILABLE on their own individual
-     * merits).  The list of properties affected by HVAC_POWER_ON must be set
-     * in the VehiclePropConfig.configArray.
+     * merits).
+     *
+     * [Definition] HvacPower_DependentProperties: Properties that need HVAC to be
+     *   powered on in order to enable their functionality. For example, in some cars,
+     *   in order to turn on the AC, HVAC must be powered on first.
+     *
+     * HvacPower_DependentProperties list must be set in the
+     * VehiclePropConfig.configArray. HvacPower_DependentProperties must only contain
+     * properties that are associated with VehicleArea:SEAT. Properties that are not
+     * associated with VehicleArea:SEAT, for example, HVAC_DEFROSTER, must never
+     * depend on HVAC_POWER_ON property and must never be part of
+     * HvacPower_DependentProperties list.
+     *
+     * AreaID mapping for HVAC_POWER_ON property must contain all AreaIDs that
+     * HvacPower_DependentProperties are mapped to.
+     *
+     * Example 1: A car has two front seats (ROW_1_LEFT, ROW_1_RIGHT) and three back
+     *  seats (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT). If the HVAC features (AC,
+     *  Temperature etc.) throughout the car are dependent on a single HVAC power
+     *  controller then HVAC_POWER_ON must be mapped to
+     *  [ROW_1_LEFT | ROW_1_RIGHT | ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT].
+     *
+     * Example 2: A car has two seats in the front row (ROW_1_LEFT, ROW_1_RIGHT) and
+     *   three seats in the second (ROW_2_LEFT, ROW_2_CENTER, ROW_2_RIGHT) and third
+     *   rows (ROW_3_LEFT, ROW_3_CENTER, ROW_3_RIGHT). If the car has temperature
+     *   controllers in the front row which can operate entirely independently of
+     *   temperature controllers in the back of the vehicle, then HVAC_POWER_ON
+     *   must be mapped to a two element array:
+     *   - ROW_1_LEFT | ROW_1_RIGHT
+     *   - ROW_2_LEFT | ROW_2_CENTER | ROW_2_RIGHT | ROW_3_LEFT | ROW_3_CENTER | ROW_3_RIGHT
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -971,8 +1091,8 @@
      * It is assumed that AP's power state is controller by separate power
      * controller.
      *
-     * For configuration information, VehiclePropConfig.configFlags can
-     * have bit flag combining values in VehicleApPowerStateConfigFlag.
+     * For configuration information, VehiclePropConfig.configArray can have bit flag combining
+     * values in VehicleApPowerStateConfigFlag.
      *
      *   int32Values[0] : VehicleApPowerStateReq enum value
      *   int32Values[1] : additional parameter relevant for each state,
@@ -2463,14 +2583,6 @@
      */
     vec<VehicleAreaConfig> areaConfigs;
 
-    /**
-     * Configuration flags for this property.
-     *
-     * For example, it may store the number of presets that are stored by the
-     * radio module.
-     */
-    int32_t configFlags;
-
     /** Contains additional configuration parameters */
     vec<int32_t> configArray;
 
@@ -2635,7 +2747,7 @@
     INTERNAL_ERROR = 5,
 };
 
-enum Wheel : int32_t {
+enum VehicleAreaWheel : int32_t {
     UNKNOWN = 0x0,
 
     LEFT_FRONT = 0x1,
diff --git a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
index a7f4031..9911038 100644
--- a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
+++ b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
@@ -19,6 +19,7 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
 #include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
 #include <hidl/HidlSupport.h>
@@ -28,6 +29,7 @@
 #include <future>
 #include <utility>
 
+using android::base::GetUintProperty;
 using android::Condition;
 using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
 using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
@@ -44,7 +46,7 @@
 static const uint32_t kTimeout = 3;
 static const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
 static const uint32_t kGroupId = 99;
-static const std::string kTmpDir = "/data/system/users/0/fpdata/";
+static std::string kTmpDir = "";
 static const uint32_t kIterations = 1000;
 
 // Wait for a callback to occur (signaled by the given future) up to the
@@ -199,9 +201,25 @@
         FingerprintHidlEnvironment::Instance()->getServiceName<IBiometricsFingerprint>());
     ASSERT_FALSE(mService == nullptr);
 
-    // Create an active group
-    // FP service can only write to /data/system/users/*/fpdata/ due to
-    // SELinux Policy and Linux Dir Permissions
+    /*
+     * 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.
+     */
+
+    uint64_t 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_TRUE(api_level != 0);
+
+    // 27 is the API number for O-MR1
+    if (api_level <= 27) {
+      kTmpDir = "/data/system/users/0/fpdata/";
+    } else {
+      kTmpDir = "/data/vendor_de/0/fpdata/";
+    }
+
     Return<RequestStatus> res = mService->setActiveGroup(kGroupId, kTmpDir);
     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
   }
diff --git a/broadcastradio/1.0/types.hal b/broadcastradio/1.0/types.hal
index 8c3ec11..259c7c9 100644
--- a/broadcastradio/1.0/types.hal
+++ b/broadcastradio/1.0/types.hal
@@ -136,7 +136,8 @@
     uint32_t        numAudioSources;
     /** the hardware supports capture of audio source from audio HAL */
     bool            supportsCapture;
-    vec<BandConfig> bands; /** band descriptors */
+    /** band descriptors */
+    vec<BandConfig> bands;
 };
 
 enum MetadataType : int32_t {
@@ -229,6 +230,7 @@
      */
     uint32_t signalStrength;
 
-    vec<MetaData> metadata; /** Metadata: PTY, song title etc. */
+    /** Metadata: PTY, song title etc. */
+    vec<MetaData> metadata;
 };
 
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 571b80c..62b0037 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -137,29 +137,30 @@
 }
 
 Return<void> TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& info) {
-    auto logically = utils::getType(info.logicallyTunedTo);
-    if (logically != IdentifierType::INVALID) {
-        EXPECT_TRUE(logically == IdentifierType::AMFM_FREQUENCY ||
-                    logically == IdentifierType::RDS_PI ||
-                    logically == IdentifierType::HD_STATION_ID_EXT ||
-                    logically == IdentifierType::DAB_SID_EXT ||
-                    logically == IdentifierType::DRMO_SERVICE_ID ||
-                    logically == IdentifierType::SXM_SERVICE_ID ||
-                    (logically >= IdentifierType::VENDOR_START &&
-                     logically <= IdentifierType::VENDOR_END) ||
-                    logically > IdentifierType::SXM_CHANNEL);
+    for (auto&& id : info.selector) {
+        EXPECT_NE(IdentifierType::INVALID, utils::getType(id));
     }
 
+    auto logically = utils::getType(info.logicallyTunedTo);
+    /* This field is required for currently tuned program and should be INVALID
+     * for entries from the program list.
+     */
+    EXPECT_TRUE(
+        logically == IdentifierType::AMFM_FREQUENCY || logically == IdentifierType::RDS_PI ||
+        logically == IdentifierType::HD_STATION_ID_EXT ||
+        logically == IdentifierType::DAB_SID_EXT || logically == IdentifierType::DRMO_SERVICE_ID ||
+        logically == IdentifierType::SXM_SERVICE_ID ||
+        (logically >= IdentifierType::VENDOR_START && logically <= IdentifierType::VENDOR_END) ||
+        logically > IdentifierType::SXM_CHANNEL);
+
     auto physically = utils::getType(info.physicallyTunedTo);
-    if (physically != IdentifierType::INVALID) {
-        EXPECT_TRUE(physically == IdentifierType::AMFM_FREQUENCY ||
-                    physically == IdentifierType::DAB_ENSEMBLE ||
-                    physically == IdentifierType::DRMO_FREQUENCY ||
-                    physically == IdentifierType::SXM_CHANNEL ||
-                    (physically >= IdentifierType::VENDOR_START &&
-                     physically <= IdentifierType::VENDOR_END) ||
-                    physically > IdentifierType::SXM_CHANNEL);
-    }
+    // ditto (see "logically" above)
+    EXPECT_TRUE(
+        physically == IdentifierType::AMFM_FREQUENCY ||
+        physically == IdentifierType::DAB_ENSEMBLE ||
+        physically == IdentifierType::DRMO_FREQUENCY || physically == IdentifierType::SXM_CHANNEL ||
+        (physically >= IdentifierType::VENDOR_START && physically <= IdentifierType::VENDOR_END) ||
+        physically > IdentifierType::SXM_CHANNEL);
 
     if (logically == IdentifierType::AMFM_FREQUENCY) {
         auto ps = utils::getMetadataString(info, MetadataKey::RDS_PS);
diff --git a/broadcastradio/common/tests/IdentifierIterator_test.cpp b/broadcastradio/common/tests/IdentifierIterator_test.cpp
index 5bf222b..75e0d49 100644
--- a/broadcastradio/common/tests/IdentifierIterator_test.cpp
+++ b/broadcastradio/common/tests/IdentifierIterator_test.cpp
@@ -33,8 +33,8 @@
     };
     // clang-format on
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
 
     ASSERT_NE(end, it);
     EXPECT_EQ(sel.primaryId, *it);
@@ -46,8 +46,8 @@
 TEST(IdentifierIteratorTest, empty) {
     V2_0::ProgramSelector sel{};
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
 
     ASSERT_NE(end, it++);  // primary id is always present
     ASSERT_EQ(end, it);
@@ -57,8 +57,8 @@
     V2_0::ProgramSelector sel1{};
     V2_0::ProgramSelector sel2{};
 
-    auto it1 = utils::begin(sel1);
-    auto it2 = utils::begin(sel2);
+    auto it1 = V2_0::begin(sel1);
+    auto it2 = V2_0::begin(sel2);
 
     EXPECT_NE(it1, it2);
 }
@@ -66,8 +66,8 @@
 TEST(IdentifierIteratorTest, increments) {
     V2_0::ProgramSelector sel{{}, {{}, {}}};
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
     auto pre = it;
     auto post = it;
 
@@ -102,8 +102,8 @@
     auto isRdsPi = std::bind(typeEquals, _1, IdentifierType::RDS_PI);
     auto isFreq = std::bind(typeEquals, _1, IdentifierType::AMFM_FREQUENCY);
 
-    auto end = utils::end(sel);
-    auto it = std::find_if(utils::begin(sel), end, isRdsPi);
+    auto end = V2_0::end(sel);
+    auto it = std::find_if(V2_0::begin(sel), end, isRdsPi);
     ASSERT_NE(end, it);
     EXPECT_EQ(rds_pi1, it->value);
 
@@ -111,7 +111,7 @@
     ASSERT_NE(end, it);
     EXPECT_EQ(rds_pi2, it->value);
 
-    it = std::find_if(utils::begin(sel), end, isFreq);
+    it = std::find_if(V2_0::begin(sel), end, isFreq);
     ASSERT_NE(end, it);
     EXPECT_EQ(freq1, it->value);
 
@@ -120,4 +120,17 @@
     EXPECT_EQ(freq2, it->value);
 }
 
+TEST(IdentifierIteratorTest, rangeLoop) {
+    V2_0::ProgramSelector sel{{}, {{}, {}, {}}};
+
+    unsigned count = 0;
+    for (auto&& id : sel) {
+        ASSERT_EQ(0u, id.type);
+        count++;
+    }
+
+    const auto expectedCount = 1 + sel.secondaryIds.size();
+    ASSERT_EQ(expectedCount, count);
+}
+
 }  // anonymous namespace
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index 6fe9554..3e20b35 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -81,14 +81,6 @@
     return mPos == rhs.mPos;
 }
 
-IdentifierIterator begin(const V2_0::ProgramSelector& sel) {
-    return IdentifierIterator(sel);
-}
-
-IdentifierIterator end(const V2_0::ProgramSelector& sel) {
-    return IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
-}
-
 FrequencyBand getBand(uint64_t freq) {
     // keep in sync with
     // frameworks/base/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
@@ -411,6 +403,18 @@
 }
 
 }  // namespace utils
+
+namespace V2_0 {
+
+utils::IdentifierIterator begin(const ProgramSelector& sel) {
+    return utils::IdentifierIterator(sel);
+}
+
+utils::IdentifierIterator end(const ProgramSelector& sel) {
+    return utils::IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
+}
+
+}  // namespace V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
index 5e51941..c4aecb2 100644
--- a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
@@ -69,9 +69,6 @@
     size_t mPos = 0;
 };
 
-IdentifierIterator begin(const V2_0::ProgramSelector& sel);
-IdentifierIterator end(const V2_0::ProgramSelector& sel);
-
 /**
  * Guesses band from the frequency value.
  *
@@ -153,6 +150,13 @@
 V2_0::ProgramIdentifier make_hdradio_station_name(const std::string& name);
 
 }  // namespace utils
+
+namespace V2_0 {
+
+utils::IdentifierIterator begin(const ProgramSelector& sel);
+utils::IdentifierIterator end(const ProgramSelector& sel);
+
+}  // namespace V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 9217a82..dc4e0f0 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -306,7 +306,7 @@
             return ret;
         }
         CameraMetadata m;
-        m = rawInfo.static_camera_characteristics;
+        m.append(rawInfo.static_camera_characteristics);
         deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
         cameraInfo = rawInfo;
         cameraInfo.static_camera_characteristics = m.release();
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 1cef882..69f8535 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -18,6 +18,7 @@
 #include <android/log.h>
 
 #include <set>
+#include <cutils/properties.h>
 #include <utils/Trace.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
@@ -31,9 +32,16 @@
 namespace implementation {
 
 // Size of request metadata fast message queue. Change to 0 to always use hwbinder buffer.
-static constexpr size_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
+static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
 // Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
-static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE  = 1 << 20 /* 1MB */;
+static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE  = 1 << 20 /* 1MB */;
+
+// Metadata sent by HAL will be replaced by a compact copy
+// if their (total size >= compact size + METADATA_SHRINK_ABS_THRESHOLD &&
+//           total_size >= compact size * METADATA_SHRINK_REL_THRESHOLD)
+// Heuristically picked by size of one page
+static constexpr int METADATA_SHRINK_ABS_THRESHOLD = 4096;
+static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
 
 HandleImporter CameraDeviceSession::sHandleImporter;
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
@@ -88,14 +96,30 @@
         return true;
     }
 
+    int32_t reqFMQSize = property_get_int32("ro.camera.req.fmq.size", /*default*/-1);
+    if (reqFMQSize < 0) {
+        reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+    } else {
+        ALOGV("%s: request FMQ size overridden to %d", __FUNCTION__, reqFMQSize);
+    }
+
     mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
-            CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
+            static_cast<size_t>(reqFMQSize),
+            false /* non blocking */);
     if (!mRequestMetadataQueue->isValid()) {
         ALOGE("%s: invalid request fmq", __FUNCTION__);
         return true;
     }
+
+    int32_t resFMQSize = property_get_int32("ro.camera.res.fmq.size", /*default*/-1);
+    if (resFMQSize < 0) {
+        resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+    } else {
+        ALOGV("%s: result FMQ size overridden to %d", __FUNCTION__, resFMQSize);
+    }
     mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
-            CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
+            static_cast<size_t>(resFMQSize),
+            false /* non blocking */);
     if (!mResultMetadataQueue->isValid()) {
         ALOGE("%s: invalid result fmq", __FUNCTION__);
         return true;
@@ -780,13 +804,11 @@
                 mOverridenRequest.update(
                         ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
                         defaultBoost, 1);
-                const camera_metadata_t *metaBuffer =
-                        mOverridenRequest.getAndLock();
-                convertToHidl(metaBuffer, outMetadata);
-                mOverridenRequest.unlock(metaBuffer);
-            } else {
-                convertToHidl(rawRequest, outMetadata);
             }
+            const camera_metadata_t *metaBuffer =
+                    mOverridenRequest.getAndLock();
+            convertToHidl(metaBuffer, outMetadata);
+            mOverridenRequest.unlock(metaBuffer);
         }
     }
     return status;
@@ -1362,6 +1384,64 @@
     return OK;
 }
 
+// Static helper method to copy/shrink capture result metadata sent by HAL
+void CameraDeviceSession::sShrinkCaptureResult(
+        camera3_capture_result* dst, const camera3_capture_result* src,
+        std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds,
+        std::vector<const camera_metadata_t*>* physCamMdArray,
+        bool handlePhysCam) {
+    *dst = *src;
+    // Reserve maximum number of entries to avoid metadata re-allocation.
+    mds->reserve(1 + (handlePhysCam ? src->num_physcam_metadata : 0));
+    if (sShouldShrink(src->result)) {
+        mds->emplace_back(sCreateCompactCopy(src->result));
+        dst->result = mds->back().getAndLock();
+    }
+
+    if (handlePhysCam) {
+        // First determine if we need to create new camera_metadata_t* array
+        bool needShrink = false;
+        for (uint32_t i = 0; i < src->num_physcam_metadata; i++) {
+            if (sShouldShrink(src->physcam_metadata[i])) {
+                needShrink = true;
+            }
+        }
+
+        if (!needShrink) return;
+
+        physCamMdArray->reserve(src->num_physcam_metadata);
+        dst->physcam_metadata = physCamMdArray->data();
+        for (uint32_t i = 0; i < src->num_physcam_metadata; i++) {
+            if (sShouldShrink(src->physcam_metadata[i])) {
+                mds->emplace_back(sCreateCompactCopy(src->physcam_metadata[i]));
+                dst->physcam_metadata[i] = mds->back().getAndLock();
+            } else {
+                dst->physcam_metadata[i] = src->physcam_metadata[i];
+            }
+        }
+    }
+}
+
+bool CameraDeviceSession::sShouldShrink(const camera_metadata_t* md) {
+    size_t compactSize = get_camera_metadata_compact_size(md);
+    size_t totalSize = get_camera_metadata_size(md);
+    if (totalSize >= compactSize + METADATA_SHRINK_ABS_THRESHOLD &&
+            totalSize >= compactSize * METADATA_SHRINK_REL_THRESHOLD) {
+        ALOGV("Camera metadata should be shrunk from %zu to %zu", totalSize, compactSize);
+        return true;
+    }
+    return false;
+}
+
+camera_metadata_t* CameraDeviceSession::sCreateCompactCopy(const camera_metadata_t* src) {
+    size_t compactSize = get_camera_metadata_compact_size(src);
+    void* buffer = calloc(1, compactSize);
+    if (buffer == nullptr) {
+        ALOGE("%s: Allocating %zu bytes failed", __FUNCTION__, compactSize);
+    }
+    return copy_camera_metadata(buffer, compactSize, src);
+}
+
 /**
  * Static callback forwarding methods from HAL to instance
  */
@@ -1372,7 +1452,13 @@
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
     CaptureResult result = {};
-    status_t ret = d->constructCaptureResult(result, hal_result);
+    camera3_capture_result shadowResult;
+    bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
+    std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
+    std::vector<const camera_metadata_t*> physCamMdArray;
+    sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
+
+    status_t ret = d->constructCaptureResult(result, &shadowResult);
     if (ret == OK) {
         d->mResultBatcher.processCaptureResult(result);
     }
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 269cc06..af90e5a 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -141,7 +141,7 @@
     };
 
     camera3_device_t* mDevice;
-    uint32_t mDeviceVersion;
+    const uint32_t mDeviceVersion;
     bool mIsAELockAvailable;
     bool mDerivePostRawSensKey;
     uint32_t mNumPartialResults;
@@ -329,6 +329,17 @@
 
     status_t constructCaptureResult(CaptureResult& result,
                                 const camera3_capture_result *hal_result);
+
+    // Static helper method to copy/shrink capture result metadata sent by HAL
+    // Temporarily allocated metadata copy will be hold in mds
+    static void sShrinkCaptureResult(
+            camera3_capture_result* dst, const camera3_capture_result* src,
+            std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds,
+            std::vector<const camera_metadata_t*>* physCamMdArray,
+            bool handlePhysCam);
+    static bool sShouldShrink(const camera_metadata_t* md);
+    static camera_metadata_t* sCreateCompactCopy(const camera_metadata_t* src);
+
 private:
 
     struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 9722c75..6a18161 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -479,31 +479,40 @@
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
     CaptureResult result = {};
-    status_t ret = d->constructCaptureResult(result.v3_2, hal_result);
+    camera3_capture_result shadowResult;
+    bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
+    std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
+    std::vector<const camera_metadata_t*> physCamMdArray;
+    sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
+
+    status_t ret = d->constructCaptureResult(result.v3_2, &shadowResult);
     if (ret != OK) {
         return;
     }
 
-    if (hal_result->num_physcam_metadata > d->mPhysicalCameraIds.size()) {
-        ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
-                hal_result->num_physcam_metadata);
-        return;
-    }
-    result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
-    for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
-        std::string physicalId = hal_result->physcam_ids[i];
-        if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
-            ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
-                  i, hal_result->physcam_ids[i]);
+    if (handlePhysCam) {
+        if (shadowResult.num_physcam_metadata > d->mPhysicalCameraIds.size()) {
+            ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
+                    shadowResult.num_physcam_metadata);
             return;
         }
-        V3_2::CameraMetadata physicalMetadata;
-        V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
-        PhysicalCameraMetadata physicalCameraMetadata = {
-                .fmqMetadataSize = 0,
-                .physicalCameraId = physicalId,
-                .metadata = physicalMetadata };
-        result.physicalCameraMetadata[i] = physicalCameraMetadata;
+        result.physicalCameraMetadata.resize(shadowResult.num_physcam_metadata);
+        for (uint32_t i = 0; i < shadowResult.num_physcam_metadata; i++) {
+            std::string physicalId = shadowResult.physcam_ids[i];
+            if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
+                ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
+                      i, shadowResult.physcam_ids[i]);
+                return;
+            }
+            V3_2::CameraMetadata physicalMetadata;
+            V3_2::implementation::convertToHidl(
+                    shadowResult.physcam_metadata[i], &physicalMetadata);
+            PhysicalCameraMetadata physicalCameraMetadata = {
+                    .fmqMetadataSize = 0,
+                    .physicalCameraId = physicalId,
+                    .metadata = physicalMetadata };
+            result.physicalCameraMetadata[i] = physicalCameraMetadata;
+        }
     }
     d->mResultBatcher_3_4.processCaptureResult_3_4(result);
 }
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 31c5fdd..ae24d78 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -61,6 +61,30 @@
     ],
 }
 
+
+cc_binary {
+    name: "android.hardware.camera.provider@2.4-service_64",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: ["service.cpp"],
+    compile_multilib: "64",
+    init_rc: ["android.hardware.camera.provider@2.4-service_64.rc"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libbinder",
+        "liblog",
+        "libutils",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.common@1.0",
+    ],
+}
+
 cc_binary {
     name: "android.hardware.camera.provider@2.4-external-service",
     defaults: ["hidl_defaults"],
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
new file mode 100644
index 0000000..4c721ec
--- /dev/null
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
@@ -0,0 +1,7 @@
+service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service_64
+    class hal
+    user cameraserver
+    group audio camera input drmrpc
+    ioprio rt 4
+    capabilities SYS_NICE
+    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index baffc78..ff7c0ee 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -1013,6 +1013,10 @@
 
         isPartialResult =
             (results.partialResult < request->numPartialResults);
+    } else if (resultSize > 0) {
+        request->collectedResult.append(reinterpret_cast<const camera_metadata_t*>(
+                    resultMetadata.data()));
+        isPartialResult = false;
     }
 
     hasInputBufferInRequest = request->hasInputBuffer;
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
index 1f89933..6d5e2d5 100644
--- a/cas/1.0/default/DescramblerImpl.cpp
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -96,13 +96,13 @@
         descramble_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    // Get a local copy of the shared_ptr for the plugin. Note that before
-    // calling the HIDL callback, this shared_ptr must be manually reset,
-    // since the client side could proceed as soon as the callback is called
-    // without waiting for this method to go out of scope.
-    std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
-    if (holder.get() == nullptr) {
-        _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL);
+    // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map
+    // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
+    // but the mapped memory's actual size will be smaller than the reported size.
+    if (srcBuffer.heapBase.size() > SIZE_MAX) {
+        ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+        android_errorWriteLog(0x534e4554, "79376389");
+        _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
     }
 
@@ -112,7 +112,6 @@
     // mapped ashmem, since the offset and size is controlled by client.
     if (srcMem == NULL) {
         ALOGE("Failed to map src buffer.");
-        holder.reset();
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
     }
@@ -121,7 +120,6 @@
         ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
                 srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
         android_errorWriteLog(0x534e4554, "67962232");
-        holder.reset();
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
     }
@@ -139,7 +137,6 @@
                 "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
                 srcOffset, totalBytesInSubSamples, srcBuffer.size);
         android_errorWriteLog(0x534e4554, "67962232");
-        holder.reset();
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
     }
@@ -158,7 +155,6 @@
                     "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
                     dstOffset, totalBytesInSubSamples, srcBuffer.size);
             android_errorWriteLog(0x534e4554, "67962232");
-            holder.reset();
             _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
             return Void();
         }
@@ -167,6 +163,17 @@
                 dstBuffer.secureMemory.getNativeHandle());
         dstPtr = static_cast<void *>(handle);
     }
+
+    // Get a local copy of the shared_ptr for the plugin. Note that before
+    // calling the HIDL callback, this shared_ptr must be manually reset,
+    // since the client side could proceed as soon as the callback is called
+    // without waiting for this method to go out of scope.
+    std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
+    if (holder.get() == nullptr) {
+        _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL);
+        return Void();
+    }
+
     // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
     // to ensure structs are actually idential
 
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 8904c68..3702cf0 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -64,9 +64,9 @@
 LOCAL_MODULE_STEM := compatibility_matrix.3.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    4.4.0:$(my_kernel_config_data)/p/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/p/android-4.9 \
-    4.14.0:$(my_kernel_config_data)/p/android-4.14 \
+    4.4.107:$(my_kernel_config_data)/p/android-4.4 \
+    4.9.84:$(my_kernel_config_data)/p/android-4.9 \
+    4.14.42:$(my_kernel_config_data)/p/android-4.14 \
 
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index 9bc76ea..f271642 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -88,6 +88,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.camera.provider</name>
         <version>2.4</version>
         <interface>
@@ -105,7 +113,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>ISurfaceFlingerConfigs</name>
             <instance>default</instance>
@@ -185,7 +193,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.composer</name>
-        <version>2.1</version>
+        <version>2.1-2</version>
         <interface>
             <name>IComposer</name>
             <instance>default</instance>
@@ -193,7 +201,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.mapper</name>
-        <version>2.0</version>
+        <version>2.0-1</version>
         <interface>
             <name>IMapper</name>
             <instance>default</instance>
@@ -258,7 +266,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.neuralnetworks</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IDevice</name>
             <regex-instance>.*</regex-instance>
diff --git a/configstore/1.0/default/android.hardware.configstore@1.0-service.rc b/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
deleted file mode 100644
index 40fb498..0000000
--- a/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.configstore-hal-1-0 /vendor/bin/hw/android.hardware.configstore@1.0-service
-    class hal animation
-    user system
-    group system
diff --git a/configstore/1.1/Android.bp b/configstore/1.1/Android.bp
new file mode 100644
index 0000000..2b6e6fa
--- /dev/null
+++ b/configstore/1.1/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.configstore@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ISurfaceFlingerConfigs.hal",
+    ],
+    interfaces: [
+        "android.hardware.configstore@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "DisplayOrientation",
+        "OptionalDisplayOrientation",
+    ],
+    gen_java: true,
+}
+
diff --git a/configstore/1.1/ISurfaceFlingerConfigs.hal b/configstore/1.1/ISurfaceFlingerConfigs.hal
new file mode 100644
index 0000000..3a69594
--- /dev/null
+++ b/configstore/1.1/ISurfaceFlingerConfigs.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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.configstore@1.1;
+
+import @1.0::ISurfaceFlingerConfigs;
+
+/**
+ * New revision of ISurfaceFlingerConfigs
+ */
+interface ISurfaceFlingerConfigs extends @1.0::ISurfaceFlingerConfigs {
+    /**
+     * Returns the orientation of the primary display device.
+     */
+    primaryDisplayOrientation() generates (OptionalDisplayOrientation value);
+};
diff --git a/configstore/1.0/default/Android.mk b/configstore/1.1/default/Android.mk
similarity index 69%
rename from configstore/1.0/default/Android.mk
rename to configstore/1.1/default/Android.mk
index 22d7c92..40f621b 100644
--- a/configstore/1.0/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -2,15 +2,15 @@
 
 ################################################################################
 include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.0-service
+LOCAL_MODULE := android.hardware.configstore@1.1-service
 # seccomp is not required for coverage build.
 ifneq ($(NATIVE_COVERAGE),true)
-LOCAL_REQUIRED_MODULES_arm64 := configstore@1.0.policy
+LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy
 endif
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_INIT_RC := android.hardware.configstore@1.0-service.rc
+LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc
 LOCAL_SRC_FILES:= service.cpp
 
 include $(LOCAL_PATH)/surfaceflinger.mk
@@ -22,16 +22,17 @@
     libhwminijail \
     liblog \
     libutils \
-    android.hardware.configstore@1.0
+    android.hardware.configstore@1.0 \
+    android.hardware.configstore@1.1
 
 include $(BUILD_EXECUTABLE)
 
 # seccomp filter for configstore
 ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64))
 include $(CLEAR_VARS)
-LOCAL_MODULE := configstore@1.0.policy
+LOCAL_MODULE := configstore@1.1.policy
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_SRC_FILES := seccomp_policy/configstore@1.0-$(TARGET_ARCH).policy
+LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
 include $(BUILD_PREBUILT)
 endif
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.cpp b/configstore/1.1/default/SurfaceFlingerConfigs.cpp
similarity index 70%
rename from configstore/1.0/default/SurfaceFlingerConfigs.cpp
rename to configstore/1.1/default/SurfaceFlingerConfigs.cpp
index 3239274..da3081c 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.1/default/SurfaceFlingerConfigs.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.1 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,10 +16,13 @@
 
 #include "SurfaceFlingerConfigs.h"
 
+#include <android/hardware/configstore/1.1/types.h>
+#include <log/log.h>
+
 namespace android {
 namespace hardware {
 namespace configstore {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
 // Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs
@@ -139,10 +142,59 @@
     return Void();
 }
 
+// Methods from ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs
+// follow.
+
+#ifdef PRIMARY_DISPLAY_ORIENTATION
+static_assert(PRIMARY_DISPLAY_ORIENTATION == 0 || PRIMARY_DISPLAY_ORIENTATION == 90 ||
+                  PRIMARY_DISPLAY_ORIENTATION == 180 || PRIMARY_DISPLAY_ORIENTATION == 270,
+              "Primary display orientation must be 0/90/180/270");
+#endif
+
+Return<void> SurfaceFlingerConfigs::primaryDisplayOrientation(
+    primaryDisplayOrientation_cb _hidl_cb) {
+    using ::android::hardware::configstore::V1_1::DisplayOrientation;
+
+    bool specified = false;
+    DisplayOrientation value = DisplayOrientation::ORIENTATION_0;
+
+    int orientation = 0;
+#ifdef PRIMARY_DISPLAY_ORIENTATION
+    specified = true;
+    orientation = PRIMARY_DISPLAY_ORIENTATION;
+#endif
+
+    switch (orientation) {
+        case 0: {
+            value = DisplayOrientation::ORIENTATION_0;
+            break;
+        }
+        case 90: {
+            value = DisplayOrientation::ORIENTATION_90;
+            break;
+        }
+        case 180: {
+            value = DisplayOrientation::ORIENTATION_180;
+            break;
+        }
+        case 270: {
+            value = DisplayOrientation::ORIENTATION_270;
+            break;
+        }
+        default: {
+            // statically checked above -> memory corruption
+            LOG_ALWAYS_FATAL("Invalid orientation %d", orientation);
+        }
+    }
+
+    _hidl_cb({specified, value});
+    return Void();
+}
+
 // Methods from ::android::hidl::base::V1_0::IBase follow.
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace configstore
 }  // namespace hardware
 }  // namespace android
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.h b/configstore/1.1/default/SurfaceFlingerConfigs.h
similarity index 74%
rename from configstore/1.0/default/SurfaceFlingerConfigs.h
rename to configstore/1.1/default/SurfaceFlingerConfigs.h
index 32e5fc3..3714e81 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.1/default/SurfaceFlingerConfigs.h
@@ -1,17 +1,17 @@
-#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
-#define ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
+#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
+#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
 namespace android {
 namespace hardware {
 namespace configstore {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
-using ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
@@ -32,13 +32,17 @@
     Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
     Return<void> startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override;
 
+    // Methods from
+    // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow.
+    Return<void> primaryDisplayOrientation(primaryDisplayOrientation_cb _hidl_cb) override;
+
     // Methods from ::android::hidl::base::V1_0::IBase follow.
 };
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace configstore
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
+#endif  // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
new file mode 100644
index 0000000..105678a
--- /dev/null
+++ b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
@@ -0,0 +1,4 @@
+service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service
+    class hal animation
+    user system
+    group system
diff --git a/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
similarity index 100%
rename from configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
rename to configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
diff --git a/configstore/1.0/default/service.cpp b/configstore/1.1/default/service.cpp
similarity index 77%
rename from configstore/1.0/default/service.cpp
rename to configstore/1.1/default/service.cpp
index c9c81a0..3b4e774 100644
--- a/configstore/1.0/default/service.cpp
+++ b/configstore/1.1/default/service.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.1 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.configstore@1.0-service"
+#define LOG_TAG "android.hardware.configstore@1.1-service"
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hwminijail/HardwareMinijail.h>
 
@@ -24,8 +24,8 @@
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
-using android::hardware::configstore::V1_0::implementation::SurfaceFlingerConfigs;
+using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
+using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs;
 using android::hardware::SetupMinijail;
 using android::sp;
 using android::status_t;
@@ -34,7 +34,7 @@
 int main() {
     configureRpcThreadpool(10, true);
 
-    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.0.policy");
+    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.1.policy");
 
     sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
     status_t status = surfaceFlingerConfigs->registerAsService();
diff --git a/configstore/1.0/default/surfaceflinger.mk b/configstore/1.1/default/surfaceflinger.mk
similarity index 92%
rename from configstore/1.0/default/surfaceflinger.mk
rename to configstore/1.1/default/surfaceflinger.mk
index f7487d5..51f06e1 100644
--- a/configstore/1.0/default/surfaceflinger.mk
+++ b/configstore/1.1/default/surfaceflinger.mk
@@ -58,3 +58,7 @@
 ifneq ($(SF_START_GRAPHICS_ALLOCATOR_SERVICE),)
     LOCAL_CFLAGS += -DSTART_GRAPHICS_ALLOCATOR_SERVICE
 endif
+
+ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),)
+    LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION)
+endif
diff --git a/configstore/1.1/types.hal b/configstore/1.1/types.hal
new file mode 100644
index 0000000..adc5747
--- /dev/null
+++ b/configstore/1.1/types.hal
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 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.configstore@1.1;
+
+/**
+ * Orientation in degrees.
+ */
+enum DisplayOrientation : uint8_t {
+    ORIENTATION_0,
+    ORIENTATION_90,
+    ORIENTATION_180,
+    ORIENTATION_270,
+};
+
+struct OptionalDisplayOrientation {
+    bool specified;
+    DisplayOrientation value;
+};
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index 93e52f1..cb4e6eb 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -28,11 +28,13 @@
 
     shared_libs: [
         "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
         "libbase",
         "libhidlbase"
     ],
     export_shared_lib_headers: [
         "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
         "libbase",
         "libhidlbase"
     ],
diff --git a/configstore/utils/include/configstore/Utils.h b/configstore/utils/include/configstore/Utils.h
index b107a20..e04f57d 100644
--- a/configstore/utils/include/configstore/Utils.h
+++ b/configstore/utils/include/configstore/Utils.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
 
 #include <android/hardware/configstore/1.0/types.h>
+#include <android/hardware/configstore/1.1/types.h>
 #include <hidl/Status.h>
 
 #include <sstream>
@@ -34,13 +35,20 @@
 }  // namespace details
 
 namespace configstore {
-// import types from V1_0
+// import types from configstore
+using ::android::hardware::configstore::V1_1::DisplayOrientation;
 using ::android::hardware::configstore::V1_0::OptionalBool;
 using ::android::hardware::configstore::V1_0::OptionalInt32;
 using ::android::hardware::configstore::V1_0::OptionalUInt32;
 using ::android::hardware::configstore::V1_0::OptionalInt64;
 using ::android::hardware::configstore::V1_0::OptionalUInt64;
 using ::android::hardware::configstore::V1_0::OptionalString;
+using ::android::hardware::configstore::V1_1::OptionalDisplayOrientation;
+
+static inline std::ostream& operator<<(std::ostream& os, DisplayOrientation orientation) {
+    os << ::android::hardware::configstore::V1_1::toString(orientation);
+    return os;
+}
 
 // a function to retrieve and cache the service handle
 // for a particular interface
@@ -141,6 +149,12 @@
     return get<OptionalString, I, func>(defValue);
 }
 
+template <typename I, android::hardware::Return<void> (I::*func)(
+                          std::function<void(const OptionalDisplayOrientation&)>)>
+DisplayOrientation getDisplayOrientation(DisplayOrientation defValue) {
+    return get<OptionalDisplayOrientation, I, func>(defValue);
+}
+
 }  // namespace configstore
 }  // namespace hardware
 }  // namespace android
diff --git a/confirmationui/1.0/default/service.cpp b/confirmationui/1.0/default/service.cpp
index 58ec66a..39f3f62 100644
--- a/confirmationui/1.0/default/service.cpp
+++ b/confirmationui/1.0/default/service.cpp
@@ -27,6 +27,7 @@
 using android::hardware::confirmationui::V1_0::implementation::ConfirmationUI;
 
 int main() {
+    ::android::hardware::configureRpcThreadpool(1, true /*willJoinThreadpool*/);
     auto confirmationui = new ConfirmationUI();
     auto status = confirmationui->registerAsService();
     if (status != android::OK) {
diff --git a/current.txt b/current.txt
index b3f2ff6..e519eb0 100644
--- a/current.txt
+++ b/current.txt
@@ -250,6 +250,7 @@
 c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
 
 # ABI preserving changes to HALs during Android P
+9e7a0b650d0e461ece2cfec0e1072abf8676f592b41a7fb48f01e88fc3c8f780 android.hardware.broadcastradio@1.0::types
 eaeb3e4f3237430a7fdc206bffdf844713f5682990b2d49ea24392e15b5d343f android.hardware.broadcastradio@2.0::ITunerCallback
 2804120c1f8522ad15feb7695fe5eece527d399b406c671ea99618194118c316 android.hardware.broadcastradio@2.0::types
 cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
@@ -258,10 +259,21 @@
 fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
 251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
 4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+190ea4898809de6cf379afe318f5fa9564686157b24d9a2d7f5698b0c977d8b2 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
+25892789b50eb673506b6c5a2cdab5d9aa428d41608aab10280cc898538b524a android.hardware.graphics.composer@2.1::IComposerClient
+e205dd30f5ff99445b706a901de8ebc46c379e9d7c1921d6a327ed2082cfa83d android.hardware.graphics.composer@2.1::types
+a46251718abfada458dc64c41ce94915757bf6c87cfa2d9e99cfb01fa8e32331 android.hardware.graphics.mapper@2.0::IMapper
+bd33ac23c57b4a07632691d2191bc2c93930f57e62f4ccf459748fdaa5c0f480 android.hardware.graphics.mapper@2.0::types
+ad8a28ca3a5549fb9bc24cf5f80ac8f660cc27be885210d76266780aa52ddb8d android.hardware.keymaster@3.0::types
 5804ca86611d72e5481f022b3a0c1b334217f2e4988dad25730c42af2d1f4d1c android.hardware.neuralnetworks@1.0::IDevice
 12e8dca4ab7d8aadd0ef8f1b438021938e2396139e85db2ed65783b08800aa52 android.hardware.neuralnetworks@1.0::IExecutionCallback
 86b77e06da756a76aa3685be88765852dd982a86d8c90b8b4fc1130ed4184c8f android.hardware.neuralnetworks@1.0::types
 d4840db8efabdf1e4b344fc981cd36e5fe81a39aff6e199f6d06c1c8da413efd android.hardware.radio@1.0::types
+f96cbc59dfe16c8d0c2a7e06db24d8738a6328b6e90f7b8e1640ea2b4600debd android.hardware.radio@1.1::ISap
+2d86929794795e5c70f4fdb5073485fd05835c9c6f496116687c3d9f32e6df3e android.hardware.radio@1.2::ISap
+905a4af79c8329b39d8b11b08f015137216bb078b427b6986f32884a04bc1bec android.hardware.tv.cec@1.0::types
+aebcd9ff2da05c9d4c439916f40dfd219ba7629919007cb981ebf150064b4f82 android.hardware.usb@1.1::IUsb
+e29fb1941b40a990676f8e9c676a38761defd890b81a9c034608eb7ba6496023 android.hardware.wifi@1.0::IWifiP2pIface
 b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
 
 # HALs released in Android P
@@ -272,7 +284,7 @@
 d5de64e66b95f135dd42492250a309134b8227203ef3524440798c66b6f5a392 android.hardware.audio@4.0::IStreamIn
 888ac906461327fa0bd93854d5109be8c292a33afdb467164826970a8bd5b789 android.hardware.audio@4.0::IStreamOut
 15f6ae78e73344c8e7d68847ef03caec64fcd9f951bbcf59957d1712c247fcff android.hardware.audio@4.0::IStreamOutCallback
-e8abfc73b7f3c2095ea4fad83b5f42bced4315de2abcc3199376af880dac451b android.hardware.audio@4.0::types
+61f0eaa4d08547d039e9b1dd7c82abe2c004286d1b9b8153c2491ff46a8a63ca android.hardware.audio@4.0::types
 5d47a2ad2c136b8aba067dd45bb10d0ad390dd76340764154f580658f98f4fe6 android.hardware.audio.common@4.0::types
 b04b6b364938b80008e61fa2e318bc299622433e57c2e1f6cfba332a3f6e3f15 android.hardware.audio.effect@4.0::IAcousticEchoCancelerEffect
 1c17d4ece5c8ba3f7a646a305ee0dd109b0d51372e1bd585812e513cd40e1852 android.hardware.audio.effect@4.0::IAutomaticGainControlEffect
@@ -290,16 +302,6 @@
 fe28829dab10d171783b79ac9cc45412739f8ff275e90228d7c6370ef189b859 android.hardware.audio.effect@4.0::IVisualizerEffect
 21c8a702579356480236c6851b5b2c16b9bd369ce12bdd6ffdc4626a89f34f73  android.hardware.audio.effect@4.0::types
 42a06dc288f61b0690580f3d37b30b663c31d74d50bb58d0772386b550d5faab android.hardware.authsecret@1.0::IAuthSecret
-a0f93c768c353cecee6237fe479bce47404eb10b629fafe07e32a054fd67f2af android.hardware.automotive.audiocontrol@1.0::IAudioControl
-ca515ff4b63c80cf5ad7b3395c997c57d6c56157361f6c367d1c96f23cc4860a android.hardware.automotive.audiocontrol@1.0::types
-f2904a4c108ad1b93eb2fa4e43b82bd01ce1ff26156316e49d1d9fc80dfecaad android.hardware.automotive.evs@1.0::IEvsCamera
-94cba6ad04c83aa840de2ed52b74ba2126a26dd960225e61ac36703315279a80 android.hardware.automotive.evs@1.0::IEvsCameraStream
-5ea36fb043d9e3b413219de3dfd7b046b48af4fda39f167f3528652e986cb76d android.hardware.automotive.evs@1.0::IEvsDisplay
-14ef8e993a4a7c899b19bb5e39b5b0cafd28312ea2b127e35b3be8f08e23fe8e android.hardware.automotive.evs@1.0::IEvsEnumerator
-3b17c1fdfc389e0abe626c37054954b07201127d890c2bc05d47613ec1f4de4f android.hardware.automotive.evs@1.0::types
-b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
-7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
-9cf9690f559f8425fa86e409137a42435ca225505152f03736ac8f3773ef4f89 android.hardware.automotive.vehicle@2.0::types
 32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
 ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
 27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
@@ -313,6 +315,8 @@
 812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
 cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
 f9278c8beb9d42d96e26d73ecabe1dff1d7e2fb301ab7f737d93e5ffae8d3312 android.hardware.camera.metadata@3.3::types
+f858091b10f7d5927be60573c06df4805275d37226bbb41a732190bfb81457ec android.hardware.configstore@1.1::ISurfaceFlingerConfigs
+5b0fb9842f8b0eb3730b93c30a7925290ab44763ab86bb493bfa58d0f2eeb369 android.hardware.configstore@1.1::types
 1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
 6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
 a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
@@ -326,14 +330,15 @@
 1a07d1383e847c3deb696ec7a2c9e33b9683772945660448a010b18063da67a4 android.hardware.gnss@1.1::IGnssMeasurement
 83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback
 0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types
+7d2cef99c838fb58038de8bbfd3cdb76ff4797241987077721715297f8d45e34 android.hardware.graphics.common@1.1::types # b/78135149
 d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer
-18eff12102db47b03a5fa906f8d4fd9018f0fb9236c663d457b8eac8d57c2937 android.hardware.graphics.composer@2.2::IComposerClient
+a2f183f7fcc79aabedaef11095ab223aac0ed5ef984d850893872515e7f560c7 android.hardware.graphics.composer@2.2::IComposerClient
 dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper
 675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth
 434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback
 c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types
-a6cf986593c6ad15fe2ae3a1995d2cae233500bc32c055912a42723bdc076868 android.hardware.keymaster@4.0::IKeymasterDevice
-e15ebdf1e0a326ff5b8a59668d4d8cd3852bd88388eae91de13f5f7e1af50ed1 android.hardware.keymaster@4.0::types
+201f9723353fdbd40bf3705537fb7e015e4c399879425e68688fe0f43606ea4d android.hardware.keymaster@4.0::IKeymasterDevice
+1b7d2090c0a28b229d37c4b96160796b1f0d703950ac6ccc163fccd280830503 android.hardware.keymaster@4.0::types
 6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor
 b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager
 4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection
diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp
index bbc4940..bbf1cd3 100644
--- a/gnss/1.1/default/Gnss.cpp
+++ b/gnss/1.1/default/Gnss.cpp
@@ -227,7 +227,9 @@
         getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
         getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
         getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
-        getSvInfo(30, GnssConstellationType::GPS, 20.5, 11.5, 116.0),
+        getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
+        getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
+        getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
         getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
 
     GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 8928a5a..46d61e5 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -191,7 +191,7 @@
 void GnssHalTest::StartAndCheckLocations(int count) {
     const int kMinIntervalMsec = 500;
     const int kLocationTimeoutSubsequentSec = 2;
-    const bool kLowPowerMode = true;
+    const bool kLowPowerMode = false;
 
     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
 
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index 8f4691e..cce46f1 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -84,15 +84,15 @@
 }
 
 /*
- * FindStrongFrequentSource:
+ * FindStrongFrequentNonGpsSource:
  *
- * Search through a GnssSvStatus list for the strongest satellite observed enough times
+ * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
  *
  * returns the strongest source,
  *         or a source with constellation == UNKNOWN if none are found sufficient times
  */
 
-IGnssConfiguration::BlacklistedSource FindStrongFrequentSource(
+IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource(
     const list<IGnssCallback::GnssSvStatus> list_gnss_sv_status, const int min_observations) {
     struct ComparableBlacklistedSource {
         IGnssConfiguration::BlacklistedSource id;
@@ -113,7 +113,8 @@
     for (const auto& gnss_sv_status : list_gnss_sv_status) {
         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
-            if (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) {
+            if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+                (gnss_sv.constellation != GnssConstellationType::GPS)) {
                 ComparableBlacklistedSource source;
                 source.id.svid = gnss_sv.svid;
                 source.id.constellation = gnss_sv.constellation;
@@ -187,8 +188,12 @@
      */
 
     IGnssConfiguration::BlacklistedSource source_to_blacklist =
-        FindStrongFrequentSource(list_gnss_sv_status_, kLocationsToAwait - 1);
-    EXPECT_NE(source_to_blacklist.constellation, GnssConstellationType::UNKNOWN);
+        FindStrongFrequentNonGpsSource(list_gnss_sv_status_, kLocationsToAwait - 1);
+
+    if (source_to_blacklist.constellation == GnssConstellationType::UNKNOWN) {
+        // Cannot find a non-GPS satellite. Let the test pass.
+        return;
+    }
 
     // Stop locations, blacklist the common SV
     StopAndClearLocations();
diff --git a/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal b/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
index 87bb814..c59a16c 100644
--- a/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
+++ b/graphics/bufferqueue/1.0/IGraphicBufferProducer.hal
@@ -546,7 +546,7 @@
      */
     disconnect(
             int32_t api,
-            DisconnectMode mode /** = DisconnectMode::API */
+            DisconnectMode mode /* = DisconnectMode::API */
         ) generates (
             Status status
         );
diff --git a/graphics/common/1.1/types.hal b/graphics/common/1.1/types.hal
index 5dca482..423cf44 100644
--- a/graphics/common/1.1/types.hal
+++ b/graphics/common/1.1/types.hal
@@ -124,7 +124,7 @@
     /** buffer contains a complete mipmap hierarchy */
     GPU_MIPMAP_COMPLETE   = 1ULL << 26,
 
-    /** bits 27 and 32-47 must be zero and are reserved for future versions */
+    /* bits 27 and 32-47 must be zero and are reserved for future versions */
 };
 
 @export(name="android_dataspace_v1_1_t", value_prefix="HAL_DATASPACE_",
diff --git a/graphics/composer/2.1/IComposerClient.hal b/graphics/composer/2.1/IComposerClient.hal
index f2ff932..5ad46f0 100644
--- a/graphics/composer/2.1/IComposerClient.hal
+++ b/graphics/composer/2.1/IComposerClient.hal
@@ -1138,7 +1138,7 @@
         SET_LAYER_Z_ORDER                  = 0x40a << OPCODE_SHIFT,
         SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT = 0x40b << OPCODE_SHIFT,
 
-        /** 0x800 - 0xfff are reserved for vendor extensions */
-        /** 0x1000 - 0xffff are reserved */
+        /* 0x800 - 0xfff are reserved for vendor extensions */
+        /* 0x1000 - 0xffff are reserved */
     };
 };
diff --git a/graphics/composer/2.1/types.hal b/graphics/composer/2.1/types.hal
index 9f0dd8b..eb0a73b 100644
--- a/graphics/composer/2.1/types.hal
+++ b/graphics/composer/2.1/types.hal
@@ -18,15 +18,15 @@
 
 /** Return codes from all functions. */
 enum Error : int32_t {
-    NONE            = 0, /** no error */
-    BAD_CONFIG      = 1, /** invalid Config */
-    BAD_DISPLAY     = 2, /** invalid Display */
-    BAD_LAYER       = 3, /** invalid Layer */
-    BAD_PARAMETER   = 4, /** invalid width, height, etc. */
-    /** 5 is reserved */
-    NO_RESOURCES    = 6, /** temporary failure due to resource contention */
-    NOT_VALIDATED   = 7, /** validateDisplay has not been called */
-    UNSUPPORTED     = 8, /** permanent failure */
+    NONE            = 0, /* no error */
+    BAD_CONFIG      = 1, /* invalid Config */
+    BAD_DISPLAY     = 2, /* invalid Display */
+    BAD_LAYER       = 3, /* invalid Layer */
+    BAD_PARAMETER   = 4, /* invalid width, height, etc. */
+    /* 5 is reserved */
+    NO_RESOURCES    = 6, /* temporary failure due to resource contention */
+    NOT_VALIDATED   = 7, /* validateDisplay has not been called */
+    UNSUPPORTED     = 8, /* permanent failure */
 };
 
 typedef uint32_t Config;
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
index 77f06bb..6551a99 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -858,18 +858,20 @@
         return Error::Unsupported;
     }
 
-    uint32_t hwc1Config = 0;
-    auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
-    if (error != Error::None) {
-        return error;
-    }
+    if (mDevice.mHwc1MinorVersion >= 4) {
+        uint32_t hwc1Config = 0;
+        auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+        if (error != Error::None) {
+            return error;
+        }
 
-    ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
-    int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
-            mHwc1Id, hwc1Config);
-    if (intError != 0) {
-        ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
-        return Error::Unsupported;
+        ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+        int intError =
+            mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, hwc1Config);
+        if (intError != 0) {
+            ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+            return Error::Unsupported;
+        }
     }
 
     mActiveColorMode = mode;
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 8b8b530..747c66c 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -292,9 +292,16 @@
  * Test that IComposerClient::setColorMode succeeds for all color modes.
  */
 TEST_F(GraphicsComposerHidlTest, SetColorMode) {
+    std::unordered_set<ColorMode> validModes;
+    for (auto mode : hidl_enum_iterator<ColorMode>()) {
+        validModes.insert(mode);
+    }
+
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
     for (auto mode : modes) {
-        mComposerClient->setColorMode(mPrimaryDisplay, mode);
+        if (validModes.count(mode)) {
+            mComposerClient->setColorMode(mPrimaryDisplay, mode);
+        }
     }
 }
 
diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal
index a6665a1..d4a87e6 100644
--- a/graphics/composer/2.2/IComposerClient.hal
+++ b/graphics/composer/2.2/IComposerClient.hal
@@ -152,6 +152,11 @@
      * output of the display remains the same (subject to the note about protected
      * content in the description of setReadbackBuffer).
      *
+     * If the active configuration or color mode of this display has changed
+     * since a previous call to this function, it must be called again prior to
+     * setting a readback buffer such that the returned format and dataspace can
+     * be updated accordingly.
+     *
      * Parameters:
      * @param display - the display on which to create the layer.
      *
@@ -203,7 +208,13 @@
      *       must be non-NULL
      * @return error - is HWC2_ERROR_NONE or one of the following errors:
      *         BAD_DISPLAY - an invalid display handle was passed in
-     *         UNSUPPORTED if not supported on underlying HAL
+     *         NO_RESOURCES - the readback operation was successful, but
+     *                        resulted in a different validate result than would
+     *                        have occurred without readback
+     *         UNSUPPORTED - the readback operation was unsuccessful because of
+     *                       resource constraints, the presence of protected
+     *                       content, or other reasons; -1 must be returned for
+     *                       acquireFence
      *
      * See also:
      *   getReadbackBufferAttributes
@@ -344,7 +355,8 @@
      * Returns the render intents supported by the specified display and color
      * mode.
      *
-     * RenderIntent::COLORIMETRIC is always supported.
+     * For SDR color modes, RenderIntent::COLORIMETRIC must be supported. For
+     * HDR color modes, RenderIntent::TONE_MAP_COLORIMETRIC must be supported.
      *
      * @param display is the display to query.
      * @param mode is the color mode to query.
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 357c772..6a32071 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -45,6 +45,10 @@
     return client;
 }
 
+sp<V2_2::IComposerClient> ComposerClient_v2_2::getRaw() const {
+    return mClient_v2_2;
+}
+
 std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFrameMetadataKeys(
     Display display) {
     std::vector<IComposerClient::PerFrameMetadataKey> keys;
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 62ab83f..1c6d7ae 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -63,6 +63,8 @@
     ComposerClient_v2_2(const sp<IComposerClient>& client)
         : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
 
+    sp<V2_2::IComposerClient> getRaw() const;
+
     void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 4e41333..23bf558 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -78,6 +78,11 @@
         // explicitly disable vsync
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+            mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) {
+                mHasReadbackBuffer = tmpError == Error::NONE;
+            });
     }
 
     void TearDown() override {
@@ -96,6 +101,7 @@
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
+    bool mHasReadbackBuffer;
 
    private:
     Display waitForFirstDisplay() {
@@ -257,18 +263,44 @@
 }
 
 TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) {
-    mComposerClient->setReadbackBuffer(mPrimaryDisplay, nullptr, -1);
-}
+    if (!mHasReadbackBuffer) {
+        return;
+    }
 
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferFence) {
-    int32_t fence;
-    mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence);
-}
-
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferAttributes) {
     PixelFormat pixelFormat;
     Dataspace dataspace;
     mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
+    ASSERT_LT(static_cast<PixelFormat>(0), pixelFormat);
+    ASSERT_NE(Dataspace::UNKNOWN, dataspace);
+
+    IMapper::BufferDescriptorInfo info{};
+    Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
+    info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                      IComposerClient::Attribute::WIDTH);
+    info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                       IComposerClient::Attribute::HEIGHT);
+    info.layerCount = 1;
+    info.format = pixelFormat;
+    // BufferUsage::COMPOSER_OUTPUT is missing
+    info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+
+    std::unique_ptr<Gralloc> gralloc;
+    const native_handle_t* buffer;
+    ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
+    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+
+    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
+}
+
+TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) {
+    if (!mHasReadbackBuffer) {
+        return;
+    }
+
+    mComposerClient->getRaw()->getReadbackBufferFence(
+        mPrimaryDisplay, [&](const auto& tmpError, const auto&) {
+            ASSERT_EQ(Error::UNSUPPORTED, tmpError) << "readback buffer is active";
+        });
 }
 
 /**
@@ -315,9 +347,22 @@
     for (auto mode : modes) {
         std::vector<RenderIntent> intents =
             mComposerClient->getRenderIntents(mPrimaryDisplay, mode);
-        auto colorimetricIntent =
-            std::find(intents.cbegin(), intents.cend(), RenderIntent::COLORIMETRIC);
-        EXPECT_NE(intents.cend(), colorimetricIntent);
+
+        bool isHdr;
+        switch (mode) {
+            case ColorMode::BT2100_PQ:
+            case ColorMode::BT2100_HLG:
+                isHdr = true;
+                break;
+            default:
+                isHdr = false;
+                break;
+        }
+        RenderIntent requiredIntent =
+            isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC;
+
+        auto iter = std::find(intents.cbegin(), intents.cend(), requiredIntent);
+        EXPECT_NE(intents.cend(), iter);
     }
 }
 
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 4ee206b..4566135 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -155,7 +155,7 @@
      * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence, when non-empty, is a handle containing a file
+     * @param acquireFence when non-empty, is a handle containing a file
      *        descriptor referring to a sync fence object, which will be
      *        signaled when it is safe for the mapper to lock the buffer. If
      *        it is already safe to lock, acquireFence is empty.
@@ -191,7 +191,7 @@
      * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence, when non-empty, is a handle containing a file
+     * @param acquireFence when non-empty, is a handle containing a file
      *        descriptor referring to a sync fence object, which will be
      *        signaled when it is safe for the mapper to lock the buffer. If
      *        it is already safe to lock, acquireFence is empty.
diff --git a/graphics/mapper/2.0/types.hal b/graphics/mapper/2.0/types.hal
index e9b2f3a..2291f70 100644
--- a/graphics/mapper/2.0/types.hal
+++ b/graphics/mapper/2.0/types.hal
@@ -17,14 +17,14 @@
 package android.hardware.graphics.mapper@2.0;
 
 enum Error : int32_t {
-    NONE            = 0, /** no error */
-    BAD_DESCRIPTOR  = 1, /** invalid BufferDescriptor */
-    BAD_BUFFER      = 2, /** invalid buffer handle */
-    BAD_VALUE       = 3, /** invalid width, height, etc. */
+    NONE            = 0, /* no error */
+    BAD_DESCRIPTOR  = 1, /* invalid BufferDescriptor */
+    BAD_BUFFER      = 2, /* invalid buffer handle */
+    BAD_VALUE       = 3, /* invalid width, height, etc. */
     /* 4 is reserved */
-    NO_RESOURCES    = 5, /** temporary failure due to resource contention */
+    NO_RESOURCES    = 5, /* temporary failure due to resource contention */
     /* 6 is reserved */
-    UNSUPPORTED     = 7, /** permanent failure */
+    UNSUPPORTED     = 7, /* permanent failure */
 };
 
 /**
diff --git a/keymaster/3.0/types.hal b/keymaster/3.0/types.hal
index 6dad23e..72f7d47 100644
--- a/keymaster/3.0/types.hal
+++ b/keymaster/3.0/types.hal
@@ -17,17 +17,17 @@
 package android.hardware.keymaster@3.0;
 
 enum TagType : uint32_t {
-    INVALID = 0 << 28, /** Invalid type, used to designate a tag as uninitialized */
+    INVALID = 0 << 28, /* Invalid type, used to designate a tag as uninitialized */
     ENUM = 1 << 28,
-    ENUM_REP = 2 << 28, /** Repeatable enumeration value. */
+    ENUM_REP = 2 << 28, /* Repeatable enumeration value. */
     UINT = 3 << 28,
-    UINT_REP = 4 << 28, /** Repeatable integer value */
+    UINT_REP = 4 << 28, /* Repeatable integer value */
     ULONG = 5 << 28,
     DATE = 6 << 28,
     BOOL = 7 << 28,
     BIGNUM = 8 << 28,
     BYTES = 9 << 28,
-    ULONG_REP = 10 << 28, /** Repeatable long value */
+    ULONG_REP = 10 << 28, /* Repeatable long value */
 };
 
 enum Tag : uint32_t {
@@ -254,12 +254,12 @@
  * Possible purposes of a key (or pair).
  */
 enum KeyPurpose : uint32_t {
-    ENCRYPT = 0,    /** Usable with RSA, EC and AES keys. */
-    DECRYPT = 1,    /** Usable with RSA, EC and AES keys. */
-    SIGN = 2,       /** Usable with RSA, EC and HMAC keys. */
-    VERIFY = 3,     /** Usable with RSA, EC and HMAC keys. */
-    DERIVE_KEY = 4, /** Usable with EC keys. */
-    WRAP_KEY = 5,   /** Usable with wrapping keys. */
+    ENCRYPT = 0,    /* Usable with RSA, EC and AES keys. */
+    DECRYPT = 1,    /* Usable with RSA, EC and AES keys. */
+    SIGN = 2,       /* Usable with RSA, EC and HMAC keys. */
+    VERIFY = 3,     /* Usable with RSA, EC and HMAC keys. */
+    DERIVE_KEY = 4, /* Usable with EC keys. */
+    WRAP_KEY = 5,   /* Usable with wrapping keys. */
 };
 
 /**
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index aef81c7..74d13d8 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -20,46 +20,234 @@
 import android.hardware.keymaster@3.0::KeyFormat;
 
 /**
- * Keymaster device definition.  For thorough documentation see the implementer's reference, at
- * https://source.android.com/security/keystore/implementer-ref.html
+ * Keymaster device definition.
+ *
+ * == Features ==
+ *
+ * An IKeymasterDevice provides cryptographic services, including the following categories of
+ * operations:
+ *
+ * o   Key generation
+ * o   Import and export (public only) of asymmetric keys
+ * o   Import of raw symmetric keys
+ * o   Asymmetric encryption and decryption with appropriate padding modes
+ * o   Asymmetric signing and verification with digesting and appropriate padding modes
+ * o   Symmetric encryption and decryption in appropriate modes, including an AEAD mode
+ * o   Generation and verification of symmetric message authentication codes
+ * o   Attestation to the presence and configuration of asymmetric keys.
+ *
+ * Protocol elements, such as purpose, mode and padding, as well as access control constraints, must
+ * be specified by the caller when keys are generated or imported and must be permanently bound to
+ * the key, ensuring that the key cannot be used in any other way.
+ *
+ * In addition to the list above, IKeymasterDevice implementations must provide one more service
+ * which is not exposed as an API but used internally: Random number generation.  The random number
+ * generator must be high-quality and must be used for generation of keys, initialization vectors,
+ * random padding and other elements of secure protocols that require randomness.
+ *
+ * == Types of IKeymasterDevices ==
+ *
+ * All of the operations and storage of key material must occur in a secure environment.  Secure
+ * environments may be either:
+ *
+ * 1.  Isolated execution environments, such as a separate virtual machine, hypervisor or
+ *      purpose-built trusted execution environment like ARM TrustZone.  The isolated environment
+ *      must provide complete separation from the Android kernel and user space (collectively called
+ *      the "non-secure world", or NSW) so that nothing running in the NSW can observe or manipulate
+ *      the results of any computation in the isolated environment.  Isolated execution environments
+ *      are identified by the SecurityLevel TRUSTED_ENVIRONMENT.
+ *
+ * 2.  Completely separate, purpose-built and certified secure CPUs, called "StrongBox" devices.
+ *      Examples of StrongBox devices are embedded Secure Elements (eSE) or on-SoC secure processing
+ *      units (SPU).  StrongBox environments are identified by the SecurityLevel STRONGBOX.  To
+ *      qualify as a StrongBox, a device must meet the requirements specified in CDD 9.11.2.
+ *
+ * == Necessary Primitives ==
+ *
+ * All IKeymasterDevice implementations must provide support for the following:
+ *
+ * o   RSA
+ *
+ *      - TRUSTED_ENVIRONMENT IKeymasterDevices must support 2048, 3072 and 4096-bit keys.
+ *        STRONGBOX IKeymasterDevices must support 2048-bit keys.
+ *      - Public exponent F4 (2^16+1)
+ *      - Unpadded, RSASSA-PSS and RSASSA-PKCS1-v1_5 padding modes for RSA signing
+ *      - TRUSTED_ENVIRONMENT IKeymasterDevices must support MD5, SHA1, SHA-2 224, SHA-2 256, SHA-2
+ *        384 and SHA-2 512 digest modes for RSA signing.  STRONGBOX IKeymasterDevices must support
+ *        SHA-2 256.
+ *      - Unpadded, RSAES-OAEP and RSAES-PKCS1-v1_5 padding modes for RSA encryption.
+ *
+ * o   ECDSA
+ *
+ *      - TRUSTED_ENVIRONMENT IKeymasterDevices must support NIST curves P-224, P-256, P-384 and
+ *        P-521.  STRONGBOX IKeymasterDevices must support NIST curve P-256.
+ *      - TRUSTED_ENVIRONMENT IKeymasterDevices must support SHA1, SHA-2 224, SHA-2 256, SHA-2
+ *        384 and SHA-2 512 digest modes.  STRONGBOX IKeymasterDevices must support SHA-2 256.
+ *
+ * o   AES
+ *
+ *      - 128 and 256-bit keys
+ *      - CBC, CTR, ECB and GCM modes.  The GCM mode must not allow the use of tags smaller than 96
+ *        bits or nonce lengths other than 96 bits.
+ *      - CBC and ECB modes must support unpadded and PKCS7 padding modes.  With no padding CBC and
+ *        ECB-mode operations must fail with ErrorCode::INVALID_INPUT_LENGTH if the input isn't a
+ *        multiple of the AES block size.  With PKCS7 padding, GCM and CTR operations must fail with
+ *        ErrorCode::INCOMPATIBLE_PADDING_MODE.
+ *
+ * o   3DES
+ *
+ *      - 168-bit keys.
+ *      - CBC and ECB mode.
+
+ *      - CBC and ECB modes must support unpadded and PKCS7 padding modes.  With no padding CBC and
+ *        ECB-mode operations must fail with ErrorCode::INVALID_INPUT_LENGTH if the input isn't a
+ *        multiple of the DES block size.
+ *
+ * o   HMAC
+ *
+ *      - Any key size that is between 64 and 512 bits (inclusive) and a multiple of 8 must be
+ *        supported.  STRONGBOX IKeymasterDevices must not support keys larger than 512 bits.
+ *      - TRUSTED_ENVIRONMENT IKeymasterDevices must support MD-5, SHA1, SHA-2-224, SHA-2-256,
+ *        SHA-2-384 and SHA-2-512.  STRONGBOX IKeymasterDevices must support SHA-2-256.
+ *
+ * == Key Access Control ==
+ *
+ * Hardware-based keys that can never be extracted from the device don't provide much security if an
+ * attacker can use them at will (though they're more secure than keys which can be
+ * exfiltrated).  Therefore, IKeymasterDevice must enforce access controls.
+ *
+ * Access controls are defined as an "authorization list" of tag/value pairs.  Authorization tags
+ * are 32-bit integers from the Tag enum, and the values are a variety of types, defined in the
+ * TagType enum.  Some tags may be repeated to specify multiple values.  Whether a tag may be
+ * repeated is specified in the documentation for the tag and in the TagType.  When a key is created
+ * or imported, the caller specifies an authorization list.  The IKeymasterDevice must divide the
+ * caller-provided authorizations into two lists, those it enforces in hardware and those it does
+ * not.  These two lists are returned as the "hardwareEnforced" and "softwareEnforced" elements of
+ * the KeyCharacteristics struct.  The IKeymasterDevice must also add the following authorizations
+ * to the appropriate list:
+ *
+ * o    Tag::OS_VERSION, must be hardware-enforced.
+ * o    Tag::OS_PATCHLEVEL, must be hardware-enforced.
+ * o    Tag::VENDOR_PATCHLEVEL, must be hardware-enforced.
+ * o    Tag::BOOT_PATCHLEVEL, must be hardware-enforced.
+ * o    Tag::CREATION_DATETIME, must be software-enforced, unless the IKeymasterDevice has access to
+ *      a secure time service.
+ * o    Tag::ORIGIN, must be hardware-enforced.
+ *
+ * The IKeymasterDevice must accept arbitrary, unknown tags and return them in the softwareEnforced
+ * list.
+ *
+ * All authorization tags and their values, both hardwareEnforced and softwareEnforced, including
+ * unknown tags, must be cryptographically bound to the private/secret key material such that any
+ * modification of the portion of the key blob that contains the authorization list makes it
+ * impossible for the secure environment to obtain the private/secret key material.  The recommended
+ * approach to meet this requirement is to use the full set of authorization tags associated with a
+ * key as input to a secure key derivation function used to derive a key that is used to encrypt the
+ * private/secret key material.
+ *
+ * IKeymasterDevice implementations must place any tags they cannot fully and completely enforce in
+ * the softwareEnforced list.  For example, Tag::ORIGINATION_EXPIRE_DATETIME provides the date and
+ * time after which a key may not be used to encrypt or sign new messages.  Unless the
+ * IKeymasterDevice has access to a secure source of current date/time information, it is not
+ * possible for the IKeymasterDevice to enforce this tag.  An IKeymasterDevice implementation may
+ * not rely on the non-secure world's notion of time, because it could be controlled by an attacker.
+ * Similarly, it cannot rely on GPSr time, even if it has exclusive control of the GPSr, because
+ * that might be spoofed by attacker RF signals.
+ *
+ * It is recommended that IKeymasterDevices not enforce any tags they place in the softwareEnforced
+ * list.  The IKeymasterDevice caller must enforce them, and it is unnecessary to enforce them
+ * twice.
+ *
+ * Some tags must be enforced by the IKeymasterDevice.  See the detailed documentation on each Tag
+ * in types.hal.
+ *
+ * == Root of Trust Binding ==
+ *
+ * IKeymasterDevice keys must be bound to a root of trust, which is a bitstring that must be
+ * provided to the secure environment (by an unspecified, implementation-defined mechanism) during
+ * startup, preferably by the bootloader.  This bitstring must be cryptographically bound to every
+ * key managed by the IKeymasterDevice.  As above, the recommended mechanism for this cryptographic
+ * binding is to include the Root of Trust data in the input to the key derivation function used to
+ * derive a key that is used to encryp the private/secret key material.
+ *
+ * The root of trust consists of a bitstring that must be derived from the public key used by
+ * Verified Boot to verify the signature on the boot image and from the the lock state of the
+ * device.  If the public key is changed to allow a different system image to be used or if the lock
+ * state is changed, then all of the IKeymasterDevice-protected keys created by the previous system
+ * state must be unusable, unless the previous state is restored.  The goal is to increase the value
+ * of the software-enforced key access controls by making it impossible for an attacker-installed
+ * operating system to use IKeymasterDevice keys.
+ *
+ * == Version Binding ==
+ *
+ * All keys must also be bound to the operating system and patch level of the system image and the
+ * patch levels of the vendor image and boot image.  This ensures that an attacker who discovers a
+ * weakness in an old version of the software cannot roll a device back to the vulnerable version
+ * and use keys created with the newer version.  In addition, when a key with a given version and
+ * patch level is used on a device that has been upgraded to a newer version or patch level, the key
+ * must be upgraded (See IKeymasterDevice::upgradeKey()) before it can be used, and the previous
+ * version of the key must be invalidated.  In this way, as the device is upgraded, the keys will
+ * "ratchet" forward along with the device, but any reversion of the device to a previous release
+ * will cause the keys to be unusable.
+ *
+ * This version information must be associated with every key as a set of tag/value pairs in the
+ * hardwareEnforced authorization list.  Tag::OS_VERSION, Tag::OS_PATCHLEVEL,
+ * Tag::VENDOR_PATCHLEVEL, and Tag::BOOT_PATCHLEVEL must be cryptographically bound to every
+ * IKeymasterDevice key, as described in the Key Access Control section above.
  */
+
 interface IKeymasterDevice {
 
     /**
-     * Returns information about the underlying Keymaster hardware.
+     * Returns information about the underlying IKeymasterDevice hardware.
      *
-     * @return security level of the Keymaster implementation accessed through this HAL.
+     * @return security level of the IKeymasterDevice implementation accessed through this HAL.
      *
-     * @return keymasterName is the name of the Keymaster implementation.
+     * @return keymasterName is the name of the IKeymasterDevice implementation.
      *
-     * @return keymasterAuthorName is the name of the author of the Keymaster implementation
+     * @return keymasterAuthorName is the name of the author of the IKeymasterDevice implementation
      *         (organization name, not individual).
      */
     getHardwareInfo()
         generates (SecurityLevel securityLevel, string keymasterName, string keymasterAuthorName);
 
     /**
-     * Start the creation of an HMAC key, shared with another Keymaster implementation.  Any device
-     * with a StrongBox Keymaster has two Keymaster instances, because there must be a TEE Keymaster
-     * as well.  The HMAC key used to MAC and verify authentication tokens must be shared between
-     * TEE and StrongBox so they can each validate tokens produced by the other.  This method is the
-     * first step in the process for for agreeing on a shared key.  It is called by Keystore during
-     * startup if and only if Keystore loads multiple Keymaster HALs.  Keystore calls it on each of
-     * the HAL instances and collects the results in preparation for the second step.
+     * Start the creation of an HMAC key, shared with another IKeymasterDevice implementation.  Any
+     * device with a StrongBox IKeymasterDevice has two IKeymasterDevice instances, because there
+     * must be a TEE Keymaster as well.  The HMAC key used to MAC and verify authentication tokens
+     * (HardwareAuthToken, VerificationToken and ConfirmationToken all use this HMAC key) must be
+     * shared between TEE and StrongBox so they can each validate tokens produced by the other.
+     * This method is the first step in the process for agreeing on a shared key.  It is called by
+     * Android during startup.  The system calls it on each of the HAL instances and collects the
+     * results in preparation for the second step.
+     *
+     * @return error ErrorCode::OK on success, ErrorCode::UNIMPLEMENTED if HMAC agreement is not
+     *         implemented (note that all 4.0::IKeymasterDevice HALS must implement HMAC agreement,
+     *         regardless of whether or not the HAL will be used on a device with StrongBox), or
+     *         ErrorCode::UNKNOWN_ERROR if the parameters cannot be returned.
+     *
+     * @return params The HmacSharingParameters to use.  As specified in the HmacSharingParameters
+     *         documentation in types.hal, the seed must contain the same value in every invocation
+     *         of the method on a given device, and the nonce must return the same value for every
+     *         invocation during a boot session.
      */
     getHmacSharingParameters() generates (ErrorCode error, HmacSharingParameters params);
 
     /**
-     * Complete the creation of an HMAC key, shared with another Keymaster implementation.  Any
-     * device with a StrongBox Keymaster has two Keymasters instances, because there must be a TEE
-     * Keymaster as well.  The HMAC key used to MAC and verify authentication tokens must be shared
-     * between TEE and StrongBox so they can each validate tokens produced by the other.  This
-     * method is the second and final step in the process for agreeing on a shared key.  It is
-     * called by Keystore during startup if and only if Keystore loads multiple Keymaster HALs.
-     * Keystore calls it on each of the HAL instances, and sends to it all of the
-     * HmacSharingParameters returned by all HALs.
+     * Complete the creation of an HMAC key, shared with another IKeymasterDevice implementation.
+     * Any device with a StrongBox IKeymasterDevice has two IKeymasterDevice instances, because
+     * there must be a TEE IKeymasterDevice as well.  The HMAC key used to MAC and verify
+     * authentication tokens must be shared between TEE and StrongBox so they can each validate
+     * tokens produced by the other.  This method is the second and final step in the process for
+     * agreeing on a shared key.  It is called by Android during startup.  The system calls it on
+     * each of the HAL instances, and sends to it all of the HmacSharingParameters returned by all
+     * HALs.
      *
-     * This method computes the shared 32-byte HMAC ``H'' as follows (all Keymaster instances
+     * To ensure consistent ordering of the HmacSharingParameters, the caller must sort the
+     * parameters lexicographically.  See the support/keymaster_utils.cpp for an operator< that
+     * defines the appropriate ordering.
+     *
+     * This method computes the shared 32-byte HMAC ``H'' as follows (all IKeymasterDevice instances
      * perform the same computation to arrive at the same result):
      *
      *     H = CKDF(key = K,
@@ -70,25 +258,27 @@
      *
      *     ``CKDF'' is the standard AES-CMAC KDF from NIST SP 800-108 in counter mode (see Section
      *           5.1 of the referenced publication).  ``key'', ``context'', and ``label'' are
-     *           defined in the standard.  The counter is prefixed, as shown in the construction on
-     *           page 12 of the standard.  The label string is UTF-8 encoded.
+     *           defined in the standard.  The counter is prefixed and length L appended, as shown
+     *           in the construction on page 12 of the standard.  The label string is UTF-8 encoded.
      *
      *     ``K'' is a pre-established shared secret, set up during factory reset.  The mechanism for
      *           establishing this shared secret is implementation-defined, but see below for a
-     *           recommended approach, which assumes that the TEE Keymaster does not have storage
-     *           available to it, but the StrongBox Keymaster does.
+     *           recommended approach, which assumes that the TEE IKeymasterDevice does not have
+     *           storage available to it, but the StrongBox IKeymasterDevice does.
      *
-     *           <b>CRITICAL SECURITY REQUIREMENT</b>: All keys created by a Keymaster instance must
+     *           CRITICAL SECURITY REQUIREMENT: All keys created by a IKeymasterDevice instance must
      *           be cryptographically bound to the value of K, such that establishing a new K
      *           permanently destroys them.
      *
      *     ``||'' represents concatenation.
      *
      *     ``Pi'' is the i'th HmacSharingParameters value in the params vector.  Note that at
-     *           present only two Keymaster implementations are supported, but this mechanism
+     *           present only two IKeymasterDevice implementations are supported, but this mechanism
      *           extends without modification to any number of implementations.  Encoding of an
      *           HmacSharingParameters is the concatenation of its two fields, i.e. seed || nonce.
      *
+     * Note that the label "KeymasterSharedMac" is the 18-byte UTF-8 encoding of the string.
+     *
      * Process for establishing K:
      *
      *     Any method of securely establishing K that ensures that an attacker cannot obtain or
@@ -98,19 +288,19 @@
      *     have secure persistent storage.  This model was chosen because StrongBox has secure
      *     persistent storage (by definition), but the TEE may not.  The instance without storage is
      *     assumed to be able to derive a unique hardware-bound key (HBK) which is used only for
-     *     this purpose, and is not derivable outside of the secure environment..
+     *     this purpose, and is not derivable outside the secure environment.
      *
-     *     In what follows, T is the Keymaster instance without storage, S is the Keymaster instance
-     *     with storage:
+     *     In what follows, T is the IKeymasterDevice instance without storage, S is the
+     *     IKeymasterDevice instance with storage:
      *
-     *     1. T generates an ephemeral EC P-256 key pair K1
+     *     1. T generates an ephemeral EC P-256 key pair K1.
      *     2. T sends K1_pub to S, signed with T's attestation key.
      *     3. S validates the signature on K1_pub.
      *     4. S generates an ephemeral EC P-256 key pair K2.
      *     5. S sends {K1_pub, K2_pub}, to T, signed with S's attestation key.
-     *     6. T validates the signature on {K1_pub, K2_pub}
+     *     6. T validates the signature on {K1_pub, K2_pub}.
      *     7. T uses {K1_priv, K2_pub} with ECDH to compute session secret Q.
-     *     8. T generates a random seed S
+     *     8. T generates a random seed S.
      *     9. T computes K = KDF(HBK, S), where KDF is some secure key derivation function.
      *     10. T sends M = AES-GCM-ENCRYPT(Q, {S || K}) to S.
      *     10. S uses {K2_priv, K1_pub} with ECDH to compute session secret Q.
@@ -121,40 +311,54 @@
      *     T receives the computeSharedHmac call, it uses the seed provided by S to compute K.  S,
      *     of course, has K stored.
      *
-     * @param params The HmacSharingParameters data returned by all Keymaster instances when
+     * @param params The HmacSharingParameters data returned by all IKeymasterDevice instances when
      *        getHmacSharingParameters was called.
      *
-     * @return sharingCheck A 32-byte value used to verify that all Keymaster instances have
+     * @return error ErrorCode::OK in the event that there is no error.  ErrorCode::INVALID_ARGUMENT
+     *         if one of the provided parameters is not the value returned by the prior call to
+     *         getHmacParameters().
+     *
+     * @return sharingCheck A 32-byte value used to verify that all IKeymasterDevice instances have
      *         computed the same shared HMAC key.  The sharingCheck value is computed as follows:
      *
      *             sharingCheck = HMAC(H, "Keymaster HMAC Verification")
      *
-     *         The string is UTF-8 encoded.  If the returned values of all Keymaster instances don't
-     *         match, Keystore will assume that HMAC agreement failed.
+     *         The string is UTF-8 encoded, 27 bytes in length.  If the returned values of all
+     *         IKeymasterDevice instances don't match, clients must assume that HMAC agreement
+     *         failed.
      */
     computeSharedHmac(vec<HmacSharingParameters> params)
         generates (ErrorCode error, vec<uint8_t> sharingCheck);
 
     /**
-     * Verify authorizations for another Keymaster instance.
+     * Verify authorizations for another IKeymasterDevice instance.
      *
-     * On systems with both a StrongBox and a TEE Keymaster instance it is sometimes useful to ask
-     * the TEE Keymaster to verify authorizations for a key hosted in StrongBox.
+     * On systems with both a StrongBox and a TEE IKeymasterDevice instance it is sometimes useful
+     * to ask the TEE IKeymasterDevice to verify authorizations for a key hosted in StrongBox.
      *
      * For every StrongBox operation, Keystore is required to call this method on the TEE Keymaster,
      * passing in the StrongBox key's hardwareEnforced authorization list and the operation handle
-     * returned by StrongBox begin().  The TEE Keymaster must validate all of the authorizations it
-     * can and return those it validated in the VerificationToken.  If it cannot verify any, the
-     * parametersVerified field of the VerificationToken must be empty.  Keystore must then pass the
-     * VerificationToken to the subsequent invocations of StrongBox update() and finish().
+     * returned by StrongBox begin().  The TEE IKeymasterDevice must validate all of the
+     * authorizations it can and return those it validated in the VerificationToken.  If it cannot
+     * verify any, the parametersVerified field of the VerificationToken must be empty.  Keystore
+     * must then pass the VerificationToken to the subsequent invocations of StrongBox update() and
+     * finish().
      *
      * StrongBox implementations must return ErrorCode::UNIMPLEMENTED.
      *
      * @param operationHandle the operation handle returned by StrongBox Keymaster's begin().
      *
-     * @param parametersToVerify Set of authorizations to verify.
+     * @param parametersToVerify Set of authorizations to verify.  The caller may provide an empty
+     *        vector if the only required information is the TEE timestamp.
      *
      * @param authToken A HardwareAuthToken if needed to authorize key usage.
+     *
+     * @return error ErrorCode::OK on success or ErrorCode::UNIMPLEMENTED if the IKeymasterDevice is
+     *         a StrongBox.  If the IKeymasterDevice cannot verify one or more elements of
+     *         parametersToVerify it must not return an error code, but just omit the unverified
+     *         parameter from the VerificationToken.
+     *
+     * @return token the verification token.  See VerificationToken in types.hal for details.
      */
     verifyAuthorization(uint64_t operationHandle, vec<KeyParameter> parametersToVerify,
                         HardwareAuthToken authToken)
@@ -162,53 +366,143 @@
 
 
     /**
-     * Adds entropy to the RNG used by Keymaster.  Entropy added through this method is guaranteed
-     * not to be the only source of entropy used, and the mixing function is required to be secure,
-     * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
-     * predict (or control), then the RNG output is indistinguishable from random.  Thus, if the
-     * entropy from any source is good, the output must be good.
+     * Adds entropy to the RNG used by Keymaster.  Entropy added through this method must not be the
+     * only source of entropy used, and a secure mixing function must be used to mix the entropy
+     * provided by this method with internally-generated entropy.  The mixing function must be
+     * secure in the sense that if any one of the mixing function inputs is provided with any data
+     * the attacker cannot predict (or control), then the output of the seeded CRNG is
+     * indistinguishable from random.  Thus, if the entropy from any source is good, the output must
+     * be good.
      *
-     * @param data Bytes to be mixed into the RNG.
+     * @param data Bytes to be mixed into the CRNG seed.  The caller must not provide more than 2
+     *        KiB of data per invocation.
      *
-     * @return error See the ErrorCode enum in types.hal.
+     * @return error ErrorCode::OK on success; ErrorCode::INVALID_INPUT_LENGTH if the caller
+     *         provides more than 2 KiB of data.
      */
     addRngEntropy(vec<uint8_t> data) generates (ErrorCode error);
 
     /**
-     * Generates a key, or key pair, returning a key blob and a description of the key.
+     * Generates a new cryptographic key, specifying associated parameters, which must be
+     * cryptographically bound to the key.  IKeymasterDevice implementations must disallow any use
+     * of a key in any way inconsistent with the authorizations specified at generation time.  With
+     * respect to parameters that the secure environment cannot enforce, the secure envionment's
+     * obligation is limited to ensuring that the unenforceable parameters associated with the key
+     * cannot be modified, so that every call to getKeyCharacteristics returns the original
+     * values.  In addition, the characteristics returned by generateKey places parameters correctly
+     * in the hardware-enforced and software-enforced lists.  See getKeyCharacteristics for more
+     * details.
      *
-     * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided
-     *        in params.  See Tag in types.hal for the full list.
+     * In addition to the parameters provided, generateKey must add the following to the returned
+     * characteristics.
      *
-     * @return error See the ErrorCode enum in types.hal.
+     * o Tag::ORIGIN with the value KeyOrigin::GENERATED.
      *
-     * @return keyBlob Opaque, encrypted descriptor of the generated key.  A recommended
-     *        implementation strategy is to include an encrypted copy of the key material, wrapped
-     *        in a key unavailable outside secure hardware.
+     * o Tag::BLOB_USAGE_REQUIREMENTS with the appropriate value (see KeyBlobUsageRequirements in
+     *   types.hal).
      *
-     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristis in
-     *         types.hal.
+     * o Tag::CREATION_DATETIME with the appropriate value.  Note that it is expected that this will
+     *   generally be added by the HAL, not by the secure environment, and that it will be in the
+     *   software-enforced list.  It must be cryptographically bound to the key, like all tags.
+     *
+     * o Tag::OS_VERSION, Tag::OS_PATCHLEVEL, Tag::VENDOR_PATCHLEVEL and Tag::BOOT_PATCHLEVEL with
+     *   appropriate values.
+     *
+     * The parameters provided to generateKey depend on the type of key being generated.  This
+     * section summarizes the necessary and optional tags for each type of key.  Tag::ALGORITHM is
+     * always necessary, to specify the type.
+     *
+     * == RSA Keys ==
+     *
+     * The following parameters are required to generate an RSA key:
+     *
+     * o Tag::Key_SIZE specifies the size of the public modulus, in bits.  If omitted, generateKey
+     *   must return ErrorCode::UNSUPPORTED_KEY_SIZE.  Required values for TEE IKeymasterDevice
+     *   implementations are 1024, 2048, 3072 and 4096.  StrongBox IKeymasterDevice implementations
+     *   must support 2048.
+     *
+     * o Tag::RSA_PUBLIC_EXPONENT specifies the RSA public exponent value.  If omitted, generateKey
+     *   must return ErrorCode::INVALID_ARGUMENT.  The values 3 and 65537 must be supported.  It is
+     *   recommended to support all prime values up to 2^64.  If provided with a non-prime value,
+     *   generateKey must return ErrorCode::INVALID_ARGUMENT.
+     *
+     * The following parameters are not necessary to generate a usable RSA key, but generateKey must
+     * not return an error if they are omitted:
+     *
+     * o Tag::PURPOSE specifies allowed purposes.  All KeyPurpose values (see types.hal) must be
+     *   supported for RSA keys.
+     *
+     * o Tag::DIGEST specifies digest algorithms that may be used with the new key.  TEE
+     *   IKeymasterDevice implementatiosn must support all Digest values (see types.hal) for RSA
+     *   keys.  StrongBox IKeymasterDevice implementations must support SHA_2_256.
+     *
+     * o Tag::PADDING specifies the padding modes that may be used with the new
+     *   key.  IKeymasterDevice implementations must support PaddingMode::NONE,
+     *   PaddingMode::RSA_OAEP, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
+     *   PaddingMode::RSA_PKCS1_1_5_SIGN for RSA keys.
+     *
+     * == ECDSA Keys ==
+     *
+     * Either Tag::KEY_SIZE or Tag::EC_CURVE must be provided to generate an ECDSA key.  If neither
+     * is provided, generateKey must return ErrorCode::UNSUPPORTED_KEY_SIZE.  If Tag::KEY_SIZE is
+     * provided, the possible values are 224, 256, 384 and 521, and must be mapped to Tag::EC_CURVE
+     * values P_224, P_256, P_384 and P_521, respectively.  TEE IKeymasterDevice implementations
+     * must support all curves.  StrongBox implementations must support P_256.
+     *
+     * == AES Keys ==
+     *
+     * Only Tag::KEY_SIZE is required to generate an AES key.  If omitted, generateKey must return
+     * ErrorCode::UNSUPPORTED_KEY_SIZE.  128 and 256-bit key sizes must be supported.
+     *
+     * If Tag::BLOCK_MODE is specified with value BlockMode::GCM, then the caller must also provide
+     * Tag::MIN_MAC_LENGTH.  If omitted, generateKey must return ErrorCode::MISSING_MIN_MAC_LENGTH.
+     *
+     *
+     * @param keyParams Key generation parameters are defined as IKeymasterDevice tag/value pairs,
+     *        provided in params.  See above for detailed specifications of which tags are required
+     *        for which types of keys.
+     *
+     * @return keyBlob Opaque descriptor of the generated key.  The recommended implementation
+     *         strategy is to include an encrypted copy of the key material, wrapped in a key
+     *         unavailable outside secure hardware.
+     *
+     * @return keyCharacteristics Description of the generated key.  See the getKeyCharacteristics
+     *         method below.
      */
     generateKey(vec<KeyParameter> keyParams)
         generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
 
     /**
-     * Imports a key, or key pair, returning a key blob and/or a description of the key.
+     * Imports key material into an IKeymasterDevice.  Key definition parameters and return values
+     * are the same as for generateKey, with the following exceptions:
      *
-     * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided
-     *        in params.  See Tag for the full list.
+     * o Tag::KEY_SIZE is not necessary in the input parameters.  If not provided, the
+     *   IKeymasterDevice must deduce the value from the provided key material and add the tag and
+     *   value to the key characteristics.  If Tag::KEY_SIZE is provided, the IKeymasterDevice must
+     *   validate it against the key material.  In the event of a mismatch, importKey must return
+     *   ErrorCode::IMPORT_PARAMETER_MISMATCH.
      *
-     * @param keyFormat The format of the key material to import.
+     * o Tag::RSA_PUBLIC_EXPONENT (for RSA keys only) is not necessary in the input parameters.  If
+     *   not provided, the IKeymasterDevice must deduce the value from the provided key material and
+     *   add the tag and value to the key characteristics.  If Tag::RSA_PUBLIC_EXPONENT is provided,
+     *   the IKeymasterDevice must validate it against the key material.  In the event of a
+     *   mismatch, importKey must return ErrorCode::IMPORT_PARAMETER_MISMATCH.
+     *
+     * o Tag::ORIGIN (returned in keyCharacteristics) must have the value KeyOrigin::IMPORTED.
+     *
+     * @param keyParams Key generation parameters are defined as IKeymasterDevice tag/value pairs,
+     *        provided in params.
+     *
+     * @param keyFormat The format of the key material to import.  See KeyFormat in types.hal.
      *
      * @pram keyData The key material to import, in the format specifed in keyFormat.
      *
-     * @return error See the ErrorCode enum.
+     * @return keyBlob Opaque descriptor of the imported key.  The recommended implementation
+     *         strategy is to include an encrypted copy of the key material, wrapped in a key
+     *         unavailable outside secure hardware.
      *
-     * @return keyBlob Opaque, encrypted descriptor of the generated key, which will generally
-     *         contain a copy of the key material, wrapped in a key unavailable outside secure
-     *         hardware.
-     *
-     * @return keyCharacteristics Decription of the generated key.
+     * @return keyCharacteristics Decription of the generated key.  See the getKeyCharacteristics
+     *         method below.
      */
     importKey(vec<KeyParameter> keyParams, KeyFormat keyFormat, vec<uint8_t> keyData)
         generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
@@ -241,10 +535,10 @@
      *     o keyParams is the characteristics of the key to be imported (as with generateKey or
      *       importKey).  If the secure import is successful, these characteristics must be
      *       associated with the key exactly as if the key material had been insecurely imported
-     *       with the @3.0::IKeymasterDevice::importKey.
+     *       with the @3.0::IKeymasterDevice::importKey.  See attestKey() for documentation of the
+     *       AuthorizationList schema.
      *     o encryptedTransportKey is a 256-bit AES key, XORed with a masking key and then encrypted
-     *       in RSA-OAEP mode (SHA-256 digest, SHA-1 MGF1 digest) with the wrapping key specified by
-     *       wrappingKeyBlob.
+     *       with the wrapping key specified by wrappingKeyBlob.
      *     o keyDescription is a KeyDescription, above.
      *     o encryptedKey is the key material of the key to be imported, in format keyFormat, and
      *       encrypted with encryptedEphemeralKey in AES-GCM mode, with the DER-encoded
@@ -266,10 +560,7 @@
      *        that the origin tag should be set to SECURELY_IMPORTED.
      *
      * @param wrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey().
-     *        This key must have been created with Purpose::WRAP_KEY, and must be a key algorithm
-     *        that supports encryption and must be at least as strong (in key size) as the key to be
-     *        imported (per NIST key length recommendations: 112 bits symmetric is equivalent to
-     *        2048-bit RSA or 224-bit EC, 128 bits symmetric ~ 3072-bit RSA or 256-bit EC, etc.).
+     *        This key must have been created with Purpose::WRAP_KEY.
      *
      * @param maskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
      *        structure.
@@ -291,8 +582,6 @@
      *        If the wrappedKeyData does not contain such a tag and value, this argument must be
      *        ignored.
      *
-     * @return error See the ErrorCode enum.
-     *
      * @return keyBlob Opaque descriptor of the imported key.  It is recommended that the keyBlob
      *         contain a copy of the key material, wrapped in a key unavailable outside secure
      *         hardware.
@@ -303,10 +592,18 @@
         generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
 
     /**
-     * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
-     * must fully validate the integrity of the key).
+     * Returns parameters associated with the provided key, divided into two sets: hardware-enforced
+     * and software-enforced.  The description here applies equally to the key characteristics lists
+     * returned by generateKey, importKey and importWrappedKey.  The characteristics returned by
+     * this method completely describe the type and usage of the specified key.
      *
-     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
+     * The rule that IKeymasterDevice implementations must use for deciding whether a given tag
+     * belongs in the hardware-enforced or software-enforced list is that if the meaning of the tag
+     * is fully assured by secure hardware, it is hardware enforced.  Otherwise, it's software
+     * enforced.
+     *
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey, importKey or importWrappedKey.
      *
      * @param clientId An opaque byte string identifying the client.  This value must match the
      *        Tag::APPLICATION_ID data provided during key generation/import.  Without the correct
@@ -318,9 +615,7 @@
      *        value, it must be computationally infeasible for the secure hardware to obtain the key
      *        material.
      *
-     * @return error See the ErrorCode enum in types.hal.
-     *
-     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis in
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristics in
      *         types.hal.
      */
     getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
@@ -344,8 +639,6 @@
      *        value, it must be computationally infeasible for the secure hardware to obtain the key
      *        material.
      *
-     * @return error See the ErrorCode enum in types.hal.
-     *
      * @return keyMaterial The public key material in PKCS#8 format.
      */
     exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
@@ -353,56 +646,190 @@
 
     /**
      * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in
-     * Keymaster.  The certificate must contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and
-     * value defined in:
+     * Keymaster.
      *
-     *     https://developer.android.com/training/articles/security-key-attestation.html.
+     * The certificates in the chain must be ordered such that each certificate is signed by the
+     * subsequent one, up to the root which must be self-signed.  The first certificate in the chain
+     * signs the public key info of the attested key and must contain the following entries (see RFC
+     * 5280 for details on each):
+     *
+     * o version -- with value 2
+     *
+     * o serialNumber -- with value 1 (same value for all keys)
+     *
+     * o signature -- contains an the AlgorithmIdentifier of the algorithm used to sign, must be
+     *   ECDSA for EC keys, RSA for RSA keys.
+     *
+     * o issuer -- must contain the same value as the Subject field of the next certificate.
+     *
+     * o validity -- SEQUENCE of two dates, containing the values of Tag::ACTIVE_DATETIME and
+     *   Tag::USAGE_EXPIRE_DATETIME.  The tag values are in milliseconds since Jan 1, 1970; see RFD
+     *   5280 for the correct representation in certificates.  If Tag::ACTIVE_DATETIME is not
+     *   present in the key, the IKeymasterDevice must use the value of Tag::CREATION_DATETIME.  If
+     *   Tag::USAGE_EXPIRE_DATETIME is not present, the IKeymasterDevice must use the expiration
+     *   date of the batch attestation certificate (see below).
+     *
+     * o subject -- CN="Android Keystore Key" (same value for all keys)
+     *
+     * o subjectPublicKeyInfo -- X.509 SubjectPublicKeyInfo containing the attested public key.
+     *
+     * o Key Usage extension -- digitalSignature bit must be set iff the attested key has
+     *   KeyPurpose::SIGN.  dataEncipherment bit must be set iff the attested key has
+     *   KeyPurpose::DECRYPT.  keyEncipherment bit must be set iff the attested key has
+     *   KeyPurpose::KEY_WRAP.  All other bits must be clear.
+     *
+     * In addition to the above, the attestation certificate must contain an extension with OID
+     * 1.3.6.1.4.1.11129.2.1.17 and value according to the KeyDescription schema defined as:
+     *
+     * KeyDescription ::= SEQUENCE {
+     *     attestationVersion         INTEGER, # Value 3
+     *     attestationSecurityLevel   SecurityLevel, # See below
+     *     keymasterVersion           INTEGER, # Value 4
+     *     keymasterSecurityLevel     SecurityLevel, # See below
+     *     attestationChallenge       OCTET_STRING, # Tag::ATTESTATION_CHALLENGE from attestParams
+     *     uniqueId                   OCTET_STRING, # Empty unless key has Tag::INCLUDE_UNIQUE_ID
+     *     softwareEnforced           AuthorizationList, # See below
+     *     hardwareEnforced           AuthorizationList, # See below
+     * }
+     *
+     * SecurityLevel ::= ENUMERATED {
+     *     Software                   (0),
+     *     TrustedEnvironment         (1),
+     *     StrongBox                  (2),
+     * }
+     *
+     * RootOfTrust ::= SEQUENCE {
+     *     verifiedBootKey            OCTET_STRING,
+     *     deviceLocked               BOOLEAN,
+     *     verifiedBootState          VerifiedBootState,
+     *     # verifiedBootHash must contain 32-byte value that represents the state of all binaries
+     *     # or other components validated by verified boot.  Updating any verified binary or
+     *     # component must cause this value to change.
+     *     verifiedBootHash           OCTET_STRING,
+     * }
+     *
+     * VerifiedBootState ::= ENUMERATED {
+     *     Verified                   (0),
+     *     SelfSigned                 (1),
+     *     Unverified                 (2),
+     *     Failed                     (3),
+     * }
+     *
+     * AuthorizationList ::= SEQUENCE {
+     *     purpose                    [1] EXPLICIT SET OF INTEGER OPTIONAL,
+     *     algorithm                  [2] EXPLICIT INTEGER OPTIONAL,
+     *     keySize                    [3] EXPLICIT INTEGER OPTIONAL,
+     *     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL,
+     *     digest                     [5] EXPLICIT SET OF INTEGER OPTIONAL,
+     *     padding                    [6] EXPLICIT SET OF INTEGER OPTIONAL,
+     *     callerNonce                [7] EXPLICIT NULL OPTIONAL,
+     *     minMacLength               [8] EXPLICIT INTEGER OPTIONAL,
+     *     ecCurve                    [10] EXPLICIT INTEGER OPTIONAL,
+     *     rsaPublicExponent          [200] EXPLICIT INTEGER OPTIONAL,
+     *     rollbackResistance         [303] EXPLICIT NULL OPTIONAL,
+     *     activeDateTime             [400] EXPLICIT INTEGER OPTIONAL,
+     *     originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
+     *     usageExpireDateTime        [402] EXPLICIT INTEGER OPTIONAL,
+     *     userSecureId               [502] EXPLICIT INTEGER OPTIONAL,
+     *     noAuthRequired             [503] EXPLICIT NULL OPTIONAL,
+     *     userAuthType               [504] EXPLICIT INTEGER OPTIONAL,
+     *     authTimeout                [505] EXPLICIT INTEGER OPTIONAL,
+     *     allowWhileOnBody           [506] EXPLICIT NULL OPTIONAL,
+     *     trustedUserPresenceReq     [507] EXPLICIT NULL OPTIONAL,
+     *     trustedConfirmationReq     [508] EXPLICIT NULL OPTIONAL,
+     *     unlockedDeviceReq          [509] EXPLICIT NULL OPTIONAL,
+     *     creationDateTime           [701] EXPLICIT INTEGER OPTIONAL,
+     *     origin                     [702] EXPLICIT INTEGER OPTIONAL,
+     *     rootOfTrust                [704] EXPLICIT RootOfTrust OPTIONAL,
+     *     osVersion                  [705] EXPLICIT INTEGER OPTIONAL,
+     *     osPatchLevel               [706] EXPLICIT INTEGER OPTIONAL,
+     *     attestationApplicationId   [709] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdBrand         [710] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdDevice        [711] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdProduct       [712] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdSerial        [713] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdImei          [714] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdMeid          [715] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdManufacturer  [716] EXPLICIT OCTET_STRING OPTIONAL,
+     *     attestationIdModel         [717] EXPLICIT OCTET_STRING OPTIONAL,
+     *     vendorPatchLevel           [718] EXPLICIT INTEGER OPTIONAL,
+     *     bootPatchLevel             [718] EXPLICIT INTEGER OPTIONAL,
+     * }
+     *
+     * The above schema is mostly a straightforward translation of the IKeymasterDevice tag/value
+     * parameter lists to ASN.1:
+     *
+     * o TagType::ENUM, TagType::UINT, TagType::ULONG and TagType::DATE tags are represented as
+     *   ASN.1 INTEGER.
+     *
+     * o TagType::ENUM_REP, TagType::UINT_REP and TagType::ULONG_REP tags are represented as ASN.1
+     *   SET of INTEGER.
+     *
+     * o TagType::BOOL tags are represented as ASN.1 NULL.  All entries in AuthorizationList are
+     *   OPTIONAL, so the presence of the tag means "true", absence means "false".
+     *
+     * o TagType::BYTES tags are represented as ASN.1 OCTET_STRING.
+     *
+     * The numeric ASN.1 tag numbers are the same values as the IKeymasterDevice Tag enum values,
+     * except with the TagType modifier stripped.
+     *
+     * The attestation certificate must be signed by a "batch" key, which must be securely
+     * pre-installed into the device, generally in the factory, and securely stored to prevent
+     * access or extraction.  The batch key must be used only for signing attestation certificates.
+     * The batch attestation certificate must be signed by a chain or zero or more intermediates
+     * leading to a self-signed roots.  The intermediate and root certificate signing keys must not
+     * exist anywhere on the device.
+     *
+     * == ID Attestation ==
+     *
+     * ID attestation is a special case of key attestation in which unique device ID values are
+     * included in the signed attestation certificate.
      *
      * @param keyToAttest The opaque descriptor returned by generateKey() or importKey().  The
      *        referenced key must be asymmetric.
      *
-     * @param attestParams Parameters for the attestation, notably Tag::ATTESTATION_CHALLENGE.
-     *
-     * @return error See the ErrorCode enum in types.hal.
+     * @param attestParams Parameters for the attestation.  Must contain Tag::ATTESTATION_CHALLENGE,
+     *        the value of which must be put in the attestationChallenge field of the KeyDescription
+     *        ASN.1 structure defined above.
      *
      * @return certChain The attestation certificate, and additional certificates back to the root
      *         attestation certificate, which clients will need to check against a known-good value.
+     *         The certificates must be DER-encoded.
      */
     attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
         generates (ErrorCode error, vec<vec<uint8_t>> certChain);
 
     /**
-     * Upgrades an old key blob.  Keys can become "old" in two ways: Keymaster can be upgraded to a
-     * new version with an incompatible key blob format, or the system can be updated to invalidate
-     * the OS version (OS_VERSION tag), system patch level (OS_PATCHLEVEL tag), vendor patch level
-     * (VENDOR_PATCH_LEVEL tag), boot patch level (BOOT_PATCH_LEVEL tag) or other,
+     * Upgrades an old key blob.  Keys can become "old" in two ways: IKeymasterDevice can be
+     * upgraded to a new version with an incompatible key blob format, or the system can be updated
+     * to invalidate the OS version (OS_VERSION tag), system patch level (OS_PATCHLEVEL tag), vendor
+     * patch level (VENDOR_PATCH_LEVEL tag), boot patch level (BOOT_PATCH_LEVEL tag) or other,
      * implementation-defined patch level (keymaster implementers are encouraged to extend this HAL
-     * with a minor version extension to define validatable patch levels for other images; tags
-     * must be defined in the implemeter's namespace, starting at 10000).  In either case,
-     * attempts to use an old key blob with getKeyCharacteristics(), exportKey(), attestKey() or
-     * begin() must result in Keymaster returning ErrorCode::KEY_REQUIRES_UPGRADE.  The caller must
-     * use this method to upgrade the key blob.
+     * with a minor version extension to define validatable patch levels for other images; tags must
+     * be defined in the implementer's namespace, starting at 10000).  In either case, attempts to
+     * use an old key blob with getKeyCharacteristics(), exportKey(), attestKey() or begin() must
+     * result in IKeymasterDevice returning ErrorCode::KEY_REQUIRES_UPGRADE.  The caller must use
+     * this method to upgrade the key blob.
      *
-     * If upgradeKey is asked to update a key with any version or patch level that is higher than
-     * the current system version or patch level, it must return ErrorCode::INVALID_ARGUMENT.  There
-     * is one exception: it is always permissible to "upgrade" from any OS_VERSION number to
-     * OS_VERSION 0.  For example, if the key has OS_VERSION 080001, it is permisible to upgrade the
-     * key if the current system version is 080100, because the new version is larger, or if the
-     * current system version is 0, because upgrades to 0 are always allowed.  If the system version
-     * were 080000, however, keymaster must return ErrorCode::INVALID_ARGUMENT because that value is
-     * smaller than 080001.
+     * The upgradeKey method must examine each version or patch level associated with the key.  If
+     * any one of them is higher than the corresponding current device value upgradeKey() must
+     * return ErrorCode::INVALID_ARGUMENT.  There is one exception: it is always permissible to
+     * "downgrade" from any OS_VERSION number to OS_VERSION 0.  For example, if the key has
+     * OS_VERSION 080001, it is permisible to upgrade the key if the current system version is
+     * 080100, because the new version is larger, or if the current system version is 0, because
+     * upgrades to 0 are always allowed.  If the system version were 080000, however, keymaster must
+     * return ErrorCode::INVALID_ARGUMENT because that value is smaller than 080001.  Values other
+     * than OS_VERSION must never be downgraded.
      *
      * Note that Keymaster versions 2 and 3 required that the system and boot images have the same
-     * patch level and OS version.  This requirement is relaxed for Keymaster 4, and the OS version
-     * in the boot image footer is no longer used.
+     * patch level and OS version.  This requirement is relaxed for 4.0::IKeymasterDevice, and the
+     * OS version in the boot image footer is no longer used.
      *
      * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
      *
      * @param upgradeParams A parameter list containing any parameters needed to complete the
      *        upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
      *
-     * @return error See the ErrorCode enum.
-     *
      * @return upgradedKeyBlob A new key blob that references the same key as keyBlobToUpgrade, but
      *         is in the new format, or has the new version data.
      */
@@ -416,8 +843,6 @@
      * unusable.
      *
      * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
-     *
-     * @return error See the ErrorCode enum.
      */
     deleteKey(vec<uint8_t> keyBlob) generates (ErrorCode error);
 
@@ -441,8 +866,6 @@
      * must never attest any device ids.
      *
      * This is a NOP if device id attestation is not supported.
-     *
-     * @return error See the ErrorCode enum.
      */
     destroyAttestationIds() generates (ErrorCode error);
 
@@ -452,12 +875,180 @@
      * to update(), finish() or abort().
      *
      * It is critical that each call to begin() be paired with a subsequent call to finish() or
-     * abort(), to allow the Keymaster implementation to clean up any internal operation state.  The
-     * caller's failure to do this may leak internal state space or other internal resources and may
-     * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space
-     * for operations.  Any result other than ErrorCode::OK from begin(), update() or finish()
-     * implicitly aborts the operation, in which case abort() need not be called (and must return
-     * ErrorCode::INVALID_OPERATION_HANDLE if called).
+     * abort(), to allow the IKeymasterDevice implementation to clean up any internal operation
+     * state.  The caller's failure to do this may leak internal state space or other internal
+     * resources and may eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it
+     * runs out of space for operations.  Any result other than ErrorCode::OK from begin(), update()
+     * or finish() implicitly aborts the operation, in which case abort() need not be called (and
+     * must return ErrorCode::INVALID_OPERATION_HANDLE if called).  IKeymasterDevice implementations
+     * must support 16 concurrent operations.
+     *
+     * If Tag::APPLICATION_ID or Tag::APPLICATION_DATA were specified during key generation or
+     * import, calls to begin must include those tags with the originally-specified values in the
+     * inParams argument to this method.  If not, begin() must return ErrorCode::INVALID_KEY_BLOB.
+     *
+     * == Authorization Enforcement ==
+     *
+     * The following key authorization parameters must be enforced by the IKeymasterDevice secure
+     * environment if the tags were returned in the "hardwareEnforced" list in the
+     * KeyCharacteristics.  Public key operations, meaning KeyPurpose::ENCRYPT and
+     * KeyPurpose::VERIFY must be allowed to succeed even if authorization requirements are not met.
+     *
+     * -- All Key Types --
+     *
+     * The tags in this section apply to all key types.  See below for additional key type-specific
+     * tags.
+     *
+     * o Tag::PURPOSE: The purpose specified in the begin() call must match one of the purposes in
+     *   the key authorizations.  If the specified purpose does not match, begin() must return
+     *   ErrorCode::UNSUPPORTED_PURPOSE.
+     *
+     * o Tag::ACTIVE_DATETIME can only be enforced if a trusted UTC time source is available.  If
+     *   the current date and time is prior to the tag value, begin() must return
+     *   ErrorCode::KEY_NOT_YET_VALID.
+     *
+     * o Tag::ORIGINATION_EXPIRE_DATETIME can only be enforced if a trusted UTC time source is
+     *   available.  If the current date and time is later than the tag value and the purpose is
+     *   KeyPurpose::ENCRYPT or KeyPurpose::SIGN, begin() must return ErrorCode::KEY_EXPIRED.
+     *
+     * o Tag::USAGE_EXPIRE_DATETIME can only be enforced if a trusted UTC time source is
+     *   available.  If the current date and time is later than the tag value and the purpose is
+     *   KeyPurpose::DECRYPT or KeyPurpose::VERIFY, begin() must return ErrorCode::KEY_EXPIRED.
+
+     * o Tag::MIN_SECONDS_BETWEEN_OPS must be compared with a trusted relative timer indicating the
+     *   last use of the key.  If the last use time plus the tag value is less than the current
+     *   time, begin() must return ErrorCode::KEY_RATE_LIMIT_EXCEEDED.  See the tag description for
+     *   important implementation details.
+
+     * o Tag::MAX_USES_PER_BOOT must be compared against a secure counter that tracks the uses of
+     *   the key since boot time.  If the count of previous uses exceeds the tag value, begin() must
+     *   return ErrorCode::KEY_MAX_OPS_EXCEEDED.
+     *
+     * o Tag::USER_SECURE_ID must be enforced by this method if and only if the key also has
+     *   Tag::AUTH_TIMEOUT (if it does not have Tag::AUTH_TIMEOUT, the Tag::USER_SECURE_ID
+     *   requirement must be enforced by update() and finish()).  If the key has both, then this
+     *   method must receive a non-empty HardwareAuthToken in the authToken argument.  For the auth
+     *   token to be valid, all of the following have to be true:
+     *
+     *   o The HMAC field must validate correctly.
+     *
+     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+     *     the secure ID values in the token.
+     *
+     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+     *
+     *   o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
+     *     the current secure timestamp (which is a monotonic timer counting milliseconds since
+     *     boot.)
+     *
+     *   If any of these conditions are not met, begin() must return
+     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * o Tag::CALLER_NONCE allows the caller to specify a nonce or initialization vector (IV).  If
+     *   the key doesn't have this tag, but the caller provided Tag::NONCE to this method,
+     *   ErrorCode::CALLER_NONCE_PROHIBITED must be returned.
+     *
+     * o Tag::BOOTLOADER_ONLY specifies that only the bootloader may use the key.  If this method is
+     *   called with a bootloader-only key after the bootloader has finished executing, it must
+     *   return ErrorCode::INVALID_KEY_BLOB.  The mechanism for notifying the IKeymasterDevice that
+     *   the bootloader has finished executing is implementation-defined.
+     *
+     * -- RSA Keys --
+     *
+     * All RSA key operations must specify exactly one padding mode in inParams.  If unspecified or
+     * specified more than once, the begin() must return ErrorCode::UNSUPPORTED_PADDING_MODE.
+     *
+     * RSA signing and verification operations need a digest, as do RSA encryption and decryption
+     * operations with OAEP padding mode.  For those cases, the caller must specify exactly one
+     * digest in inParams.  If unspecified or specified more than once, begin() must return
+     * ErrorCode::UNSUPPORTED_DIGEST.
+     *
+     * Private key operations (KeyPurpose::DECRYPT and KeyPurpose::SIGN) need authorization of
+     * digest and padding, which means that the key authorizations need to contain the specified
+     * values.  If not, begin() must return ErrorCode::INCOMPATIBLE_DIGEST or
+     * ErrorCode::INCOMPATIBLE_PADDING, as appropriate.  Public key operations (KeyPurpose::ENCRYPT
+     * and KeyPurpose::VERIFY) are permitted with unauthorized digest or padding modes.
+     *
+     * With the exception of PaddingMode::NONE, all RSA padding modes are applicable only to certain
+     * purposes.  Specifically, PaddingMode::RSA_PKCS1_1_5_SIGN and PaddingMode::RSA_PSS only
+     * support signing and verification, while PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
+     * PaddingMode::RSA_OAEP only support encryption and decryption.  begin() must return
+     * ErrorCode::UNSUPPORTED_PADDING_MODE if the specified mode does not support the specified
+     * purpose.
+     *
+     * There are some important interactions between padding modes and digests:
+     *
+     * o PaddingMode::NONE indicates that a "raw" RSA operation is performed.  If signing or
+     *   verifying, Digest::NONE is specified for the digest.  No digest is necessary for unpadded
+     *   encryption or decryption.
+     *
+     * o PaddingMode::RSA_PKCS1_1_5_SIGN padding requires a digest.  The digest may be Digest::NONE,
+     *   in which case the Keymaster implementation cannot build a proper PKCS#1 v1.5 signature
+     *   structure, because it cannot add the DigestInfo structure.  Instead, the IKeymasterDevice
+     *   must construct 0x00 || 0x01 || PS || 0x00 || M, where M is the provided message and PS is a
+     *   random padding string at least eight bytes in length.  The size of the RSA key has to be at
+     *   least 11 bytes larger than the message, otherwise begin() must return
+     *   ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * o PaddingMode::RSA_PKCS1_1_1_5_ENCRYPT padding does not require a digest.
+     *
+     * o PaddingMode::RSA_PSS padding requires a digest, which may not be Digest::NONE.  If
+     *   Digest::NONE is specified, the begin() must return ErrorCode::INCOMPATIBLE_DIGEST.  In
+     *   addition, the size of the RSA key must be at least 2 + D bytes larger than the output size
+     *   of the digest, where D is the size of the digest, in bytes.  Otherwise begin() must
+     *   return ErrorCode::INCOMPATIBLE_DIGEST.  The salt size must be D.
+     *
+     * o PaddingMode::RSA_OAEP padding requires a digest, which may not be Digest::NONE.  If
+     *   Digest::NONE is specified, begin() must return ErrorCode::INCOMPATIBLE_DIGEST.  The OAEP
+     *   mask generation function must be MGF1 and the MGF1 digest must be SHA1, regardless of the
+     *   OAEP digest specified.
+     *
+     * -- EC Keys --
+     *
+     * EC key operations must specify exactly one padding mode in inParams.  If unspecified or
+     * specified more than once, begin() must return ErrorCode::UNSUPPORTED_PADDING_MODE.
+     *
+     * Private key operations (KeyPurpose::SIGN) need authorization of digest and padding, which
+     * means that the key authorizations must contain the specified values.  If not, begin() must
+     * return ErrorCode::INCOMPATIBLE_DIGEST.  Public key operations (KeyPurpose::VERIFY) are
+     * permitted with unauthorized digest or padding.
+     *
+     * -- AES Keys --
+     *
+     * AES key operations must specify exactly one block mode (Tag::BLOCK_MODE) and one padding mode
+     * (Tag::PADDING) in inParams.  If either value is unspecified or specified more than once,
+     * begin() must return ErrorCode::UNSUPPORTED_BLOCK_MODE or
+     * ErrorCode::UNSUPPORTED_PADDING_MODE.  The specified modes must be authorized by the key,
+     * otherwise begin() must return ErrorCode::INCOMPATIBLE_BLOCK_MODE or
+     * ErrorCode::INCOMPATIBLE_PADDING_MODE.
+     *
+     * If the block mode is BlockMode::GCM, inParams must specify Tag::MAC_LENGTH, and the specified
+     * value must be a multiple of 8 that is not greater than 128 or less than the value of
+     * Tag::MIN_MAC_LENGTH in the key authorizations.  For MAC lengths greater than 128 or
+     * non-multiples of 8, begin() must return ErrorCode::UNSUPPORTED_MAC_LENGTH.  For values less
+     * than the key's minimum length, begin() must return ErrorCode::INVALID_MAC_LENGTH.
+     *
+     * If the block mode is BlockMode::GCM or BlockMode::CTR, the specified padding mode must be
+     * PaddingMode::NONE.  For BlockMode::ECB or BlockMode::CBC, the mode may be PaddingMode::NONE
+     * or PaddingMode::PKCS7.  If the padding mode doesn't meet these conditions, begin() must
+     * return ErrorCode::INCOMPATIBLE_PADDING_MODE.
+     *
+     * If the block mode is BlockMode::CBC, BlockMode::CTR, or BlockMode::GCM, an initialization
+     * vector or nonce is required.  In most cases, callers shouldn't provide an IV or nonce and the
+     * IKeymasterDevice implementation must generate a random IV or nonce and return it via
+     * Tag::NONCE in outParams.  CBC and CTR IVs are 16 bytes.  GCM nonces are 12 bytes.  If the key
+     * authorizations contain Tag::CALLER_NONCE, then the caller may provide an IV/nonce with
+     * Tag::NONCE in inParams.  If a nonce is provided when Tag::CALLER_NONCE is not authorized,
+     * begin() must return ErrorCode::CALLER_NONCE_PROHIBITED.  If a nonce is not provided when
+     * Tag::CALLER_NONCE is authorized, IKeymasterDevice msut generate a random IV/nonce.
+     *
+     * -- HMAC keys --
+     *
+     * HMAC key operations must specify Tag::MAC_LENGTH in inParams.  The specified value must be a
+     * multiple of 8 that is not greater than the digest length or less than the value of
+     * Tag::MIN_MAC_LENGTH in the key authorizations.  For MAC lengths greater than the digest
+     * length or non-multiples of 8, begin() must return ErrorCode::UNSUPPORTED_MAC_LENGTH.  For
+     * values less than the key's minimum length, begin() must return ErrorCode::INVALID_MAC_LENGTH.
      *
      * @param purpose The purpose of the operation, one of KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT,
      *        KeyPurpose::SIGN or KeyPurpose::VERIFY.  Note that for AEAD modes, encryption and
@@ -466,7 +1057,7 @@
      *
      * @param keyBlob The opaque key descriptor returned by generateKey() or importKey().  The key
      *        must have a purpose compatible with purpose and all of its usage requirements must be
-     *        satisfied, or begin() must return an appropriate error code.
+     *        satisfied, or begin() must return an appropriate error code (see above).
      *
      * @param inParams Additional parameters for the operation.  If Tag::APPLICATION_ID or
      *        Tag::APPLICATION_DATA were provided during generation, they must be provided here, or
@@ -478,8 +1069,6 @@
      * @param authToken Authentication token.  Callers that provide no token must set all numeric
      *        fields to zero and the MAC must be an empty vector.
      *
-     * @return error See the ErrorCode enum in types.hal.
-     *
      * @return outParams Output parameters.  Used to return additional data from the operation
      *         initialization, notably to return the IV or nonce from operations that generate an IV
      *         or nonce.
@@ -493,13 +1082,87 @@
 
     /**
      * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
-     * with begin().
+     * with begin().  The operation is specified by the operationHandle paramater.
      *
      * If operationHandle is invalid, update() must return ErrorCode::INVALID_OPERATION_HANDLE.
      *
-     * update() may not consume all of the data provided in the data buffer.  update() must return
-     * the amount consumed in inputConsumed.  The caller may provide the unconsumed data in a
-     * subsequent call.
+     * To provide more flexibility for buffer handling, implementations of this method have the
+     * option of consuming less data than was provided.  The caller is responsible for looping to
+     * feed the rest of the data in subsequent calls.  The amount of input consumed must be returned
+     * in the inputConsumed parameter.  Implementations must always consume at least one byte, unless
+     * the operation cannot accept any more; if more than zero bytes are provided and zero bytes are
+     * consumed, callers must consider this an error and abort the operation.
+     *
+     * Implementations may also choose how much data to return, as a result of the update.  This is
+     * only relevant for encryption and decryption operations, because signing and verification
+     * return no data until finish.  It is recommended to return data as early as possible, rather
+     * than buffer it.
+     *
+     * If this method returns an error code other than ErrorCode::OK, the operation is aborted and
+     * the operation handle must be invalidated.  Any future use of the handle, with this method,
+     * finish, or abort, must return ErrorCode::INVALID_OPERATION_HANDLE.
+     *
+     * == Authorization Enforcement ==
+     *
+     * Key authorization enforcement is performed primarily in begin().  The one exception is the
+     * case where the key has:
+
+     * o One or more Tag::USER_SECURE_IDs, and
+     *
+     * o Does not have a Tag::AUTH_TIMEOUT
+     *
+     * In this case, the key requires an authorization per operation, and the update method must
+     * receive a non-empty and valid HardwareAuthToken.  For the auth token to be valid, all of the
+     * following has to be true:
+     *
+     *   o The HMAC field must validate correctly.
+     *
+     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+     *     the secure ID values in the token.
+     *
+     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+     *
+     *   o The challenge field in the auth token must contain the operationHandle
+     *
+     *   If any of these conditions are not met, update() must return
+     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * The caller must provide the auth token on every call to update() and finish().
+     *
+     * -- RSA keys --
+     *
+     * For signing and verification operations with Digest::NONE, this method must accept the entire
+     * block to be signed or verified in a single update.  It may not consume only a portion of the
+     * block in these cases.  However, the caller may choose to provide the data in multiple updates,
+     * and update() must accept the data this way as well.  If the caller provides more data to sign
+     * than can be used (length of data exceeds RSA key size), update() must return
+     * ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * -- ECDSA keys --
+     *
+     * For signing and verification operations with Digest::NONE, this method must accept the entire
+     * block to be signed or verified in a single update.  This method may not consume only a
+     * portion of the block.  However, the caller may choose to provide the data in multiple updates
+     * and update() must accept the data this way as well.  If the caller provides more data to sign
+     * than can be used, the data is silently truncated.  (This differs from the handling of excess
+     * data provided in similar RSA operations.  The reason for this is compatibility with legacy
+     * clients.)
+     *
+     * -- AES keys --
+     *
+     * AES GCM mode supports "associated authentication data," provided via the Tag::ASSOCIATED_DATA
+     * tag in the inParams argument.  The associated data may be provided in repeated calls
+     * (important if the data is too large to send in a single block) but must always precede data
+     * to be encrypted or decrypted.  An update call may receive both associated data and data to
+     * encrypt/decrypt, but subsequent updates must not include associated data.  If the caller
+     * provides associated data to an update call after a call that includes data to
+     * encrypt/decrypt, update() must return ErrorCode::INVALID_TAG.
+     *
+     * For GCM encryption, the AEAD tag must be appended to the ciphertext by finish().  During
+     * decryption, the last Tag::MAC_LENGTH bytes of the data provided to the last update call must
+     * be the AEAD tag.  Since a given invocation of update cannot know if it's the last invocation,
+     * it must process all but the tag length and buffer the possible tag data for processing during
+     * finish().
      *
      * @param operationHandle The operation handle returned by begin().
      *
@@ -513,16 +1176,18 @@
      * @param authToken Authentication token.  Callers that provide no token must set all numeric
      *        fields to zero and the MAC must be an empty vector.
      *
-     * @param verificationToken Verification token, used to prove that another Keymaster HAL has
-     *        verified some parameters, and to deliver the other HAL's current timestamp, if needed.
-     *        If not provided, all fields must be initialized to zero and vectors empty.
+     * @param verificationToken Verification token, used to prove that another IKeymasterDevice HAL
+     *        has verified some parameters, and to deliver the other HAL's current timestamp, if
+     *        needed.  If not provided, all fields must be initialized to zero and vectors must be
+     *        empty.
      *
      * @return error See the ErrorCode enum in types.hal.
      *
      * @return inputConsumed Amount of data that was consumed by update().  If this is less than the
      *         amount provided, the caller may provide the remainder in a subsequent call to
-     *         update() or finish().  Every call to update must consume at least one byte, and
-     *         implementations should consume as much data as reasonably possible for each call.
+     *         update() or finish().  Every call to update must consume at least one byte, unless
+     *         the input is empty, and implementations should consume as much data as reasonably
+     *         possible for each call.
      *
      * @return outParams Output parameters, used to return additional data from the operation.
      *
@@ -536,6 +1201,86 @@
     /**
      * Finalizes a cryptographic operation begun with begin() and invalidates operationHandle.
      *
+     * This method is the last one called in an operation, so all processed data must be returned.
+     *
+     * Whether it completes successfully or returns an error, this method finalizes the operation
+     * and therefore must invalidate the provided operation handle.  Any future use of the handle,
+     * with finish(), update(), or abort(), must return ErrorCode::INVALID_OPERATION_HANDLE.
+     *
+     * Signing operations return the signature as the output.  Verification operations accept the
+     * signature in the signature parameter, and return no output.
+     *
+     * == Authorization enforcement ==
+     *
+     * Key authorization enforcement is performed primarily in begin().  The exceptions are
+     * authorization per operation keys and confirmation-required keys.
+     *
+     * Authorization per operation keys are the case where the key has one or more
+     * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT.  In this case, the key requires
+     * an authorization per operation, and the finish method must receive a non-empty and valid
+     * authToken.  For the auth token to be valid, all of the following has to be true:
+     *
+     *   o The HMAC field must validate correctly.
+     *
+     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+     *     the secure ID values in the token.
+     *
+     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+     *
+     *   o The challenge field in the auth token must contain the operationHandle
+     *
+     *   If any of these conditions are not met, update() must return
+     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * The caller must provide the auth token on every call to update() and finish().
+     *
+     * Confirmation-required keys are keys that were generated with
+     * Tag::TRUSTED_CONFIRMATION_REQUIRED.  For these keys, when doing a signing operation the
+     * caller must pass a KeyParameter Tag::CONFIRMATION_TOKEN to finish().  Implementations must
+     * check the confirmation token by computing the 32-byte HMAC-SHA256 over all of the
+     * to-be-signed data, prefixed with the 18-byte UTF-8 encoded string "confirmation token". If
+     * the computed value does not match the Tag::CONFIRMATION_TOKEN parameter, finish() must not
+     * produce a signature and must return ErrorCode::NO_USER_CONFIRMATION.
+     *
+     * -- RSA keys --
+     *
+     * Some additional requirements, depending on the padding mode:
+     *
+     * o PaddingMode::NONE.  For unpadded signing and encryption operations, if the provided data is
+     *   shorter than the key, the data must be zero-padded on the left before
+     *   signing/encryption.  If the data is the same length as the key, but numerically larger,
+     *   finish() must return ErrorCode::INVALID_ARGUMENT.  For verification and decryption
+     *   operations, the data must be exactly as long as the key.  Otherwise, return
+     *   ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * o PaddingMode::RSA_PSS.  For PSS-padded signature operations, the PSS salt length must match
+     *   the size of the PSS digest selected.  The digest specified with Tag::DIGEST in inputParams
+     *   on begin() must be used as the PSS digest algorithm, MGF1 must be used as the mask
+     *   generation function and SHA1 must be used as the MGF1 digest algorithm.
+     *
+     * o PaddingMode::RSA_OAEP.  The digest specified with Tag::DIGEST in inputParams on begin is
+     *   used as the OAEP digest algorithm, MGF1 must be used as the mask generation function and
+     *   and SHA1 must be used as the MGF1 digest algorithm.
+     *
+     * -- ECDSA keys --
+     *
+     * If the data provided for unpadded signing or verification is too long, truncate it.
+     *
+     * -- AES keys --
+     *
+     * Some additional conditions, depending on block mode:
+     *
+     * o BlockMode::ECB or BlockMode::CBC.  If padding is PaddingMode::NONE and the data length is
+     *  not a multiple of the AES block size, finish() must return
+     *  ErrorCode::INVALID_INPUT_LENGTH.  If padding is PaddingMode::PKCS7, pad the data per the
+     *  PKCS#7 specification, including adding an additional padding block if the data is a multiple
+     *  of the block length.
+     *
+     * o BlockMode::GCM.  During encryption, after processing all plaintext, compute the tag
+     *   (Tag::MAC_LENGTH bytes) and append it to the returned ciphertext.  During decryption,
+     *   process the last Tag::MAC_LENGTH bytes as the tag.  If tag verification fails, finish()
+     *   must return ErrorCode::VERIFICATION_FAILED.
+     *
      * @param operationHandle The operation handle returned by begin().  This handle must be invalid
      *        when finish() returns.
      *
@@ -551,11 +1296,9 @@
      * @param authToken Authentication token.  Callers that provide no token must set all numeric
      *        fields to zero and the MAC must be an empty vector.
      *
-     * @param verificationToken Verification token, used to prove that another Keymaster HAL has
-     *        verified some parameters, and to deliver the other HAL's current timestamp, if needed.
-     *        If not provided, all fields must be initialized to zero and vectors empty.
-     *
-     * @return error See the ErrorCode enum in types.hal.
+     * @param verificationToken Verification token, used to prove that another IKeymasterDevice HAL
+     *        has verified some parameters, and to deliver the other HAL's current timestamp, if
+     *        needed.  If not provided, all fields must be initialized to zero and vectors empty.
      *
      * @return outParams Any output parameters generated by finish().
      *
diff --git a/keymaster/4.0/default/service.cpp b/keymaster/4.0/default/service.cpp
index cfb960a..fdcc6ba 100644
--- a/keymaster/4.0/default/service.cpp
+++ b/keymaster/4.0/default/service.cpp
@@ -24,6 +24,7 @@
 using android::hardware::keymaster::V4_0::SecurityLevel;
 
 int main() {
+    ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
     auto keymaster = ::keymaster::V4_0::ng::CreateKeymasterDevice(SecurityLevel::SOFTWARE);
     auto status = keymaster->registerAsService();
     if (status != android::OK) {
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index fac0017..444298b 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -16,24 +16,73 @@
 
 #include <keymasterV4_0/Keymaster.h>
 
+#include <iomanip>
+
 #include <android-base/logging.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <keymasterV4_0/Keymaster3.h>
 #include <keymasterV4_0/Keymaster4.h>
+#include <keymasterV4_0/key_param_output.h>
+#include <keymasterV4_0/keymaster_utils.h>
 
 namespace android {
 namespace hardware {
+
+template <class T>
+std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) {
+    os << "{ ";
+    if (vec.size()) {
+        for (size_t i = 0; i < vec.size() - 1; ++i) os << vec[i] << ", ";
+        os << vec[vec.size() - 1];
+    }
+    os << " }";
+    return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const hidl_vec<uint8_t>& vec) {
+    std::ios_base::fmtflags flags(os.flags());
+    os << std::setw(2) << std::setfill('0') << std::hex;
+    for (uint8_t c : vec) os << static_cast<int>(c);
+    os.flags(flags);
+    return os;
+}
+
+template <size_t N>
+std::ostream& operator<<(std::ostream& os, const hidl_array<uint8_t, N>& vec) {
+    std::ios_base::fmtflags flags(os.flags());
+    os << std::setw(2) << std::setfill('0') << std::hex;
+    for (size_t i = 0; i < N; ++i) os << static_cast<int>(vec[i]);
+    os.flags(flags);
+    return os;
+}
+
 namespace keymaster {
 namespace V4_0 {
+
+std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) {
+    // Note that by design, although seed and nonce are used to compute a secret, they are
+    // not secrets and it's just fine to log them.
+    os << "(seed: " << params.seed << ", nonce: " << params.nonce << ')';
+    return os;
+}
+
 namespace support {
 
 using ::android::sp;
 using ::android::hidl::manager::V1_0::IServiceManager;
 
+std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster) {
+    auto& version = keymaster.halVersion();
+    os << version.keymasterName << " from " << version.authorName
+       << " SecurityLevel: " << toString(version.securityLevel)
+       << " HAL: " << keymaster.descriptor() << "/" << keymaster.instanceName();
+    return os;
+}
+
 template <typename Wrapper>
 std::vector<std::unique_ptr<Keymaster>> enumerateDevices(
     const sp<IServiceManager>& serviceManager) {
-    std::vector<std::unique_ptr<Keymaster>> result;
+    Keymaster::KeymasterSet result;
 
     bool foundDefault = false;
     auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor;
@@ -57,7 +106,7 @@
     return result;
 }
 
-std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() {
+Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() {
     auto serviceManager = IServiceManager::getService();
     CHECK(serviceManager) << "Could not retrieve ServiceManager";
 
@@ -73,18 +122,64 @@
 
     size_t i = 1;
     LOG(INFO) << "List of Keymaster HALs found:";
-    for (auto& hal : result) {
-        auto& version = hal->halVersion();
-        LOG(INFO) << "Keymaster HAL #" << i << ": " << version.keymasterName << " from "
-                  << version.authorName << " SecurityLevel: " << toString(version.securityLevel)
-                  << " HAL : " << hal->descriptor() << " instance " << hal->instanceName();
-    }
+    for (auto& hal : result) LOG(INFO) << "Keymaster HAL #" << i++ << ": " << *hal;
 
     return result;
 }
 
+static hidl_vec<HmacSharingParameters> getHmacParameters(
+    const Keymaster::KeymasterSet& keymasters) {
+    std::vector<HmacSharingParameters> params_vec;
+    params_vec.reserve(keymasters.size());
+    for (auto& keymaster : keymasters) {
+        if (keymaster->halVersion().majorVersion < 4) continue;
+        auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) {
+            CHECK(error == ErrorCode::OK)
+                << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
+            params_vec.push_back(params);
+        });
+        CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
+                         << " error: " << rc.description();
+    }
+    std::sort(params_vec.begin(), params_vec.end());
+
+    return params_vec;
+}
+
+static void computeHmac(const Keymaster::KeymasterSet& keymasters,
+                        const hidl_vec<HmacSharingParameters>& params) {
+    if (!params.size()) return;
+
+    hidl_vec<uint8_t> sharingCheck;
+    bool firstKeymaster = true;
+    LOG(DEBUG) << "Computing HMAC with params " << params;
+    for (auto& keymaster : keymasters) {
+        if (keymaster->halVersion().majorVersion < 4) continue;
+        LOG(DEBUG) << "Computing HMAC for " << *keymaster;
+        auto rc = keymaster->computeSharedHmac(
+            params, [&](ErrorCode error, const hidl_vec<uint8_t>& curSharingCheck) {
+                CHECK(error == ErrorCode::OK)
+                    << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
+                if (firstKeymaster) {
+                    sharingCheck = curSharingCheck;
+                    firstKeymaster = false;
+                }
+                CHECK(curSharingCheck == sharingCheck)
+                    << "HMAC computation failed for " << *keymaster  //
+                    << " Expected: " << sharingCheck                 //
+                    << " got: " << curSharingCheck;
+            });
+        CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
+                         << " error: " << rc.description();
+    }
+}
+
+void Keymaster::performHmacKeyAgreement(const KeymasterSet& keymasters) {
+    computeHmac(keymasters, getHmacParameters(keymasters));
+}
+
 }  // namespace support
 }  // namespace V4_0
 }  // namespace keymaster
 }  // namespace hardware
-};  // namespace android
+}  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
index f9efd51..83b1d69 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
@@ -37,6 +37,8 @@
  */
 class Keymaster : public IKeymasterDevice {
    public:
+    using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>;
+
     Keymaster(const hidl_string& descriptor, const hidl_string& instanceName)
         : descriptor_(descriptor), instanceName_(instanceName) {}
     virtual ~Keymaster() {}
@@ -55,21 +57,33 @@
         }
     };
 
-    virtual const VersionResult& halVersion() = 0;
-    const hidl_string& descriptor() { return descriptor_; }
-    const hidl_string& instanceName() { return instanceName_; }
+    virtual const VersionResult& halVersion() const = 0;
+    const hidl_string& descriptor() const { return descriptor_; }
+    const hidl_string& instanceName() const { return instanceName_; }
 
     /**
      * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least
      * secure (as defined by VersionResult::operator<).
      */
-    static std::vector<std::unique_ptr<Keymaster>> enumerateAvailableDevices();
+    static KeymasterSet enumerateAvailableDevices();
+
+    /**
+     * Ask provided Keymaster instances to compute a shared HMAC key using
+     * getHmacSharingParameters() and computeSharedHmac().  This computation is idempotent as long
+     * as the same set of Keymaster instances is used each time (and if all of the instances work
+     * correctly).  It must be performed once per boot, but should do no harm to be repeated.
+     *
+     * If key agreement fails, this method will crash the process (with CHECK).
+     */
+    static void performHmacKeyAgreement(const KeymasterSet& keymasters);
 
    private:
     hidl_string descriptor_;
     hidl_string instanceName_;
 };
 
+std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster);
+
 }  // namespace support
 }  // namespace V4_0
 }  // namespace keymaster
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
index 2bb77ca..c40be7c 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
@@ -45,8 +45,8 @@
           km3_dev_(km3_dev),
           haveVersion_(false) {}
 
-    const VersionResult& halVersion() override {
-        getVersionIfNeeded();
+    const VersionResult& halVersion() const override {
+        const_cast<Keymaster3*>(this)->getVersionIfNeeded();
         return version_;
     }
 
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
index 96afb13..dfd03ef 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
@@ -37,8 +37,8 @@
           haveVersion_(false),
           dev_(km4_dev) {}
 
-    const VersionResult& halVersion() override {
-        getVersionIfNeeded();
+    const VersionResult& halVersion() const override {
+        const_cast<Keymaster4*>(this)->getVersionIfNeeded();
         return version_;
     }
 
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
index 1c1b000..90a0f1b 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -23,6 +23,14 @@
 namespace hardware {
 namespace keymaster {
 namespace V4_0 {
+
+/**
+ * Define a lexicographical ordering on HmacSharingParameters.  The parameters to
+ * IKeymasterDevice::computeSharedHmac are required to be delivered in the order specified by this
+ * comparison operator.
+ */
+bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b);
+
 namespace support {
 
 inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
index bc610aa..729e1c1 100644
--- a/keymaster/4.0/support/keymaster_utils.cpp
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -19,8 +19,24 @@
 
 namespace android {
 namespace hardware {
+
+inline static bool operator<(const hidl_vec<uint8_t>& a, const hidl_vec<uint8_t>& b) {
+    return memcmp(a.data(), b.data(), std::min(a.size(), b.size())) == -1;
+}
+
+template <size_t SIZE>
+inline static bool operator<(const hidl_array<uint8_t, SIZE>& a,
+                             const hidl_array<uint8_t, SIZE>& b) {
+    return memcmp(a.data(), b.data(), SIZE) == -1;
+}
+
 namespace keymaster {
 namespace V4_0 {
+
+bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b) {
+    return std::tie(a.seed, a.nonce) < std::tie(b.seed, b.nonce);
+}
+
 namespace support {
 
 template <typename T, typename InIter>
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 47fd1ed..94dfec5 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -59,83 +59,364 @@
 enum Tag : uint32_t {
     INVALID = TagType:INVALID | 0,
 
-    /*
-     * Tags that must be semantically enforced by hardware and software implementations.
+    /**
+     * Tag::PURPOSE specifies the set of purposes for which the key may be used.  Possible values
+     * are defined in the KeyPurpose enumeration.
+     *
+     * This tag is repeatable; keys may be generated with multiple values, although an operation has
+     * a single purpose.  When begin() is called to start an operation, the purpose of the operation
+     * is specified.  If the purpose specified for the operation is not authorized by the key (the
+     * key didn't have a corresponding Tag::PURPOSE provided during generation/import), the
+     * operation must fail with ErrorCode::INCOMPATIBLE_PURPOSE.
+     *
+     * Must be hardware-enforced.
      */
+    PURPOSE = TagType:ENUM_REP | 1,
 
-    /* Crypto parameters */
-    PURPOSE = TagType:ENUM_REP | 1,    /* KeyPurpose. */
-    ALGORITHM = TagType:ENUM | 2,      /* Algorithm. */
-    KEY_SIZE = TagType:UINT | 3,       /* Key size in bits. */
+    /**
+     * Tag::ALGORITHM specifies the cryptographic algorithm with which the key is used.  This tag
+     * must be provided to generateKey and importKey, and must be specified in the wrapped key
+     * provided to importWrappedKey.
+     *
+     * Must be hardware-enforced.
+     */
+    ALGORITHM = TagType:ENUM | 2,
+
+    /**
+     * Tag::KEY_SIZE pecifies the size, in bits, of the key, measuring in the normal way for the
+     * key's algorithm.  For example, for RSA keys, Tag::KEY_SIZE specifies the size of the public
+     * modulus.  For AES keys it specifies the length of the secret key material.  For 3DES keys it
+     * specifies the length of the key material, not counting parity bits (though parity bits must
+     * be provided for import, etc.).  Since only three-key 3DES keys are supported, 3DES
+     * Tag::KEY_SIZE must be 168.
+     *
+     * Must be hardware-enforced.
+     */
+    KEY_SIZE = TagType:UINT | 3,
+
+    /**
+     * Tag::BLOCK_MODE specifies the block cipher mode(s) with which the key may be used.  This tag
+     * is only relevant to AES and 3DES keys.  Possible values are defined by the BlockMode enum.
+     *
+     * This tag is repeatable for key generation/import.  For AES and 3DES operations the caller
+     * must specify a Tag::BLOCK_MODE in the additionalParams argument of begin().  If the mode is
+     * missing or the specified mode is not in the modes specified for the key during
+     * generation/import, the operation must fail with ErrorCode::INCOMPATIBLE_BLOCK_MODE.
+     *
+     * Must be hardware-enforced.
+     */
     BLOCK_MODE = TagType:ENUM_REP | 4, /* BlockMode. */
-    DIGEST = TagType:ENUM_REP | 5,     /* Digest. */
-    PADDING = TagType:ENUM_REP | 6,    /* PaddingMode. */
-    CALLER_NONCE = TagType:BOOL | 7,   /* Allow caller to specify nonce or IV. */
-    MIN_MAC_LENGTH = TagType:UINT | 8, /* Minimum length of MAC or AEAD authentication tag in
-                                        * bits. */
-    // 9 reserved
-    EC_CURVE = TagType:ENUM | 10,      /* EcCurve. */
 
-    /* Algorithm-specific. */
+    /**
+     * Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
+     * and verification operations.  This tag is relevant to RSA, ECDSA and HMAC keys.  Possible
+     * values are defined by the Digest enum.
+     *
+     * This tag is repeatable for key generation/import.  For signing and verification operations,
+     * the caller must specify a digest in the additionalParams argument of begin().  If the digest
+     * is missing or the specified digest is not in the digests associated with the key, the
+     * operation must fail with ErrorCode::INCOMPATIBLE_DIGEST.
+     *
+     * Must be hardware-enforced.
+     */
+    DIGEST = TagType:ENUM_REP | 5,
+
+    /**
+     * Tag::PADDING specifies the padding modes that may be used with the key.  This tag is relevant
+     * to RSA, AES and 3DES keys.  Possible values are defined by the PaddingMode enum.
+     *
+     * PaddingMode::RSA_OAEP and PaddingMode::RSA_PKCS1_1_5_ENCRYPT are used only for RSA
+     * encryption/decryption keys and specify RSA OAEP padding and RSA PKCS#1 v1.5 randomized
+     * padding, respectively.  PaddingMode::RSA_PSS and PaddingMode::RSA_PKCS1_1_5_SIGN are used
+     * only for RSA signing/verification keys and specify RSA PSS padding and RSA PKCS#1 v1.5
+     * deterministic padding, respectively.
+     *
+     * PaddingMode::NONE may be used with either RSA, AES or 3DES keys.  For AES or 3DES keys, if
+     * PaddingMode::NONE is used with block mode ECB or CBC and the data to be encrypted or
+     * decrypted is not a multiple of the AES block size in length, the call to finish() must fail
+     * with ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * PaddingMode::PKCS7 may only be used with AES and 3DES keys, and only with ECB and CBC modes.
+     *
+     * In any case, if the caller specifies a padding mode that is not usable with the key's
+     * algorithm, the generation or import method must return ErrorCode::INCOMPATIBLE_PADDING_MODE.
+     *
+     * This tag is repeatable.  A padding mode must be specified in the call to begin().  If the
+     * specified mode is not authorized for the key, the operation must fail with
+     * ErrorCode::INCOMPATIBLE_BLOCK_MODE.
+     *
+     * Must be hardware-enforced.
+     */
+    PADDING = TagType:ENUM_REP | 6,
+
+    /**
+     * Tag::CALLER_NONCE specifies that the caller can provide a nonce for nonce-requiring
+     * operations.  This tag is boolean, so the possible values are true (if the tag is present) and
+     * false (if the tag is not present).
+     *
+     * This tag is used only for AES and 3DES keys, and is only relevant for CBC, CTR and GCM block
+     * modes.  If the tag is not present in a key's authorization list, implementations must reject
+     * any operation that provides Tag::NONCE to begin() with ErrorCode::CALLER_NONCE_PROHIBITED.
+     *
+     * Must be hardware-enforced.
+     */
+    CALLER_NONCE = TagType:BOOL | 7,
+
+    /**
+     * Tag::MIN_MAC_LENGTH specifies the minimum length of MAC that can be requested or verified
+     * with this key for HMAC keys and AES keys that support GCM mode.
+     *
+     * This value is the minimum MAC length, in bits.  It must be a multiple of 8 bits.  For HMAC
+     * keys, the value must be least 64 and no more than 512.  For GCM keys, the value must be at
+     * least 96 and no more than 128.  If the provided value violates these requirements,
+     * generateKey() or importKey() must return ErrorCode::UNSUPPORTED_KEY_SIZE.
+     *
+     * Must be hardware-enforced.
+     */
+    MIN_MAC_LENGTH = TagType:UINT | 8,
+
+    // Tag 9 reserved
+
+    /**
+     * Tag::EC_CURVE specifies the elliptic curve.  EC key generation requests may have
+     * Tag:EC_CURVE, Tag::KEY_SIZE, or both.  If both are provided and the size and curve do not
+     * match, IKeymasterDevice must return ErrorCode::INVALID_ARGUMENT.
+     *
+     * Must be hardware-enforced.
+     */
+    EC_CURVE = TagType:ENUM | 10,
+
+    /**
+     * Tag::RSA_PUBLIC_EXPONENT specifies the value of the public exponent for an RSA key pair.
+     * This tag is relevant only to RSA keys, and is required for all RSA keys.
+     *
+     * The value is a 64-bit unsigned integer that satisfies the requirements of an RSA public
+     * exponent.  This value must be a prime number.  IKeymasterDevice implementations must support
+     * the value 2^16+1 and may support other reasonable values.  If no exponent is specified or if
+     * the specified exponent is not supported, key generation must fail with
+     * ErrorCode::INVALID_ARGUMENT.
+     *
+     * Must be hardware-enforced.
+     */
     RSA_PUBLIC_EXPONENT = TagType:ULONG | 200,
-    // 201 reserved for ECIES
-    INCLUDE_UNIQUE_ID = TagType:BOOL | 202, /* If true, attestation certificates for this key must
-                                             * contain an application-scoped and time-bounded
-                                             * device-unique ID.*/
 
-    /* Other hardware-enforced. */
-    BLOB_USAGE_REQUIREMENTS = TagType:ENUM | 301, /* KeyBlobUsageRequirements. */
-    BOOTLOADER_ONLY = TagType:BOOL | 302,         /* Usable only by bootloader. */
-    ROLLBACK_RESISTANCE = TagType:BOOL | 303,     /* Whether key is rollback-resistant.  Specified
-                                                   * in the key description provided to generateKey
-                                                   * or importKey if rollback resistance is desired.
-                                                   * If the implementation cannot provide rollback
-                                                   * resistance, it must return
-                                                   * ROLLBACK_RESISTANCE_UNAVAILABLE. */
+    // Tag 201 reserved
 
-    /* HARDWARE_TYPE specifies the type of the secure hardware that is requested for the key
-     * generation / import.  See the SecurityLevel enum.  In the absence of this tag, keystore must
-     * use TRUSTED_ENVIRONMENT.  If this tag is present and the requested hardware type is not
-     * available, Keymaster returns HARDWARE_TYPE_UNAVAILABLE. This tag is not included in
-     * attestations, but hardware type must be reflected in the Keymaster SecurityLevel of the
-     * attestation header. */
+    /**
+     * Tag::INCLUDE_UNIQUE_ID is specified during key generation to indicate that an attestation
+     * certificate for the generated key should contain an application-scoped and time-bounded
+     * device-unique ID.  See Tag::UNIQUE_ID.
+     *
+     * Must be hardware-enforced.
+     */
+    INCLUDE_UNIQUE_ID = TagType:BOOL | 202,
+
+    /**
+     * Tag::BLOB_USAGE_REQUIREMENTS specifies the necessary system environment conditions for the
+     * generated key to be used.  Possible values are defined by the KeyBlobUsageRequirements enum.
+     *
+     * This tag is specified by the caller during key generation or import to require that the key
+     * is usable in the specified condition.  If the caller specifies Tag::BLOB_USAGE_REQUIREMENTS
+     * with value KeyBlobUsageRequirements::STANDALONE the IKeymasterDevice must return a key blob
+     * that can be used without file system support.  This is critical for devices with encrypted
+     * disks, where the file system may not be available until after a Keymaster key is used to
+     * decrypt the disk.
+     *
+     * Must be hardware-enforced.
+     */
+    BLOB_USAGE_REQUIREMENTS = TagType:ENUM | 301,
+
+    /**
+     * Tag::BOOTLOADER_ONLY specifies only the bootloader can use the key.
+     *
+     * Any attempt to use a key with Tag::BOOTLOADER_ONLY from the Android system must fail with
+     * ErrorCode::INVALID_KEY_BLOB.
+     *
+     * Must be hardware-enforced.
+     */
+    BOOTLOADER_ONLY = TagType:BOOL | 302,
+
+    /**
+     * Tag::ROLLBACK_RESISTANCE specifies that the key has rollback resistance, meaning that when
+     * deleted with deleteKey() or deleteAllKeys(), the key is guaranteed to be permanently deleted
+     * and unusable.  It's possible that keys without this tag could be deleted and then restored
+     * from backup.
+     *
+     * This tag is specified by the caller during key generation or import to require.  If the
+     * IKeymasterDevice cannot guarantee rollback resistance for the specified key, it must return
+     * ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE.  IKeymasterDevice implementations are not
+     * required to support rollback resistance.
+     *
+     * Must be hardwared-enforced.
+     */
+    ROLLBACK_RESISTANCE = TagType:BOOL | 303,
+
+    // Reserved for future use.
     HARDWARE_TYPE = TagType:ENUM | 304,
 
-    /*
-     * Tags that should be semantically enforced by hardware if possible and will otherwise be
-     * enforced by software (keystore).
+    /**
+     * Tag::ACTIVE_DATETIME specifies the date and time at which the key becomes active, in
+     * milliseconds since Jan 1, 1970.  If a key with this tag is used prior to the specified date
+     * and time, IKeymasterDevice::begin() must return ErrorCode::KEY_NOT_YET_VALID;
+     *
+     * Need not be hardware-enforced.
      */
+    ACTIVE_DATETIME = TagType:DATE | 400, /* Start of validity. */
 
-    /* Key validity period */
-    ACTIVE_DATETIME = TagType:DATE | 400,             /* Start of validity. */
-    ORIGINATION_EXPIRE_DATETIME = TagType:DATE | 401, /* Date when new "messages" should no longer
-                                                       * be created. */
-    USAGE_EXPIRE_DATETIME = TagType:DATE | 402,       /* Date when existing "messages" should no
-                                                       * longer be trusted. */
-    MIN_SECONDS_BETWEEN_OPS = TagType:UINT | 403,     /* Minimum elapsed time between
-                                                       * cryptographic operations with the key. */
-    MAX_USES_PER_BOOT = TagType:UINT | 404,           /* Number of times the key can be used per
-                                                       * boot. */
+    /**
+     * Tag::ORIGINATION_EXPIRE_DATETIME specifies the date and time at which the key expires for
+     * signing and encryption purposes.  After this time, any attempt to use a key with
+     * KeyPurpose::SIGN or KeyPurpose::ENCRYPT provided to begin() must fail with
+     * ErrorCode::KEY_EXPIRED.
+     *
+     * The value is a 64-bit integer representing milliseconds since January 1, 1970.
+     *
+     * Need not be hardware-enforced.
+     */
+    ORIGINATION_EXPIRE_DATETIME = TagType:DATE | 401,
 
-    /* User authentication */
-    // 500 reserved
-    USER_ID = TagType:UINT | 501,             /* Android ID of authorized user or authenticator(s), */
+    /**
+     * Tag::USAGE_EXPIRE_DATETIME specifies the date and time at which the key expires for
+     * verification and decryption purposes.  After this time, any attempt to use a key with
+     * KeyPurpose::VERIFY or KeyPurpose::DECRYPT provided to begin() must fail with
+     * ErrorCode::KEY_EXPIRED.
+     *
+     * The value is a 64-bit integer representing milliseconds since January 1, 1970.
+     *
+     * Need not be hardware-enforced.
+     */
+    USAGE_EXPIRE_DATETIME = TagType:DATE | 402,
+
+    /**
+     * Tag::MIN_SECONDS_BETWEEN_OPS specifies the minimum amount of time that elapses between
+     * allowed operations using a key.  This can be used to rate-limit uses of keys in contexts
+     * where unlimited use may enable brute force attacks.
+     *
+     * The value is a 32-bit integer representing seconds between allowed operations.
+     *
+     * When a key with this tag is used in an operation, the IKeymasterDevice must start a timer
+     * during the finish() or abort() call.  Any call to begin() that is received before the timer
+     * indicates that the interval specified by Tag::MIN_SECONDS_BETWEEN_OPS has elapsed must fail
+     * with ErrorCode::KEY_RATE_LIMIT_EXCEEDED.  This implies that the IKeymasterDevice must keep a
+     * table of use counters for keys with this tag.  Because memory is often limited, this table
+     * may have a fixed maximum size and Keymaster may fail operations that attempt to use keys with
+     * this tag when the table is full.  The table must acommodate at least 8 in-use keys and
+     * aggressively reuse table slots when key minimum-usage intervals expire.  If an operation
+     * fails because the table is full, Keymaster returns ErrorCode::TOO_MANY_OPERATIONS.
+     *
+     * Must be hardware-enforced.
+     */
+    MIN_SECONDS_BETWEEN_OPS = TagType:UINT | 403,
+
+    /**
+     * Tag::MAX_USES_PER_BOOT specifies the maximum number of times that a key may be used between
+     * system reboots.  This is another mechanism to rate-limit key use.
+     *
+     * The value is a 32-bit integer representing uses per boot.
+     *
+     * When a key with this tag is used in an operation, a key-associated counter must be
+     * incremented during the begin() call.  After the key counter has exceeded this value, all
+     * subsequent attempts to use the key must fail with ErrorCode::MAX_OPS_EXCEEDED, until the
+     * device is restarted.  This implies that the IKeymasterDevice must keep a table of use
+     * counters for keys with this tag.  Because Keymaster memory is often limited, this table can
+     * have a fixed maximum size and Keymaster can fail operations that attempt to use keys with
+     * this tag when the table is full.  The table needs to acommodate at least 8 keys.  If an
+     * operation fails because the table is full, IKeymasterDevice must
+     * ErrorCode::TOO_MANY_OPERATIONS.
+     *
+     * Must be hardware-enforced.
+     */
+    MAX_USES_PER_BOOT = TagType:UINT | 404,
+
+    /**
+     * Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
+     *
+     * Must not be hardware-enforced.
+     */
+    USER_ID = TagType:UINT | 501,
+
+    /**
+     * Tag::USER_SECURE_ID specifies that a key may only be used under a particular secure user
+     * authentication state.  This tag is mutually exclusive with Tag::NO_AUTH_REQUIRED.
+     *
+     * The value is a 64-bit integer specifying the authentication policy state value which must be
+     * present in the userId or authenticatorId field of a HardwareAuthToken provided to begin(),
+     * update(), or finish().  If a key with Tag::USER_SECURE_ID is used without a HardwareAuthToken
+     * with the matching userId or authenticatorId, the IKeymasterDevice must return
+     * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * Tag::USER_SECURE_ID interacts with Tag::AUTH_TIMEOUT in a very important way.  If
+     * Tag::AUTH_TIMEOUT is present in the key's characteristics then the key is a "timeout-based"
+     * key, and may only be used if the difference between the current time when begin() is called
+     * and the timestamp in the HardwareAuthToken is less than the value in Tag::AUTH_TIMEOUT * 1000
+     * (the multiplier is because Tag::AUTH_TIMEOUT is in seconds, but the HardwareAuthToken
+     * timestamp is in milliseconds).  Otherwise the IKeymasterDevice must returrn
+     * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * If Tag::AUTH_TIMEOUT is not present, then the key is an "auth-per-operation" key.  In this
+     * case, begin() must not require a HardwareAuthToken with appropriate contents.  Instead,
+     * update() and finish() must receive a HardwareAuthToken with Tag::USER_SECURE_ID value in
+     * userId or authenticatorId fields, and the current operation's operation handle in the
+     * challenge field.  Otherwise the IKeymasterDevice must returrn
+     * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * This tag is repeatable.  If repeated, and any one of the values matches the HardwareAuthToken
+     * as described above, the key is authorized for use.  Otherwise the operation must fail with
+     * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
+     * Must be hardware-enforced.
+     */
     USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
-                                               * Disallowed if NO_AUTH_REQUIRED is present. */
-    NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
-    USER_AUTH_TYPE = TagType:ENUM | 504,      /* Bitmask of authenticator types allowed when
-                                               * USER_SECURE_ID contains a secure user ID, rather
-                                               * than a secure authenticator ID.  Defined in
-                                               * HardwareAuthenticatorType. */
-    AUTH_TIMEOUT = TagType:UINT | 505,        /* Required freshness of user authentication for
-                                               * private/secret key operations, in seconds.  Public
-                                               * key operations require no authentication.  If
-                                               * absent, authentication is required for every use.
-                                               * Authentication state is lost when the device is
-                                               * powered off. */
-    ALLOW_WHILE_ON_BODY =  TagType:BOOL | 506, /* Allow key to be used after authentication timeout
-                                                * if device is still on-body (requires secure
-                                                * on-body sensor. */
+                                                 * Disallowed if NO_AUTH_REQUIRED is present. */
+
+    /**
+     * Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key.  This tag
+     * is mutually exclusive with Tag::USER_SECURE_ID.
+     *
+     * Must be hardware-enforced.
+     */
+    NO_AUTH_REQUIRED = TagType:BOOL | 503, /* If key is usable without authentication. */
+
+    /**
+     * Tag::USER_AUTH_TYPE specifies the types of user authenticators that may be used to authorize
+     * this key.
+     *
+     * The value is one or more values from HardwareAuthenticatorType, ORed together.
+     *
+     * When IKeymasterDevice is requested to perform an operation with a key with this tag, it must
+     * receive a HardwareAuthToken and one or more bits must be set in both the HardwareAuthToken's
+     * authenticatorType field and the Tag::USER_AUTH_TYPE value.  That is, it must be true that
+     *
+     *    (token.authenticatorType & tag_user_auth_type) != 0
+     *
+     * where token.authenticatorType is the authenticatorType field of the HardwareAuthToken and
+     * tag_user_auth_type is the value of Tag:USER_AUTH_TYPE.
+     *
+     * Must be hardware-enforced.
+     */
+    USER_AUTH_TYPE = TagType:ENUM | 504,
+
+    /**
+     * Tag::AUTH_TIMEOUT specifies the time in seconds for which the key is authorized for use,
+     * after user authentication.  If
+     * Tag::USER_SECURE_ID is present and this tag is not, then the key requies authentication for
+     * every usage (see begin() for the details of the authentication-per-operation flow).
+     *
+     * The value is a 32-bit integer specifying the time in seconds after a successful
+     * authentication of the user specified by Tag::USER_SECURE_ID with the authentication method
+     * specified by Tag::USER_AUTH_TYPE that the key can be used.
+     *
+     * Must be hardware-enforced.
+     */
+    AUTH_TIMEOUT = TagType:UINT | 505,
+
+    /**
+     * Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication timeout if
+     * device is still on-body (requires on-body sensor).
+     *
+     * Cannot be hardware-enforced.
+     */
+    ALLOW_WHILE_ON_BODY = TagType:BOOL | 506,
 
     /**
      * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
@@ -166,7 +447,7 @@
      *     the non-secure world, which means an attacker who has compromised Android can spoof
      *     password authentication.
      *
-     * Note that no mechanism is defined for delivering proof of presence to Keymaster,
+     * Note that no mechanism is defined for delivering proof of presence to an IKeymasterDevice,
      * except perhaps as implied by an auth token.  This means that Keymaster must be able to check
      * proof of presence some other way.  Further, the proof of presence must be performed between
      * begin() and the first call to update() or finish().  If the first update() or the finish()
@@ -179,111 +460,420 @@
      * called on one key with TRUSTED_USER_PRESENCE_REQUIRED, and another begin() comes in for that
      * key or another with TRUSTED_USER_PRESENCE_REQUIRED, Keymaster must return
      * ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED.
+     *
+     * Must be hardware-enforced.
      */
     TRUSTED_USER_PRESENCE_REQUIRED = TagType:BOOL | 507,
 
-    /** TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and specifies
-     *  that this key must not be usable unless the user provides confirmation of the data to be
-     *  signed. Confirmation is proven to keymaster via an approval token. See CONFIRMATION_TOKEN,
-     *  as well as the ConfirmatinUI HAL.
+    /** Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
+     *  specifies that this key must not be usable unless the user provides confirmation of the data
+     *  to be signed.  Confirmation is proven to keymaster via an approval token.  See
+     *  CONFIRMATION_TOKEN, as well as the ConfirmatinUI HAL.
      *
      * If an attempt to use a key with this tag does not have a cryptographically valid
      * CONFIRMATION_TOKEN provided to finish() or if the data provided to update()/finish() does not
-     * match the data described in the token, keymaster must return NO_USER_CONFIRMATION. */
+     * match the data described in the token, keymaster must return NO_USER_CONFIRMATION.
+     *
+     * Must be hardware-enforced.
+     */
     TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508,
 
-    UNLOCKED_DEVICE_REQUIRED = TagType:BOOL | 509, /* Require the device screen to be unlocked if
-                                                    * the key is used. */
+    /**
+     * Tag::UNLOCKED_DEVICE_REQUIRED specifies that the key may only be used when the device is
+     * unlocked.
+     *
+     * Must be software-enforced.
+     */
+    UNLOCKED_DEVICE_REQUIRED = TagType:BOOL | 509,
 
-    /* Application access control */
-    APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
+    /**
+     * Tag::APPLICATION_ID.  When provided to generateKey or importKey, this tag specifies data
+     * that is necessary during all uses of the key.  In particular, calls to exportKey() and
+     * getKeyCharacteristics() must provide the same value to the clientId parameter, and calls to
+     * begin must provide this tag and the same associated data as part of the inParams set.  If
+     * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+     *
+     * The content of this tag must be bound to the key cryptographically, meaning it must not be
+     * possible for an adversary who has access to all of the secure world secrets but does not have
+     * access to the tag content to decrypt the key without brute-forcing the tag content, which
+     * applications can prevent by specifying sufficiently high-entropy content.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    APPLICATION_ID = TagType:BYTES | 601,
 
     /*
      * Semantically unenforceable tags, either because they have no specific meaning or because
      * they're informational only.
      */
-    APPLICATION_DATA = TagType:BYTES | 700, /* Data provided by authorized application. */
-    CREATION_DATETIME = TagType:DATE | 701, /* Key creation time */
-    ORIGIN = TagType:ENUM | 702,            /* keymaster_key_origin_t. */
-    // 703 is unused.
-    ROOT_OF_TRUST = TagType:BYTES | 704,         /* Root of trust ID. */
-    OS_VERSION = TagType:UINT | 705,             /* Version of system (keymaster2) */
-    OS_PATCHLEVEL = TagType:UINT | 706,          /* Patch level of system (keymaster2) */
-    UNIQUE_ID = TagType:BYTES | 707,             /* Used to provide unique ID in attestation */
-    ATTESTATION_CHALLENGE = TagType:BYTES | 708, /* Used to provide challenge in attestation */
-    ATTESTATION_APPLICATION_ID = TagType:BYTES | 709, /* Used to identify the set of possible
-                                                       * applications of which one has initiated a
-                                                       * key attestation */
-    ATTESTATION_ID_BRAND = TagType:BYTES | 710,   /* Used to provide the device's brand name to be
-                                                   * included in attestation */
-    ATTESTATION_ID_DEVICE = TagType:BYTES | 711,  /* Used to provide the device's device name to
-                                                   * be included in attestation */
-    ATTESTATION_ID_PRODUCT = TagType:BYTES | 712, /* Used to provide the device's product name to
-                                                   * be included in attestation */
-    ATTESTATION_ID_SERIAL =
-    TagType:BYTES | 713,                       /* Used to provide the device's serial number to be
-                                                * included in attestation */
-    ATTESTATION_ID_IMEI = TagType:BYTES | 714, /* Used to provide the device's IMEI to be included
-                                                * in attestation */
-    ATTESTATION_ID_MEID = TagType:BYTES | 715, /* Used to provide the device's MEID to be included
-                                                * in attestation */
-    ATTESTATION_ID_MANUFACTURER =
-    TagType:BYTES | 716,                        /* Used to provide the device's manufacturer
-                                                 * name to be included in attestation */
-    ATTESTATION_ID_MODEL = TagType:BYTES | 717, /* Used to provide the device's model name to be
-                                                 * included in attestation */
 
     /**
-     * Patch level of vendor image.  The value is an integer of the form YYYYMM, where YYYY is the
-     * four-digit year when the vendor image was released and MM is the two-digit month.  During
-     * each boot, the bootloader must provide the patch level of the vendor image to keymaser
-     * (mechanism is implemntation-defined).  When keymaster keys are created or updated, the
-     * VENDOR_PATCHLEVEL tag must be cryptographically bound to the keys, with the current value as
-     * provided by the bootloader.  When keys are used, keymaster must verify that the
-     * VENDOR_PATCHLEVEL bound to the key matches the current value.  If they do not match,
-     * keymaster must return ErrorCode::KEY_REQUIRES_UPGRADE.  The client must then call upgradeKey.
+     * Tag::APPLICATION_DATA.  When provided to generateKey or importKey, this tag specifies data
+     * that is necessary during all uses of the key.  In particular, calls to exportKey() and
+     * getKeyCharacteristics() must provide the same value to the appData parameter, and calls to
+     * begin must provide this tag and the same associated data as part of the inParams set.  If
+     * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+     *
+     * The content of this tag msut be bound to the key cryptographically, meaning it must not be
+     * possible for an adversary who has access to all of the secure world secrets but does not have
+     * access to the tag content to decrypt the key without brute-forcing the tag content, which
+     * applications can prevent by specifying sufficiently high-entropy content.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    APPLICATION_DATA = TagType:BYTES | 700,
+
+    /**
+     * Tag::CREATION_DATETIME specifies the date and time the key was created, in milliseconds since
+     * January 1, 1970.  This tag is optional and informational only.
+     *
+     * Tag::CREATED is informational only, and not enforced by anything.  Must be in the
+     * software-enforced list, if provided.
+     */
+    CREATION_DATETIME = TagType:DATE | 701,
+
+    /**
+     * Tag::ORIGIN specifies where the key was created, if known.  This tag must not be specified
+     * during key generation or import, and must be added to the key characteristics by the
+     * IKeymasterDevice.  The possible values are defined in the KeyOrigin enum.
+     *
+     * Must be hardware-enforced.
+     */
+    ORIGIN = TagType:ENUM | 702,
+
+    // 703 is unused.
+
+    /**
+     * Tag::ROOT_OF_TRUST specifies the root of trust, the key used by verified boot to validate the
+     * operating system booted (if any).  This tag is never provided to or returned from Keymaster
+     * in the key characteristics.  It exists only to define the tag for use in the attestation
+     * record.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ROOT_OF_TRUST = TagType:BYTES | 704,
+
+    /**
+     * Tag::OS_VERSION specifies the system OS version with which the key may be used.  This tag is
+     * never sent to the IKeymasterDevice, but is added to the hardware-enforced authorization list
+     * by the TA.  Any attempt to use a key with a Tag::OS_VERSION value different from the
+     * currently-running OS version must cause begin(), getKeyCharacteristics() or exportKey() to
+     * return ErrorCode::KEY_REQUIRES_UPGRADE.  See upgradeKey() for details.
+     *
+     * The value of the tag is an integer of the form MMmmss, where MM is the major version number,
+     * mm is the minor version number, and ss is the sub-minor version number.  For example, for a
+     * key generated on Android version 4.0.3, the value would be 040003.
+     *
+     * The IKeymasterDevice HAL must read the current OS version from the system property
+     * ro.build.version.release and deliver it to the secure environment when the HAL is first
+     * loaded (mechanism is implementation-defined).  The secure environment must not accept another
+     * version until after the next boot.  If the content of ro.build.version.release has additional
+     * version information after the sub-minor version number, it must not be included in
+     * Tag::OS_VERSION.  If the content is non-numeric, the secure environment must use 0 as the
+     * system version.
+     *
+     * Must be hardware-enforced.
+     */
+    OS_VERSION = TagType:UINT | 705,
+
+    /**
+     * Tag::OS_PATCHLEVEL specifies the system security patch level with which the key may be used.
+     * This tag is never sent to the keymaster TA, but is added to the hardware-enforced
+     * authorization list by the TA.  Any attempt to use a key with a Tag::OS_PATCHLEVEL value
+     * different from the currently-running system patchlevel must cause begin(),
+     * getKeyCharacteristics() or exportKey() to return ErrorCode::KEY_REQUIRES_UPGRADE.  See
+     * upgradeKey() for details.
+     *
+     * The value of the tag is an integer of the form YYYYMM, where YYYY is the four-digit year of
+     * the last update and MM is the two-digit month of the last update.  For example, for a key
+     * generated on an Android device last updated in December 2015, the value would be 201512.
+     *
+     * The IKeymasterDevice HAL must read the current system patchlevel from the system property
+     * ro.build.version.security_patch and deliver it to the secure environment when the HAL is
+     * first loaded (mechanism is implementation-defined).  The secure environment must not accept
+     * another patchlevel until after the next boot.
+     *
+     * Must be hardware-enforced.
+     */
+    OS_PATCHLEVEL = TagType:UINT | 706,
+
+    /**
+     * Tag::UNIQUE_ID specifies a unique, time-based identifier.  This tag is never provided to or
+     * returned from Keymaster in the key characteristics.  It exists only to define the tag for use
+     * in the attestation record.
+     *
+     * When a key with Tag::INCLUDE_UNIQUE_ID is attested, the unique ID is added to the attestation
+     * record.  The value is a 128-bit hash that is unique per device and per calling application,
+     * and changes monthly and on most password resets.  It is computed with:
+     *
+     *    HMAC_SHA256(T || C || R, HBK)
+     *
+     * Where:
+     *
+     *    T is the "temporal counter value", computed by dividing the value of
+     *      Tag::CREATION_DATETIME by 2592000000, dropping any remainder.  T changes every 30 days
+     *      (2592000000 = 30 * 24 * 60 * 60 * 1000).
+     *
+     *    C is the value of Tag::ATTESTATION_APPLICATION_ID that is provided to attestKey().
+     *
+     *    R is 1 if Tag::RESET_SINCE_ID_ROTATION was provided to attestKey or 0 if the tag was not
+     *      provided.
+     *
+     *    HBK is a unique hardware-bound secret known to the secure environment and never revealed
+     *    by it.  The secret must contain at least 128 bits of entropy and be unique to the
+     *    individual device (probabilistic uniqueness is acceptable).
+     *
+     *    HMAC_SHA256 is the HMAC function, with SHA-2-256 as the hash.
+     *
+     * The output of the HMAC function must be truncated to 128 bits.
+     *
+     * Must be hardware-enforced.
+     */
+    UNIQUE_ID = TagType:BYTES | 707,
+
+    /**
+     * Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attestKey() method,
+     * which must place the value in the KeyDescription SEQUENCE of the attestation extension.  See
+     * attestKey().
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_CHALLENGE = TagType:BYTES | 708, /* Used to provide challenge in attestation */
+
+    /**
+     * Tag::ATTESTATION_APPLICATION_ID identifies the set of applications which may use a key, used
+     * only with attestKey().
+     *
+     * The content of Tag::ATTESTATION_APPLICATION_ID is a DER-encoded ASN.1 structure, with the
+     * following schema:
+     *
+     * AttestationApplicationId ::= SEQUENCE {
+     *     packageInfoRecords SET OF PackageInfoRecord,
+     *     signatureDigests   SET OF OCTET_STRING,
+     * }
+     *
+     * PackageInfoRecord ::= SEQUENCE {
+     *     packageName        OCTET_STRING,
+     *     version            INTEGER,
+     * }
+     *
+     * See system/security/keystore/keystore_attestation_id.cpp for details of construction.
+     * IKeymasterDevice implementers do not need to create or parse the ASN.1 structure, but only
+     * copy the tag value into the attestation record.  The DER-encoded string must not exceed 1 KiB
+     * in length.
+     *
+     * Cannot be hardware-enforced.
+     */
+    ATTESTATION_APPLICATION_ID = TagType:BYTES | 709,
+
+    /**
+     * Tag::ATTESTATION_ID_BRAND provides the device's brand name, as returned by Build.BRAND in
+     * Android, to attestKey().  This field must be set only when requesting attestation of the
+     * device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_BRAND = TagType:BYTES | 710,
+
+    /**
+     * Tag::ATTESTATION_ID_DEVICE provides the device's device name, as returned by Build.DEVICE in
+     * Android, to attestKey().  This field must be set only when requesting attestation of the
+     * device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_DEVICE = TagType:BYTES | 711,
+
+    /**
+     * Tag::ATTESTATION_ID_PRODUCT provides the device's product name, as returned by Build.PRODUCT
+     * in Android, to attestKey().  This field must be set only when requesting attestation of the
+     * device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_PRODUCT = TagType:BYTES | 712,
+
+    /**
+     * Tag::ATTESTATION_ID_SERIAL the device's serial number.  This field must be set only when
+     * requesting attestation of the device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_SERIAL = TagType:BYTES | 713,
+
+    /**
+     * Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attestKey().
+     * This field must be set only when requesting attestation of the device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_IMEI = TagType:BYTES | 714, /* Used to provide the device's IMEI to be included
+                                                  * in attestation */
+
+    /**
+     * Tag::ATTESTATION_ID_MEID provides the MEIDs for all radios on the device to attestKey().
+     * This field must be set only when requesting attestation of the device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_MEID = TagType:BYTES | 715, /* Used to provide the device's MEID to be included
+                                                  * in attestation */
+
+    /**
+     * Tag::ATTESTATION_ID_MANUFACTURER provides the device's manufacturer name, as returned by
+     * Build.MANUFACTURER in Android, to attstKey().  This field must be set only when requesting
+     * attestation of the device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_MANUFACTURER = TagType:BYTES | 716,
+
+    /**
+     * Tag::ATTESTATION_ID_MODEL provides the device's model name, as returned by Build.MODEL in
+     * Android, to attestKey().  This field must be set only when requesting attestation of the
+     * device's identifiers.
+     *
+     * If the device does not support ID attestation (or destroyAttestationIds() was previously
+     * called and the device can no longer attest its IDs), any key attestation request that
+     * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    ATTESTATION_ID_MODEL = TagType:BYTES | 717,
+
+    /**
+     * Tag::VENDOR_PATCHLEVEL specifies the vendor image security patch level with which the key may
+     * be used.  This tag is never sent to the keymaster TA, but is added to the hardware-enforced
+     * authorization list by the TA.  Any attempt to use a key with a Tag::VENDOR_PATCHLEVEL value
+     * different from the currently-running system patchlevel must cause begin(),
+     * getKeyCharacteristics() or exportKey() to return ErrorCode::KEY_REQUIRES_UPGRADE.  See
+     * upgradeKey() for details.
+     *
+     * The value of the tag is an integer of the form YYYYMMDD, where YYYY is the four-digit year of
+     * the last update, MM is the two-digit month and DD is the two-digit day of the last
+     * update.  For example, for a key generated on an Android device last updated on June 5, 2018,
+     * the value would be 20180605.
+     *
+     * The IKeymasterDevice HAL must read the current vendor patchlevel from the system property
+     * ro.vendor.build.security_patch and deliver it to the secure environment when the HAL is first
+     * loaded (mechanism is implementation-defined).  The secure environment must not accept another
+     * patchlevel until after the next boot.
+     *
+     * Must be hardware-enforced.
      */
     VENDOR_PATCHLEVEL = TagType:UINT | 718,
 
     /**
-     * Patch level of boot image.  The value is an integer of the form YYYYMM, where YYYY is the
-     * four-digit year when the boot image was released and MM is the two-digit month.  During each
-     * boot, the bootloader must provide the patch level of the boot image to keymaser (mechanism is
-     * implemntation-defined).  When keymaster keys are created or updated, the BOOT_PATCHLEVEL tag
-     * must be cryptographically bound to the keys, with the current value as provided by the
-     * bootloader.  When keys are used, keymaster must verify that the BOOT_PATCHLEVEL bound to the
-     * key matches the current value.  If they do not match, keymaster must return
-     * ErrorCode::KEY_REQUIRES_UPGRADE.  The client must then call upgradeKey.
+     * Tag::BOOT_PATCHLEVEL specifies the boot image (kernel) security patch level with which the
+     * key may be used.  This tag is never sent to the keymaster TA, but is added to the
+     * hardware-enforced authorization list by the TA.  Any attempt to use a key with a
+     * Tag::BOOT_PATCHLEVEL value different from the currently-running system patchlevel must
+     * cause begin(), getKeyCharacteristics() or exportKey() to return
+     * ErrorCode::KEY_REQUIRES_UPGRADE.  See upgradeKey() for details.
+     *
+     * The value of the tag is an integer of the form YYYYMMDD, where YYYY is the four-digit year of
+     * the last update, MM is the two-digit month and DD is the two-digit day of the last
+     * update.  For example, for a key generated on an Android device last updated on June 5, 2018,
+     * the value would be 20180605.  If the day is not known, 00 may be substituted.
+     *
+     * During each boot, the bootloader must provide the patch level of the boot image to the secure
+     * envirionment (mechanism is implementation-defined).
+     *
+     * Must be hardware-enforced.
      */
     BOOT_PATCHLEVEL = TagType:UINT | 719,
 
-    /* Tags used only to provide data to or receive data from operations */
-    ASSOCIATED_DATA = TagType:BYTES | 1000, /* Used to provide associated data for AEAD modes. */
-    NONCE = TagType:BYTES | 1001,           /* Nonce or Initialization Vector */
-    MAC_LENGTH = TagType:UINT | 1003,       /* MAC or AEAD authentication tag length in bits. */
-
-    RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004, /* Whether the device has beeen factory reset
-                                                    * since the last unique ID rotation.  Used for
-                                                    * key attestation. */
+    /**
+     * Tag::ASSOCIATED_DATA Provides "associated data" for AES-GCM encryption or decryption.  This
+     * tag is provided to update and specifies data that is not encrypted/decrypted, but is used in
+     * computing the GCM tag.
+     *
+     * Must never appear KeyCharacteristics.
+     */
+    ASSOCIATED_DATA = TagType:BYTES | 1000,
 
     /**
-     * CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user confirmed a
-     * signing request. The content is a full-length HMAC-SHA256 value. See the ConfirmationUI HAL
-     * for details of token computation.
+     * Tag::NONCE is used to provide or return a nonce or Initialization Vector (IV) for AES-GCM,
+     * AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption.  This tag is provided to begin during
+     * encryption and decryption operations.  It is only provided to begin if the key has
+     * Tag::CALLER_NONCE.  If not provided, an appropriate nonce or IV must be randomly generated by
+     * Keymaster and returned from begin.
+     *
+     * The value is a blob, an arbitrary-length array of bytes.  Allowed lengths depend on the mode:
+     * GCM nonces are 12 bytes in length; AES-CBC and AES-CTR IVs are 16 bytes in length, 3DES-CBC
+     * IVs are 8 bytes in length.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    NONCE = TagType:BYTES | 1001,
+
+    /**
+     * Tag::MAC_LENGTH provides the requested length of a MAC or GCM authentication tag, in bits.
+     *
+     * The value is the MAC length in bits.  It must be a multiple of 8 and at least as large as the
+     * value of Tag::MIN_MAC_LENGTH associated with the key.  Otherwise, begin() must return
+     * ErrorCode::INVALID_MAC_LENGTH.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    MAC_LENGTH = TagType:UINT | 1003,
+
+    /**
+     * Tag::RESET_SINCE_ID_ROTATION specifies whether the device has been factory reset since the
+     * last unique ID rotation.  Used for key attestation.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004,
+
+    /**
+     * Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user
+     * confirmed a signing request.  The content is a full-length HMAC-SHA256 value.  See the
+     * ConfirmationUI HAL for details of token computation.
+     *
+     * Must never appear in KeyCharacteristics.
      */
     CONFIRMATION_TOKEN = TagType:BYTES | 1005,
 };
 
 /**
- * Algorithms provided by keymaser implementations.
+ * Algorithms provided by IKeymasterDevice implementations.
  */
 enum Algorithm : uint32_t {
     /** Asymmetric algorithms. */
     RSA = 1,
-    // DSA = 2, -- Removed, do not re-use value 2.
+    // 2 removed, do not reuse.
     EC = 3,
 
-    /** Block ciphers algorithms */
+    /** Block cipher algorithms */
     AES = 32,
     TRIPLE_DES = 33,
 
@@ -393,12 +983,12 @@
  * Possible purposes of a key (or pair).
  */
 enum KeyPurpose : uint32_t {
-    ENCRYPT = 0,    /* Usable with RSA, EC and AES keys. */
-    DECRYPT = 1,    /* Usable with RSA, EC and AES keys. */
-    SIGN = 2,       /* Usable with RSA, EC and HMAC keys. */
-    VERIFY = 3,     /* Usable with RSA, EC and HMAC keys. */
+    ENCRYPT = 0, /* Usable with RSA, EC and AES keys. */
+    DECRYPT = 1, /* Usable with RSA, EC and AES keys. */
+    SIGN = 2,    /* Usable with RSA, EC and HMAC keys. */
+    VERIFY = 3,  /* Usable with RSA, EC and HMAC keys. */
     /* 4 is reserved */
-    WRAP_KEY = 5,   /* Usable with wrapping keys. */
+    WRAP_KEY = 5, /* Usable with wrapping keys. */
 };
 
 /**
@@ -481,6 +1071,8 @@
     VERSION_MISMATCH = -101,
 
     UNKNOWN_ERROR = -1000,
+
+    // Implementer's namespace for error codes starts at -10000.
 };
 
 /**
@@ -521,39 +1113,10 @@
     SOFTWARE = 0,
     TRUSTED_ENVIRONMENT = 1,
     /**
-     * STRONGBOX specifies that the secure hardware satisfies the following requirements:
-     *
-     *    a) Has a discrete CPU.  The StrongBox device must not be the same CPU that is used to run
-     *       the Android non-secure world, or any other untrusted code.  The StrongBox CPU must not
-     *       share cache, RAM or any other critical resources with any device that runs untrusted
-     *       code.
-     *
-     *    b) Has integral secure storage.  The StrongBox device must have its own non-volatile
-     *       storage that is not accessible by any other hardware component.
-     *
-     *    c) Has a high-quality True Random Number Generator.  The StrongBox device must have sole
-     *       control of and access to a high-quality TRNG which it uses for generating necessary
-     *       random bits.  It must combine the output of this TRNG with caller-provided entropy in a
-     *       strong CPRNG, as do non-Strongbox Keymaster implementations.
-     *
-     *    d) Is enclosed in tamper-resistant packaging.  The StrongBox device must have
-     *       tamper-resistant packaging which provides obstacles to physical penetration which are
-     *       higher than those provided by normal integrated circuit packages.
-     *
-     *    e) Provides side-channel resistance.  The StrongBox device must implement resistance
-     *       against common side-channel attacks, including power analysis, timing analysis, EM
-     *       snooping, etc.
-     *
-     * Devices with StrongBox Keymasters must also have a non-StrongBox Keymaster, which lives in
-     * the higher-performance TEE.  Keystore must load both StrongBox (if available) and
-     * non-StrongBox HALs and route key generation/import requests appropriately.  Callers that want
-     * StrongBox keys must add Tag::HARDWARE_TYPE with value SecurityLevel::STRONGBOX to the key
-     * description provided to generateKey or importKey.  Keytore must route the request to a
-     * StrongBox HAL (a HAL whose isStrongBox method returns true).  Keymaster implementations that
-     * receive a request for a Tag::HARDWARE_TYPE that is inappropriate must fail with
-     * ErrorCode::HARDWARE_TYPE_UNAVAILABLE.
+     * STRONGBOX specifies that the secure hardware satisfies the requirements specified in CDD
+     * 9.11.2.
      */
-    STRONGBOX = 2,              /* See IKeymaster::isStrongBox */
+    STRONGBOX = 2,
 };
 
 /**
@@ -564,17 +1127,19 @@
     X509 = 0,
     /** PCKS#8 format, asymmetric key pair import. */
     PKCS8 = 1,
-    /** Raw bytes, for symmetric key import and export. */
+    /** Raw bytes, for symmetric key import. */
     RAW = 3,
 };
 
 struct KeyParameter {
     /**
-     * Discriminates the uinon/blob field used.  The blob cannot be coincided with the union, but
-     * only one of "f" and "blob" is ever used at a time. */
+     * Discriminates the union/blob field used.  The blob cannot be placed in the union, but only
+     * one of "f" and "blob" may ever be used at a time.
+     */
     Tag tag;
+
     union IntegerParams {
-        /** Enum types */
+        /* Enum types */
         Algorithm algorithm;
         BlockMode blockMode;
         PaddingMode paddingMode;
@@ -587,7 +1152,7 @@
         HardwareAuthenticatorType hardwareAuthenticatorType;
         SecurityLevel hardwareType;
 
-        /** Other types */
+        /* Other types */
         bool boolValue;  // Always true, if a boolean tag is present.
         uint32_t integer;
         uint64_t longInteger;
@@ -597,20 +1162,68 @@
     vec<uint8_t> blob;
 };
 
+/**
+ * KeyCharacteristics defines the attributes of a key, including cryptographic parameters, and usage
+ * restrictions.  It consits of two vectors of KeyParameters, one for "softwareEnforced" attributes
+ * and one for "hardwareEnforced" attributes.
+ *
+ * KeyCharacteristics objects are returned by generateKey, importKey, importWrappedKey and
+ * getKeyCharacteristics.  The IKeymasterDevice secure environment is responsible for allocating the
+ * parameters, all of which are Tags with associated values, to the correct vector.  The
+ * hardwareEnforced vector must contain only those attributes which are enforced by secure hardware.
+ * All others should be in the softwareEnforced vector.  See the definitions of individual Tag enums
+ * for specification of which must be hardware-enforced, which may be software-enforced and which
+ * must never appear in KeyCharacteristics.
+ */
 struct KeyCharacteristics {
     vec<KeyParameter> softwareEnforced;
     vec<KeyParameter> hardwareEnforced;
 };
 
 /**
- * Data used to prove successful authentication.
+ * HardwareAuthToken is used to prove successful user authentication, to unlock the use of a key.
+ *
+ * HardwareAuthTokens are produced by other secure environment applications, notably GateKeeper and
+ * Fingerprint, in response to successful user authentication events.  These tokens are passed to
+ * begin(), update(), and finish() to prove that authentication occurred.  See those methods for
+ * more details.  It is up to the caller to determine which of the generated auth tokens is
+ * appropriate for a given key operation.
  */
 struct HardwareAuthToken {
+    /**
+     * challenge is a value that's used to enable authentication tokens to authorize specific
+     * events.  The primary use case for challenge is to authorize an IKeymasterDevice cryptographic
+     * operation, for keys that require authentication per operation. See begin() for details.
+     */
     uint64_t challenge;
-    uint64_t userId;             // Secure User ID, not Android user ID.
-    uint64_t authenticatorId;    // Secure authenticator ID.
+
+    /**
+     *  userId is the a "secure" user ID.  It is not related to any Android user ID or UID, but is
+     *  created in the Gatekeeper application in the secure environment.
+     */
+    uint64_t userId;
+
+    /**
+     *  authenticatorId is the a "secure" user ID.  It is not related to any Android user ID or UID,
+     *  but is created in an authentication application in the secure environment, such as the
+     *  Fingerprint application.
+     */
+    uint64_t authenticatorId;  // Secure authenticator ID.
+
+    /**
+     * authenticatorType describes the type of authentication that took place, e.g. password or
+     * fingerprint.
+     */
     HardwareAuthenticatorType authenticatorType;
+
+    /**
+     * timestamp indicates when the user authentication took place, in milliseconds since some
+     * starting point (generally the most recent device boot) which all of the applications within
+     * one secure environment must agree upon.  This timestamp is used to determine whether or not
+     * the authentication occurred recently enough to unlock a key (see Tag::AUTH_TIMEOUT).
+     */
     Timestamp timestamp;
+
     /**
      * MACs are computed with a backward-compatible method, used by Keymaster 3.0, Gatekeeper 1.0
      * and Fingerprint 1.0, as well as pre-treble HALs.
@@ -623,7 +1236,8 @@
      * where ``||'' represents concatenation, the leading zero is a single byte, and all integers
      * are represented as unsigned values, the full width of the type.  The challenge, userId and
      * authenticatorId values are in machine order, but authenticatorType and timestamp are in
-     * network order.  This odd construction is compatible with the hw_auth_token_t structure,
+     * network order (big-endian).  This odd construction is compatible with the hw_auth_token_t
+     * structure,
      *
      * Note that mac is a vec rather than an array, not because it's actually variable-length but
      * because it could be empty.  As documented in the IKeymasterDevice::begin,
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index d07e799..724e0ee 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -55,5 +55,6 @@
         }
     });
 
-    return 0;
+    // b/77934844: Avoid running static destructors.
+    _exit(1);
 }
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 42f9947..725e290 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -86,6 +86,11 @@
                                this->omxNode = _nl;
                            })
                         .isOk());
+        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
+            disableTest = true;
+            std::cout << "[   WARN   ] Test Disabled, component not present\n";
+            return;
+        }
         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
index d5f1f2d..0ebab88 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
@@ -86,6 +86,11 @@
                                this->omxNode = _nl;
                            })
                         .isOk());
+        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
+            disableTest = true;
+            std::cout << "[   WARN   ] Test Disabled, component not present\n";
+            return;
+        }
         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
diff --git a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
index 9500094..e7ae083 100644
--- a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.cpp
@@ -94,6 +94,51 @@
             param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
             param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
             break;
+        case 3:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            break;
+        case 4:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelLR;
+            param.eChannelMapping[3] = OMX_AUDIO_ChannelRR;
+            break;
+        case 5:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            param.eChannelMapping[3] = OMX_AUDIO_ChannelLR;
+            param.eChannelMapping[4] = OMX_AUDIO_ChannelRR;
+            break;
+        case 6:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            param.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
+            param.eChannelMapping[4] = OMX_AUDIO_ChannelLR;
+            param.eChannelMapping[5] = OMX_AUDIO_ChannelRR;
+            break;
+        case 7:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            param.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
+            param.eChannelMapping[4] = OMX_AUDIO_ChannelLR;
+            param.eChannelMapping[5] = OMX_AUDIO_ChannelRR;
+            param.eChannelMapping[6] = OMX_AUDIO_ChannelCS;
+            break;
+        case 8:
+            param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            param.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            param.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
+            param.eChannelMapping[4] = OMX_AUDIO_ChannelLR;
+            param.eChannelMapping[5] = OMX_AUDIO_ChannelRR;
+            param.eChannelMapping[6] = OMX_AUDIO_ChannelLS;
+            param.eChannelMapping[7] = OMX_AUDIO_ChannelRS;
+            break;
         default:
             EXPECT_TRUE(false);
     }
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index f7c8433..7750a12 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -80,6 +80,11 @@
                                this->omxNode = _nl;
                            })
                         .isOk());
+        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
+            disableTest = true;
+            std::cout << "[   WARN   ] Test Disabled, component not present\n";
+            return;
+        }
         ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index 40e76c9..1db9f75 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -87,6 +87,11 @@
                                this->omxNode = _nl;
                            })
                         .isOk());
+        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
+            disableTest = true;
+            std::cout << "[   WARN   ] Test Disabled, component not present\n";
+            return;
+        }
         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 2056d9e..a740a80 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -100,6 +100,11 @@
                                this->omxNode = _nl;
                            })
                         .isOk());
+        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
+            disableTest = true;
+            std::cout << "[   WARN   ] Test Disabled, component not present\n";
+            return;
+        }
         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
         ASSERT_NE(omxNode, nullptr);
         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
diff --git a/radio/1.1/ISap.hal b/radio/1.1/ISap.hal
index edcf176..0cabccc 100644
--- a/radio/1.1/ISap.hal
+++ b/radio/1.1/ISap.hal
@@ -18,8 +18,7 @@
 
 import @1.0::ISap;
 
-interface ISap extends @1.0::ISap {
-    /**
-     * Empty top level interface.
-     */
-};
+/**
+ * Empty top level interface.
+ */
+interface ISap extends @1.0::ISap {};
diff --git a/radio/1.2/ISap.hal b/radio/1.2/ISap.hal
index 757027c..65f9b84 100644
--- a/radio/1.2/ISap.hal
+++ b/radio/1.2/ISap.hal
@@ -18,8 +18,7 @@
 
 import @1.1::ISap;
 
-interface ISap extends @1.1::ISap {
-    /**
-     * Empty top level interface.
-     */
-};
+/**
+ * Empty top level interface.
+ */
+interface ISap extends @1.1::ISap {};
diff --git a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
index 4eef4ec..03b6406 100644
--- a/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
+++ b/tetheroffload/control/1.0/vts/functional/VtsHalTetheroffloadControlV1_0TargetTest.cpp
@@ -26,7 +26,6 @@
 #include <android/hardware/tetheroffload/control/1.0/types.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netlink.h>
-#include <log/log.h>
 #include <net/if.h>
 #include <sys/socket.h>
 #include <unistd.h>
@@ -57,20 +56,16 @@
 constexpr const char* TEST_IFACE = "rmnet_data0";
 
 // We use #defines here so as to get local lamba captures and error message line numbers
-#define ASSERT_TRUE_CALLBACK                            \
-    [&](bool success, std::string errMsg) {             \
-        if (!success) {                                 \
-            ALOGI("Error message: %s", errMsg.c_str()); \
-        }                                               \
-        ASSERT_TRUE(success);                           \
+#define ASSERT_TRUE_CALLBACK                                                    \
+    [&](bool success, std::string errMsg) {                                     \
+        std::string msg = StringPrintf("unexpected error: %s", errMsg.c_str()); \
+        ASSERT_TRUE(success) << msg;                                            \
     }
 
-#define ASSERT_FALSE_CALLBACK                           \
-    [&](bool success, std::string errMsg) {             \
-        if (!success) {                                 \
-            ALOGI("Error message: %s", errMsg.c_str()); \
-        }                                               \
-        ASSERT_FALSE(success);                          \
+#define ASSERT_FALSE_CALLBACK                                                 \
+    [&](bool success, std::string errMsg) {                                   \
+        std::string msg = StringPrintf("expected error: %s", errMsg.c_str()); \
+        ASSERT_FALSE(success) << msg;                                         \
     }
 
 #define ASSERT_ZERO_BYTES_CALLBACK            \
@@ -188,10 +183,9 @@
 
     void initOffload(const bool expected_result) {
         auto init_cb = [&](bool success, std::string errMsg) {
-            if (!success) {
-                ALOGI("Error message: %s", errMsg.c_str());
-            }
-            ASSERT_EQ(expected_result, success);
+            std::string msg = StringPrintf("Unexpectedly %s to init offload: %s",
+                                           success ? "succeeded" : "failed", errMsg.c_str());
+            ASSERT_EQ(expected_result, success) << msg;
         };
         const Return<void> ret = control->initOffload(control_cb, init_cb);
         ASSERT_TRUE(ret.isOk());
@@ -204,15 +198,12 @@
 
     void stopOffload(const ExpectBoolean value) {
         auto cb = [&](bool success, const hidl_string& errMsg) {
-            if (!success) {
-                ALOGI("Error message: %s", errMsg.c_str());
-            }
             switch (value) {
                 case ExpectBoolean::False:
-                    ASSERT_EQ(false, success);
+                    ASSERT_EQ(false, success) << "Unexpectedly able to stop offload: " << errMsg;
                     break;
                 case ExpectBoolean::True:
-                    ASSERT_EQ(true, success);
+                    ASSERT_EQ(true, success) << "Unexpectedly failed to stop offload: " << errMsg;
                     break;
                 case ExpectBoolean::Ignored:
                     break;
@@ -289,8 +280,11 @@
     if (!interfaceIsUp(TEST_IFACE)) {
         return;
     }
-    stopOffload(ExpectBoolean::True);  // balance out initOffload(true)
+    SCOPED_TRACE("Expecting stopOffload to succeed");
+    stopOffload(ExpectBoolean::Ignored);  // balance out initOffload(true)
+    SCOPED_TRACE("Expecting stopOffload to fail the first time");
     stopOffload(ExpectBoolean::False);
+    SCOPED_TRACE("Expecting stopOffload to fail the second time");
     stopOffload(ExpectBoolean::False);
 }
 
diff --git a/tv/cec/1.0/types.hal b/tv/cec/1.0/types.hal
index a1853a3..c734c4d 100644
--- a/tv/cec/1.0/types.hal
+++ b/tv/cec/1.0/types.hal
@@ -193,7 +193,7 @@
      */
     SYSTEM_CEC_CONTROL = 3,
 
-    /** Option 4 not used */
+    /* Option 4 not used */
 };
 
 struct CecMessage {
diff --git a/usb/1.1/IUsb.hal b/usb/1.1/IUsb.hal
index 9cedea0..606928b 100644
--- a/usb/1.1/IUsb.hal
+++ b/usb/1.1/IUsb.hal
@@ -18,11 +18,9 @@
 
 import android.hardware.usb@1.0;
 
-interface IUsb extends android.hardware.usb@1.0::IUsb {
-    /**
-     * The setCallback function in V1_0 is used to register the V1_1
-     * IUsbCallback object as well. The implementation can use the
-     * castFrom method to cast the IUsbCallback object.
-     */
-};
-
+/*
+ * The setCallback function in V1_0 is used to register the V1_1
+ * IUsbCallback object as well. The implementation can use the
+ * castFrom method to cast the IUsbCallback object.
+ */
+interface IUsb extends android.hardware.usb@1.0::IUsb {};
diff --git a/wifi/1.0/IWifiP2pIface.hal b/wifi/1.0/IWifiP2pIface.hal
index 243748f..b908591 100644
--- a/wifi/1.0/IWifiP2pIface.hal
+++ b/wifi/1.0/IWifiP2pIface.hal
@@ -21,6 +21,4 @@
 /**
  * Interface used to represent a single NAN iface.
  */
-interface IWifiP2pIface extends IWifiIface {
-  /** TODO(rpius): Add methods to the interface. */
-};
+interface IWifiP2pIface extends IWifiIface {};
diff --git a/wifi/1.0/README-NAN.md b/wifi/1.0/README-NAN.md
index f4b3320..645c9f9 100644
--- a/wifi/1.0/README-NAN.md
+++ b/wifi/1.0/README-NAN.md
@@ -14,7 +14,7 @@
 
 # Wi-Fi Aware (NAN) HAL API Usage
 
-The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/\<version\>/</i>):
+The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/1.0/</i>):
 
 * IWifiNanIface.hal
 * IWifiNanIfaceEventCallback.hal
@@ -23,7 +23,7 @@
 The Wi-Fi Aware (NAN) HAL API surface is very large - only a subset is used from the framework.
 
 Understanding of the HAL API subset which is actively used by the Android framework can be deduced
-by reviewing framework code, specifically (<i>frameworks/opt/net/wif/</i>):
+by reviewing framework code, specifically (<i>frameworks/opt/net/wifi/</i>):
 
 * WifiAwareNativeApi.java
 * WifiAwareNativeCallback.java
@@ -41,7 +41,7 @@
 
 Format:
 * Hard-coded values are in <b>bold</b>, e.g. <b>true</b> or <b>5</b>
-* Assigned but not fixed value are specified using the <i>variable</i> keyword, possibly with some
+* Assigned but not fixed values are specified using the <i>variable</i> keyword, possibly with some
 details/constraints
 * Unassigned values are specified using the <i>N/A</i> keyword. Unassigned usually means initialized
 to 0.
diff --git a/wifi/1.2/README-NAN.md b/wifi/1.2/README-NAN.md
new file mode 100644
index 0000000..00b9169
--- /dev/null
+++ b/wifi/1.2/README-NAN.md
@@ -0,0 +1,231 @@
+Copyright 2018 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.
+
+# Wi-Fi Aware (NAN) HAL API Usage
+
+The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/1.0/</i> and
+<i>hardware/interfaces/wifi/1.2/</i>):
+
+* IWifiNanIface.hal
+* IWifiNanIfaceEventCallback.hal
+* types.hal (structure definitions)
+
+Note that the <i>1.2</i> HAL is supplemental to the <i>1.0</i> HAL - not a replacement.
+
+The Wi-Fi Aware (NAN) HAL API surface is very large - only a subset is used from the framework.
+
+Understanding of the HAL API subset which is actively used by the Android framework can be deduced
+by reviewing framework code, specifically (<i>frameworks/opt/net/wifi/</i>):
+
+* WifiAwareNativeApi.java
+* WifiAwareNativeCallback.java
+
+The above framework files determine the API usage - and should be consulted as the authoritative
+reference. Please consult the primary HAL file for documentation - they will not be replicated
+in this document. APIs which are in the HAL but are not listed in this README file are not used by
+the framework.
+
+Note: the HAL API is translated to the legacy HAL API (<i>wifi_nan.h</i>). This README file covers
+the new HAL API only. To understand the mapping between new and legacy HALs please consult
+<i>hardware/interfaces/wifi/\<version\>/default/hidl_struct_util.cpp</i>.
+
+## IWifiNanIface
+
+Format:
+* Hard-coded values are in <b>bold</b>, e.g. <b>true</b> or <b>5</b>
+* Assigned but not fixed values are specified using the <i>variable</i> keyword, possibly with some
+details/constraints
+* Unassigned values are specified using the <i>N/A</i> keyword. Unassigned usually means initialized
+to 0.
+
+APIs:
+
+* registerEventCallback_1_2(IWifiNanIfaceEventCallback_1_2 callback)
+* getCapabilitiesRequest
+* enableRequest_1_2
+  * NanEnableRequest
+    * bool[2] operateInBand
+        * Index [NanBandIndex.NAN_BAND_24GHZ] = <b>true</b>
+        * Index [NanBandIndex.NAN_BAND_5GHZ] = <i>variable</i>
+    * uint8_t hopCountMax = <b>2</b>
+    * NanConfigRequest configParams
+        * uint8_t masterPref = <i>variable</i>
+        * bool disableDiscoveryAddressChangeIndication = <i>variable</i>
+        * bool disableStartedClusterIndication = <i>variable</i>
+        * bool disableJoinedClusterIndication = <i>variable</i>
+        * bool includePublishServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfPublishServiceIdsInBeacon = <b>0</b>
+        * bool includeSubscribeServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfSubscribeServiceIdsInBeacon = <b>0</b>
+        * uint16_t rssiWindowSize = <b>8</b>
+        * uint32_t macAddressRandomizationIntervalSec = <i>variable</i>
+            * Normal run-time: set to <b>1800</b> (30 minutes)
+            * Tests: set to <b>120</b> (2 minutes)
+        * NanBandSpecificConfig[2] bandSpecificConfig
+            * Index [NanBandIndex.NAN_BAND_24GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>70</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+            * Index [NanBandIndex.NAN_BAND_5GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>75</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+    * NanDebugConfig debugConfigs
+        * bool validClusterIdVals = <b>true</b>
+        * uint16_t clusterIdBottomRangeVal = <i>variable</i>
+        * uint16_t clusterIdTopRangeVal = <i>variable</i>
+        * bool validIntfAddrVal = <b>false</b>
+        * MacAddress intfAddrVal = <i>N/A</i>
+        * bool validOuiVal = <b>false</b>
+        * uint32_t ouiVal = <i>N/A</i>
+        * bool validRandomFactorForceVal = <b>false</b>
+        * uint8_t randomFactorForceVal = <i>N/A</i>
+        * bool validHopCountForceVal = <b>false</b>
+        * uint8_t hopCountForceVal = <i>N/A</i>
+        * bool validDiscoveryChannelVal = <b>false</b>
+        * WifiChannelInMhz[2] discoveryChannelMhzVal = <i>N/A</i>
+        * bool validUseBeaconsInBandVal = <b>false</b>
+        * bool[2] useBeaconsInBandVal = <i>N/A</i>
+        * bool validUseSdfInBandVal = <b>false</b>
+        * bool[2] useSdfInBandVal = <i>N/A</i>
+  * NanConfigRequestSupplemental
+    * uint32_t discoveryBeaconIntervalMs = <b>0</b>
+    * uint32_t numberOfSpatialStreamsInDiscovery = <b>0</b>
+    * bool enableDiscoveryWindowEarlyTermination = <b>false</b>
+    * bool enableRanging = <b>true</b>
+* configRequest_1_2
+    * NanConfigRequest: same as for <i>enableRequest_1_2</i>
+* disableRequest
+* startPublishRequest
+    * NanPublishRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * uint8_t sessionId = <i>variable</i>
+            * uint16_t ttlSec = <i>variable</i>
+            * uint16_t discoveryWindowPeriod = <b>1</b>
+            * uint8_t discoveryCount = <b>0</b>
+            * vec<uint8_t> serviceName = <i>variable</i>
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_NEVER</b>
+            * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+            * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+            e vec<uint8_t> rxMatchFilter = <i>variable</i>
+            * vec<uint8_t> txMatchFilter = <i>variable</i>
+            * bool useRssiThreshold = <b>false</b>
+            * bool disableDiscoveryTerminationIndication = <i>variable</i>
+            * bool disableMatchExpirationIndication = <b>true</b>
+            * bool disableFollowupReceivedIndication = <b>false</b>
+            * NanDataPathSecurityConfig securityConfig = <b>NanDataPathSecurityType.OPEN</b>
+            * bool rangingRequired = <b>false</b>
+            * uint32_t rangingIntervalMsec = <i>N/A</i>
+            * bitfield<NanRangingIndication> configRangingIndications = <i>N/A</i>
+            * uint16_t distanceIngressCm = <i>N/A</i>
+            * uint16_t distanceEgressCm = <i>N/A</i>
+        * NanPublishType publishType = <i>variable</i>
+        * NanTxType txType = <b>NanTxType.BROADCAST</b>
+        * bool autoAcceptDataPathRequests = <b>false</b>
+* stopPublishRequest
+* startSubscribeRequest
+    * NanSubscribeRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * Mostly same as <i>publish</i> above except:
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_ONCE</b>
+        * NanSubscribeType subscribeType = <i>variable</i>
+        * NanSrfType srfType = <i>N/A</i>
+        * bool srfRespondIfInAddressSet = <i>N/A</i>
+        * bool shouldUseSrf = <i>N/A</i>
+        * bool isSsiRequiredForMatch = <i>N/A</i>
+        * vec<MacAddress> intfAddr = <i>N/A</i>
+* stopSubscribeRequest
+* transmitFollowupRequest
+    * NanTransmitFollowupRequest
+        * uint8_t discoverySessionId = <i>variable</i>
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress addr = <i>variable</i>
+        * bool isHighPriority = <b>false</b>
+        * bool shouldUseDiscoveryWindow = <b>true</b>
+        * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+        * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+        * bool disableFollowupResultIndication = <b>false</b>
+* createDataInterfaceRequest
+* deleteDataInterfaceRequest
+* initiateDataPathRequest
+    * NanInitiateDataPathRequest
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress peerDiscMacAddr = <i>variable</i>
+        * NanDataPathChannelCfg channelRequestType =
+        <i>NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED</i>
+        * WifiChannelInMhz channel = <b>2437</b> (note that should be ignored though -
+        CHANNEL_NOT_REQUESTED!)
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* respondToDataPathIndicationRequest
+    * NanRespondToDataPathIndicationRequest
+        * bool acceptRequest = <i>variable</i>
+        * uint32_t ndpInstanceId = <i>variable</i>
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* terminateDataPathRequest
+
+## IWifiNanIfaceEventCallback_1_2
+
+Format:
+* Parameters whose values are <i>ignored</i> will be flagged, otherwise the parameter value is used
+by the framework.
+
+API:
+
+* notifyXxxResponse: all callbacks are used by framework
+* eventClusterEvent
+* eventDisabled
+* eventPublishTerminated
+* eventSubscribeTerminated
+* eventMatch
+    * NanMatchInd (all parameters are used except those listed below)
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+        * bool matchOccuredInBeaconFlag: <i>ignored</i>
+        * bool outOfResourceFlag: <i>ignored</i>
+        * uint8_t rssiValue: <i>ignored</i>
+        * NanCipherSuiteType peerCipherType: <i>ignored</i>
+        * bool peerRequiresSecurityEnabledInNdp: <i>ignored</i>
+        * bool peerRequiresRanging: <i>ignored</i>
+        * uint32_t rangingMeasurementInCm: <i>ignored</i>
+        * bitfield<NanRangingIndication> rangingIndicationType: <i>ignored</i>
+* eventMatchExpired: <i>ignored</i>
+* eventFollowupReceived
+    * NanFollowupReceivedInd (all parameters are used except those listed below)
+        * bool receivedInFaw: <i>ignored</i>
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+* eventTransmitFollowup
+* eventDataPathRequest
+    * NanDataPathRequestInd (all parameters are used except those listed below)
+        * bool securityRequired: <i>ignored</i>
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathConfirm
+    * NanDataPathConfirmInd (all parameters are used except those listed below)
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathScheduleUpdate
+    * NanDataPathScheduleUpdateInd
+* eventDataPathTerminated
+
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
index 978cf63..3919690 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.2/default/Android.mk
@@ -27,6 +27,9 @@
 ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
 LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DUAL_INTERFACE
 endif
+ifdef WIFI_HIDL_FEATURE_DISABLE_AP
+LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP
+endif
 LOCAL_SRC_FILES := \
     hidl_struct_util.cpp \
     hidl_sync_util.cpp \
diff --git a/wifi/1.2/default/OWNERS b/wifi/1.2/default/OWNERS
index 2878acc..8bfb148 100644
--- a/wifi/1.2/default/OWNERS
+++ b/wifi/1.2/default/OWNERS
@@ -1,2 +1,2 @@
 rpius@google.com
-quiche@google.com
+etancohen@google.com
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.h b/wifi/1.2/default/tests/mock_wifi_feature_flags.h
index 8cf1d4b..2a36dd5 100644
--- a/wifi/1.2/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.2/default/tests/mock_wifi_feature_flags.h
@@ -34,6 +34,7 @@
 
     MOCK_METHOD0(isAwareSupported, bool());
     MOCK_METHOD0(isDualInterfaceSupported, bool());
+    MOCK_METHOD0(isApDisabled, bool());
 };
 
 }  // namespace feature_flags
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
index 3928c9a..8722d0a 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -48,6 +48,8 @@
             .WillRepeatedly(testing::Return(false));
         EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
             .WillRepeatedly(testing::Return(false));
+        EXPECT_CALL(*feature_flags_, isApDisabled())
+            .WillRepeatedly(testing::Return(false));
     }
 
     void setupV1_AwareIfaceCombination() {
@@ -55,6 +57,17 @@
             .WillRepeatedly(testing::Return(true));
         EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
             .WillRepeatedly(testing::Return(false));
+        EXPECT_CALL(*feature_flags_, isApDisabled())
+            .WillRepeatedly(testing::Return(false));
+    }
+
+    void setupV1_AwareDisabledApIfaceCombination() {
+        EXPECT_CALL(*feature_flags_, isAwareSupported())
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
+            .WillRepeatedly(testing::Return(false));
+        EXPECT_CALL(*feature_flags_, isApDisabled())
+            .WillRepeatedly(testing::Return(true));
     }
 
     void setupV2_AwareIfaceCombination() {
@@ -62,6 +75,17 @@
             .WillRepeatedly(testing::Return(true));
         EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
             .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isApDisabled())
+            .WillRepeatedly(testing::Return(false));
+    }
+
+    void setupV2_AwareDisabledApIfaceCombination() {
+        EXPECT_CALL(*feature_flags_, isAwareSupported())
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isApDisabled())
+            .WillRepeatedly(testing::Return(true));
     }
 
     void assertNumberOfModes(uint32_t num_modes) {
@@ -515,6 +539,39 @@
     ASSERT_FALSE(ap_iface_name.empty());
     ASSERT_NE(sta_iface_name, ap_iface_name);
 }
+
+////////// V1 Iface Combinations when AP creation is disabled //////////
+class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
+ public:
+  void SetUp() override {
+    setupV1_AwareDisabledApIfaceCombination();
+    WifiChipTest::SetUp();
+  }
+};
+
+TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest,
+       StaMode_CreateSta_ShouldSucceed) {
+  findModeAndConfigureForIfaceType(IfaceType::STA);
+  ASSERT_FALSE(createIface(IfaceType::STA).empty());
+  ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+////////// V2 Iface Combinations when AP creation is disabled //////////
+class WifiChipV2_AwareDisabledApIfaceCombinationTest: public WifiChipTest {
+ public:
+  void SetUp() override {
+    setupV2_AwareDisabledApIfaceCombination();
+    WifiChipTest::SetUp();
+  }
+};
+
+TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest,
+       CreateSta_ShouldSucceed) {
+  findModeAndConfigureForIfaceType(IfaceType::STA);
+  ASSERT_FALSE(createIface(IfaceType::STA).empty());
+  ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index ab96ef1..3bd0557 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -1211,10 +1211,17 @@
             {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
         const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
             {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
-        const IWifiChip::ChipMode chip_mode = {
+        if (feature_flags_.lock()->isApDisabled()) {
+          const IWifiChip::ChipMode chip_mode = {
+              kV2ChipModeId,
+              {chip_iface_combination_2}};
+          modes_ = {chip_mode};
+        } else {
+          const IWifiChip::ChipMode chip_mode = {
             kV2ChipModeId,
             {chip_iface_combination_1, chip_iface_combination_2}};
-        modes_ = {chip_mode};
+          modes_ = {chip_mode};
+        }
     } else {
         // V1 Iface combinations for Mode Id = 0. (STA Mode)
         const IWifiChip::ChipIfaceCombinationLimit
@@ -1238,7 +1245,11 @@
             {ap_chip_iface_combination_limit}};
         const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
                                                   {ap_chip_iface_combination}};
-        modes_ = {sta_chip_mode, ap_chip_mode};
+        if (feature_flags_.lock()->isApDisabled()) {
+          modes_ = {sta_chip_mode};
+        } else {
+          modes_ = {sta_chip_mode, ap_chip_mode};
+        }
     }
 }
 
diff --git a/wifi/1.2/default/wifi_feature_flags.cpp b/wifi/1.2/default/wifi_feature_flags.cpp
index 554d4d5..778944d 100644
--- a/wifi/1.2/default/wifi_feature_flags.cpp
+++ b/wifi/1.2/default/wifi_feature_flags.cpp
@@ -27,6 +27,12 @@
 #else
 static const bool wifiHidlFeatureDualInterface = false;
 #endif  // WIFI_HIDL_FEATURE_DUAL_INTERFACE
+#ifdef WIFI_HIDL_FEATURE_DISABLE_AP
+static const bool wifiHidlFeatureDisableAp = true;
+#else
+static const bool wifiHidlFeatureDisableAp = false;
+#endif  // WIFI_HIDL_FEATURE_DISABLE_AP
+
 }  // namespace
 
 namespace android {
@@ -41,6 +47,9 @@
 bool WifiFeatureFlags::isDualInterfaceSupported() {
     return wifiHidlFeatureDualInterface;
 }
+bool WifiFeatureFlags::isApDisabled() {
+  return wifiHidlFeatureDisableAp;
+}
 
 }  // namespace feature_flags
 }  // namespace implementation
diff --git a/wifi/1.2/default/wifi_feature_flags.h b/wifi/1.2/default/wifi_feature_flags.h
index dc0c1ff..4a7b2d2 100644
--- a/wifi/1.2/default/wifi_feature_flags.h
+++ b/wifi/1.2/default/wifi_feature_flags.h
@@ -31,6 +31,7 @@
 
     virtual bool isAwareSupported();
     virtual bool isDualInterfaceSupported();
+    virtual bool isApDisabled();
 };
 
 }  // namespace feature_flags